简单的写一下,这几天看的成果,参考了他人的文章,有几个写的很不错
给出一个简单的例子。
===para.c===
#include
void test(int a)
{
(a)++;
return;
}
int main(int argc, char *argv[])
{
int a = 2;
test(a);
return 0;
}
使用$>gcc -S para.c
编译生汇编文件para.s
1 .file "para.c"
2 .text
3 .globl test
4 .type test, @function
5 test:
6 .LFB0:
7 .cfi_startproc
8 pushl %ebp
9 .cfi_def_cfa_offset 8
10 .cfi_offset 5, -8
11 movl %esp, %ebp
12 .cfi_def_cfa_register 5
13 addl $1, 8(%ebp)
14 popl %ebp
15 .cfi_def_cfa 4, 4
16 .cfi_restore 5
17 ret
18 .cfi_endproc
19 .LFE0:
20 .size test, .-test
21 .globl main
22 .type main, @function
23 main:
24 .LFB1:
25 .cfi_startproc
26 pushl %ebp
27 .cfi_def_cfa_offset 8
28 .cfi_offset 5, -8
29 movl %esp, %ebp
30 .cfi_def_cfa_register 5
31 subl $20, %esp
32 movl $2, -4(%ebp)
33 movl -4(%ebp), %eax
34 movl %eax, (%esp)
35 call test
36 movl $0, %eax
37 leave
38 .cfi_restore 5
39 .cfi_def_cfa 4, 4
40 ret
41 .cfi_endproc
42 .LFE1:
43 .size main, .-main
44 .ident "GCC: (GNU) 4.6.1 20110908 (Red Hat 4.6.1-9)"
45 .section .note.GNU-stack,"",@progbits
先从汇编看,从main开始,26~29行,大家应该比较熟悉,汇编函数标准的程序开头
26 pushl %ebp
//堆栈基地址入栈,每个函数都会有自己的局部变量,我觉得这里的目的在于使每个函数都有
//自己独立的栈空间,这样就不会互相干扰,这一句的作用就是保存该函数前面使用的堆栈
//环境,main函数其实没什么特别,它也是被别人调用的,因此也要做这些保存工作
27 .cfi_def_cfa_offset 8
28 .cfi_offset 5, -8
29 movl %esp, %ebp
//把当前堆栈顶指针作为当前函数的堆栈基地址
31 subl $20, %esp
//在堆栈里面预留一些空间来存放局部变量
32 movl $2, -4(%ebp)
//这里的 a 是局部变量,把 2 赋值给a 存放在(%ebp - 4)的堆栈里
33 movl -4(%ebp), %eax
//把 a 的值 放到寄存器 %eax里面
34 movl %eax, (%esp)
//再把 a 的值放到当前堆栈顶,这个是为什么呢?
35 call test
//调用test 函数
36 movl $0, %eax
//return 0
37 leave
接下来看test函数的汇编代码:
8 pushl %ebp
//同前面讲过的main函数,这里是保存main函数的堆栈基地址指针
9 .cfi_def_cfa_offset 8
10 .cfi_offset 5, -8
11 movl %esp, %ebp
//当前函数的基地址设为%esp
12 .cfi_def_cfa_register 5
13 addl $1, 8(%ebp)
//这里是我猜测的啊,从main函数32,33,34行可以知道,有三个地方存放变量a的数值,其中
//32行是存放main函数的局部变量a,33行是存放 调用函数实参的,34行这个就看不明白了。
//而此处,为什么是8(%ebp)呢,画一个图就很清楚了,其中隐藏的一点就是call调用时,也会
//做一次入栈操作,目的是保存eip的指针,即函数返回后需要执行的下一条指令的地址。这里就占用站哟
//4个字节,然后,test函数开始处需要保存%ebp,又占用4个字节,当前的%ebp加8个字节
//正好到了34行的地址处,这里存放着a = 2
14 popl %ebp //%ebp出栈
15 .cfi_def_cfa 4, 4
16 .cfi_restore 5
17 ret
//函数返回,%eip出栈
阅读(1220) | 评论(0) | 转发(0) |