1、编写main.c代码并编译为汇编代码
2、打开main.s文件查看汇编代码
完整汇编代码如下:
.file "main.c" .text .globl g .type g, @function g: .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 movl 8(%ebp), %eax addl $e, %eax popl %ebp .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE0: .size g, .-g .globl f .type f, @function f: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $4, %esp movl 8(%ebp), %eax movl %eax, (%esp) call g leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE1: .size f, .f .globl main .type main, @function main: .LFB2 .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $4, %esp movl $8, (%esp) call f addl $1, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE2: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
3、分析过程中堆栈变化
- pushl %ebp 将esp的值减4,再将ebp的值放入esp指向的地址中
- movl %esp, %ebp 把esp的值赋值给ebp,则esp和ebp指向同一位置
- subl $4, %esp 将esp的值减4
- movl $8, (%esp) 将8放入esp指向的位置
- call f 将esp的地址减4,使栈顶指针指向下一个存储单元,并将eip寄存器中存放的地址放入栈顶指针esp所指的存储单元;然后把函数f起始地址放入eip寄存器中
- pushl %ebp 将esp的值减4,再将ebp的值放入esp指向的地址中
- movl %esp, %ebp 把esp的值传送给ebp,则esp和ebp指向同一位置
- subl $4, %esp 将esp的值减4
- movl 8(%ebp), %eax 将8(%ebp)中的内容存入eax寄存器中
- movl %eax, (%esp) 将eax的值放入esp指向的地址中
- call g 将esp的地址减4,使栈顶指针指向下一个存储单元,并将eip寄存器中存放的地址放入栈顶指针esp所指的存储单元;然后把函数g起始地址放入eip寄存器中
- pushl %ebp 将esp的值减4,再将ebp的值放入esp指向的地址中
- movl %esp, %ebp 把esp的值传送给ebp,两者指向同一位置
- movl 8(%ebp), %eax 将ebp+8后的值存入eax寄存器中
- addl $1, %eax 将eax寄存器中存放的数据加1,得到的结果仍放在eax寄存器中
- popl %ebp 将栈顶指针esp所指存储单元中存放的数据传给栈底指针ebp,使该数据即为栈底指针所代表地址;栈顶指针esp所代表的地址加4,使栈顶指针指向前一个存储单元
- ret g程序返回
- leave 将EBP寄存器的内容复制到ESP寄存器中,以释放分配给该过程的所有堆栈空间。然后,它从堆栈恢复EBP寄存器的旧值
- ret f程序返回
- addl $1, %eax 将eax寄存器中存放的数据加1,得到的结果仍放在eax寄存器中
- leave 将EBP寄存器的内容复制到ESP寄存器中,以释放分配给该过程的所有堆栈空间。然后,它从堆栈恢复EBP寄存器的旧值
- ret main程序返回
计算机中栈顶指针为esp,栈底指针为ebp,eip指向下一条将要执行的指令,eax等寄存器保存计算结果。pushl %eax相当于subl $4, %esp;movl %eax,(%esp)。popl %eax相当于movl (%esp),%eax;addl $4,%esp。call 0x12345相当于pushl %eip;movl $0x12345,%eip。ret相当于popl %eip。leave相当于movl %ebp,%esp;popl %ebp。



