标签:
几个重要的寄存器
eip - 用于存放当前所执行的指令地址
esp - 栈(顶)指针寄存器
ebp - 基址(栈底)指针寄存器
简单的C程序
1 int g(int x) 2 { 3 return x + 10; 4 } 5 6 int f(int x) 7 { 8 return g(x); 9 } 10 11 int main(void) 12 { 13 return f(7) + 5; 14 }
汇编代码分析
1 g: 2 pushl %ebp 3 movl %esp, %ebp 4 ;下面两条指令的含义是:将传入的参数7和10相加并保存在寄存器eax中 5 movl 8(%ebp), %eax 6 addl $10, %eax 7 popl %ebp 8 ret 9 f: 10 pushl %ebp 11 movl %esp, %ebp 12 subl $4, %esp 13 ;下面两句指令的含义是:将参数7保存到函数f的栈帧中 14 movl 8(%ebp), %eax 15 movl %eax, (%esp) 16 call g 17 leave 18 ret 19 20 main: 21 pushl %ebp 22 movl %esp, %ebp 23 subl $4, %esp 24 movl $7, (%esp) 25 call f 26 addl $5, %eax 27 leave 28 ret
针对上面的汇编代码,我们有如下的图例分析
说明:
在执行call指令时,eip的所指向的指令是addl $5, %eax
call 指令等价于,将eip中的地址压栈保存,然后将函数f第一条指令(pushl %ebp)的地址放到eip中。
pushl %eax ;将eax中的值压栈保存
<=>
subl $4, %esp
movl %eax, (%esp)
popl %eax
<=>
movl (%esp), %eax
addl $4, %esp
call 0x12345
<=>
pushl %eip(*)
movl $0x12345, %eip(*)
ret ; 将栈顶值弹出放到eip中,此时eip中的值便是将要执行的指令的地址
<=>
popl %eip(*)
leave ;恢复所调用程序的堆栈
< =>
movl %ebp, %esp
popl %ebp
enter ;与leave指令的操作相反
<=>
pushl %ebp
movl %esp, %ebp
标签:
原文地址:http://www.cnblogs.com/zhazhaming/p/4322486.html