AT&T 汇编控制执行流程及与高级语言的转换

时间:2021-10-03 14:43:43
注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!

一.指令指针

指令指针确定程序中的哪条指令是应该执行的下一条指令。它按顺序的方式处理应用程序中的指令码。
当指令指针在程序指令中移动时,EIP寄存器会递增。

程序不能直接修改指令指针。但是可以利用能够改动指令指针的指令。这些指令称为分支(branch)。


二.无条件分支

1.跳转

jump location
location是要跳转的内存地址。
3种不同类型:短跳转、近跳转、远跳转
这三种类型由当前指令的内存位置和目的点的内存位置之间的距离决定。
当跳转偏移量小于128字节时使用短跳转;
在分段内存模式下,当跳转到另一个段时使用远跳转;

其他都使用近跳转。


2.调用

调用和跳转类似,但是它保存发生跳转的位置,并且它具有在需要的时候返回这个地址的能力。
用函数可以写划分区域的代码,可以把不同功能分割为不同的文本段落。
call address
address引用内存中的标签,它被转化为函数中的第一条指令的内存地址。
执行call指令时,它把EIP寄存器的值存放到堆栈中,然后修改EIP寄存器以指向被调用的函数地址。当被调用的函数完成后,它从堆栈获得过去的EIP值,并把控制权返回给原始程序。
当执行call指令时,返回地址被压入栈中。当被调用的函数开始时,它必须在某个位置存储ESP寄存器,在RET指令前,从这个存储位置恢复ESP。EBP经常用作堆栈的基指针,因此,当函数开始时,通常把ESP复制到EBP。

3.中断

中断是处理器“中断”当前指令码路径,并切换到不同路径的方式。有软件中断、硬件中断两种形式。
硬件设备生成硬件中断。使用硬件中断发出信号,表示硬件层发生的事件(比如I/O端口按收到输入信号时)。
程序生成软件中断,它们是把控制交给另一个程序的信号。
当一个程序被中断调用时,发出调用的程序暂停,被调用的程序接替它运行。指令指针被转移到被调用的程序,并且从被调用的程序内继续执行。被调用程序完成时,它可以把控制权返回给发出调用的程序(使用中断返回指令)

软件中断是操作系统提供的,使应用程序可以使用操作系统内的函数,并且,在某些情况下,甚至可以接触底层的BIOS系统。


三.条件分支

1.条件跳转

xx是一到三个字符的条件代码,address是要跳到的地址。
-----------------------------------------------
指令  描述
-------------------------------------
JA 大于
JAE 大于等于
JB 小于
JBE 小于等于
JE 相等
JO 溢出
JZ 为0
-----------------------------------------------

2.比较指令

cmp operand1, operand2
cmp指令把第二个数和第一个数进行比较,幕后,对两个操作数做减法(operand2-operand1),该指令不会修改这两个数的值,但做减法就会设置EFLAGS寄存器。
例如:
cmp %eax, %ebx
jge greater


四.循环

循环指令使用ECX作为计数器并且随着循环指令的执行自动递减它的值。
---------------------------------------------------------
指令 描述
------------------------------------------------------
LOOP 循环直到ECX寄存器为0
LOOPE/LOOPZ 循环直到ECX寄存器为0,或没有设置ZF标志
LOOPNE/LOOPNZ 循环直到ECX寄存器为0,或者设置了ZF标志
---------------------------------------------------------
示例,求从1加到100的和:

# sum = 1+2+3+...+100

.section .data
output:
	.asciz	"1+2+3+...+100 = %d\n"

.section .text
.global	_start

_start:
	nop
	movl	$100,	%ecx
	xorl	%eax,	%eax

add_loop:
	addl	%ecx,	%eax
	loop	add_loop

	pushl	%eax
	pushl	$output
	call	printf

	add		$8,		%esp
	movl	$1,		%eax
	movl	$0,		%ebx
	int		$0x80
result:
liury@liury-laptop:~/program/asm/control_exec_flow/sum100$ make
as -o sum100.o sum100.s
ld -dynamic-linker /lib/ld-linux.so.2 -lc -o sum100 sum100.o
liury@liury-laptop:~/program/asm/control_exec_flow/sum100$ ls
makefile  sum100  sum100.o  sum100.s
liury@liury-laptop:~/program/asm/control_exec_flow/sum100$ ./sum100 
1+2+3+...+100 = 5050

