发在别处的文章,搬过来了。
首先编写一个简单的c程序:
int g(int x) {
return x + 6;
}
int f(int x) {
return g(x);
}
int main() {
return f(81) + 1;
}
gcc -S -o main.s main.c -m32
生成的汇编代码中有很多"."开头的行,都是链接信息,我们把这些行删除,以免影响阅读。最后剩下的汇编代码为:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $6, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $81, (%esp)
call f
addl $1, %eax
leave
ret
- EBP - 存放栈的基地址
- ESP - 存放栈的顶地址
- EIP - 存放下一条指令的地址(这里我们为了描述简单用代码的行号表示)
- EAX - 存放数值(后面会看到,它通常存放函数的返回值)
通过分析这个小程序的汇编代码,我们了解了程序执行的基本逻辑:
- 也就是通过堆栈的操作来执行函数的跳转,以及返回。
- 同时在每个函数执行期间,函数内部的变量都在栈上进行操作。
- 而返回值一般通过EAX来返回。