原创作品:陈晓爽(cxsmarkchan)
转载请注明出处
《Linux操作系统分析》MOOC课程 学习笔记
本文通过汇编一段含有简单函数调用的C程序,说明在函数调用过程中堆栈的变化。
1 C程序及其汇编代码
1.1 C程序源码
本文使用的C程序源码如下:
//main.c
int g(int x){
return x + 5;
}
int f(int x){
return g(x);
}
int main(void){
return f(9) + 3;
}
这个程序仅含有main函数和两个函数调用,不含输入输出。不难看出程序的运行过程为:
- main函数调用f函数,传入参数9;
- f函数调用g函数,传入参数9;
- g函数返回9+5,即14;
- f函数返回14;
- main函数返回14+3,即17.
1.2 汇编代码
在linux(本文平台为实验楼Linux内核分析)下执行如下编译指令:
gcc -S -o main.s main.c -m32
该指令可将main.c编译为汇编代码(而非二进制执行文件),输出到main.s。参数“-m32”表示采用32位的方式编译。
用vim打开main.s文件,可以看到如下图的汇编代码:
在main.s中,有大量的以“.”开头的行,这些行只是用于链接的说明性代码,在实际的程序中并不会出现。为便于分析,可以将这些内容删去,得到纯粹的汇编代码,如下:
g:
02 pushl %ebp
03 movl %esp, %ebp
04 movl 8(%ebp), %eax
05 addl $5, %eax
06 popl %ebp
07 ret
f:
09 pushl %ebp
10 movl %esp, %ebp
11 subl $4, %esp
12 movl 8(%ebp), %eax
13 movl %eax, (%esp)
14 call g