五.模仿高级语言

1.if-else

if (test-expr)
	then-statement
else
	else-statement
翻译成goto:
	t = test-expr
	if (!t)
		goto false
	then-statement
	goto done;
false:
	else-statement
done:
	
示例:
原始C代码
int absdiff(int x, int y)
{
	if (x < y)
		return y-x;
	else
		return x-y;
}
goto版
int goto_diff(int x, int y)
{
	int result;
	if ( x >= y)
		goto x_ge_y;
	result = y-x;
	goto done;
x_ge_y:
	result= x-y;
done:
	return result;
}
汇编代码:
# x at %ebp+8, y at %ebp+12
	movl	8(%ebp),	%edx
	movl	12(%ebp),	%eax
	cmpl	%eax,		%edx
	jge		.L2
	subl	%edx,		%eax
	jmp		.L3
.L2:
	subl	%eax,		%edx
	movl	%edx,		%eax
.L3:

2.do-while

do
	body-statement
	while (test-expr)

转为goto:
loop:
	body-statement
	t = test-expr;
	if (t)
		goto loop;

示例
C代码:
int fact_do(int n)
{
	int result = 1;
	do {
		result *= n;
		n = n-1;
	} while (n > 1);

	return result;
}
汇编代码:
# Argument: n at %ebp+8
# Registers: n in %edx, result in %eax
	movl	8(%ebp),	%edx
	movl	$1,			%eax
.L2:
	imull	%edx,		%eax
	subl	$1,			%edx
	cmpl	$1,			%edx
	jg		.L2

3.while

while (test-expr)
	body-statement

do-while版:
if (!test-expr)
	goto done;
do
	body-statement
	while (test-expr);
done:

goto版:
	t = test-expr
	if (!t)
		goto done;
loop:
	body-statement
	t = test-expr
	if (t)
		goto loop
done:

示例:
C语言:
int fact_while(int n)
{
	int result = 1;
	while (n > 1) {
		result *= n;
		n = n-1;
	}

	return result;
}

goto版:
int fact_while_goto(int n)
{
	int result = 1;
	if (n <= 1)
		goto done;
loop:
	result *= n;
	n = n-1;
	if (n > 1)
		goto loop;
done:
	return result;
}

汇编版:
# Argument: n at %ebp+8
# Register: n in %edx, result in %eax
	movl	8(%ebp),	%edx
	movl	$1,			%eax
	movl	$1,			%edx
	jle		.L7
.L10:
	imull	%edx,		%eax
	subl	$1,			%edx
	cmpl	$1,			%edx
	jg		.L10
.L7:

4.for

for (init-expr; test-expr; update-expr)
	body-statement

转换成while循环:
init-expr;
while (test-expr) {
	body-statement;
	update-expr;
}

转换成do-while循环:
init-expr;
if (!test-expr)
	goto done;
do {
	body-statement;
	update-expr;
} while (test-expr);
done:

转换成go-to:
	init-expr;
	t = test-expr;
	if (!t)
		goto done;
loop:
	body-statement;
	update-expr;
	t = test-expr;
	if (t)
		goto loop;
done:

示例:
C语言:
int fact_for(int n)
{
	int i;
	int result = 1;
	for (i = 2; i <= n; i++)
		result *= i;
	return result;
}

goto版:
int fact_for_goto(int n)
{
	int i = 2;
	int result = 1;
	if (! (i <= n))
		goto done;
loop:
	result *= i;
	i++;
	if (i <= n)
		goto loop;
done:
	return result;
}

汇编版:
# Argument: n at %ebp+8
# Register: n in %ecx, i in %edx, result in %eax
	movl	8(%ebp),	%ecx
	movl	$2,			%edx
	movl	$1,			%eax
	cmpl	$1,			%ecx
	jle		.L14
.L17:
	imull	%edx,		%eax
	addl	$1,			%edx
	cmpl	%edx,		%ecx
	jge		.L17
.L14: