“参数从右到左入栈”,“局部变量在栈上分配空间”,听的耳朵都起茧子了。
最近做项目涉及C和汇编互相调用,写代码的时候才发现没真正弄明白。
自己写了个最简单的函数,用gdb跟踪了调用过程,才多少懂了一点。
参考资料:(感谢liigo和eno_rez两位作者)
http://blog.csdn.net/liigo/archive/2006/12/23/1456938.aspx
http://blog.csdn.net/eno_rez/archive/2008/03/08/2158682.aspx
- int add(int x, int y)
- {
- int a = 0;
- a = x;
- a += y;
- return a;
- }
- int main(int argc, char *argv[])
- {
- int x, y, result;
- x = 0x12;
- y = 0x34;
- result = add(x, y);
- return 0;
- }
编译:(Fedora6, gcc 4.1.2)
[test]$ gcc -g -Wall -o stack stack.c
反汇编:
这里的汇编的格式是AT&T汇编,它的格式和我们熟悉的汇编格式不太一样,尤其要注意源操作数和目的操作数的顺序是反过来的
[test]$ objdump -d stack > stack.dump
[test]$ cat stack.dump
......
08048354 <add>:
8048354: 55 push %ebp ;保存调用者的帧指针
8048355: 89 e5 mov %esp,%ebp ;把当前的栈指针作为本函数的帧指针
8048357: 83 ec 10 sub $0x10,%esp ;调整栈指针,为局部变量保留空间
804835a: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) ;把a置0。ebp-4的位置是第一个局部变量
8048361: 8b 45 08 mov 0x8(%ebp),%eax ;把参数x保存到eax。ebp+8的位置是最后一个入栈的参数,也就是第一个参数
8048364: 89 45 fc mov %eax,0xfffffffc(%ebp) ;把eax赋值给变量a
8048367: 8b 45 0c mov 0xc(%ebp),%eax ;把参数y保存到eax。ebp+C的位置是倒数第二个入栈的参数,也就是第二个参数
804836a: 01 45 fc add %eax,0xfffffff