一.指令指针
指令指针确定程序中的哪条指令是应该执行的下一条指令。它按顺序的方式处理应用程序中的指令码。当指令指针在程序指令中移动时,EIP寄存器会递增。
程序不能直接修改指令指针。但是可以利用能够改动指令指针的指令。这些指令称为分支(branch)。
二.无条件分支
1.跳转
jump locationlocation是要跳转的内存地址。
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, operand2cmp指令把第二个数和第一个数进行比较,幕后,对两个操作数做减法(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+...+100result:
.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
loopadd_loop
pushl%eax
pushl$output
callprintf
add$8,%esp
movl$1,%eax
movl$0,%ebx
int$0x80
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
movl8(%ebp),%edx
movl12(%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
movl8(%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
movl8(%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
movl8(%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: