分类: LINUX
2013-12-20 17:01:59
原文地址:实例讲解linux c中函数的栈结构(x86) 作者:shaohui973
本文从一个实例入手来讲解函数调用过程中栈上数据的分布。
示例代码:
#include
void func1(int a, int b, int c)
{
a + b + c;
return;
}
int main()
{
int a=1,b=2,c=3;
int d=10;
printf("&a:0x%08x, &b:0x%08x, &c:0x%08x, &d:0x%08x\n", &a, &b, &c, &d);
func1(a, b, c);
return 0;
}
编译该程序,然后反汇编来看:
080483c4 <func1>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 90 nop
80483c8: 5d pop %ebp
80483c9: c3 ret
080483ca <main>:
80483ca: 55 push %ebp
80483cb: 89 e5 mov %esp,%ebp
80483cd: 83 e4 f0 and $0xfffffff0,%esp
80483d0: 83 ec 30 sub $0x30,%esp
80483d3: c7 44 24 2c 01 00 00 movl $0x1,0x2c(%esp) /* 局部变量a */
80483da: 00
80483db: c7 44 24 28 02 00 00 movl $0x2,0x28(%esp) /* 局部变量b */
80483e2: 00
80483e3: c7 44 24 24 03 00 00 movl $0x3,0x24(%esp) /* 局部变量c */
80483ea: 00
80483eb: c7 44 24 20 0a 00 00 movl $0xa,0x20(%esp) /* 局部变量d */
80483f2: 00
80483f3: b8 14 85 04 08 mov $0x8048514,%eax
80483f8: 8d 54 24 20 lea 0x20(%esp),%edx
80483fc: 89 54 24 10 mov %edx,0x10(%esp)
8048400: 8d 54 24 24 lea 0x24(%esp),%edx
8048404: 89 54 24 0c mov %edx,0xc(%esp)
8048408: 8d 54 24 28 lea 0x28(%esp),%edx
804840c: 89 54 24 08 mov %edx,0x8(%esp)
8048410: 8d 54 24 2c lea 0x2c(%esp),%edx
8048414: 89 54 24 04 mov %edx,0x4(%esp)
8048418: 89 04 24 mov %eax,(%esp)
804841b: e8
c0 fe ff ff call 80482e0
8048420: 8b 4c 24 24 mov 0x24(%esp),%ecx
8048424: 8b 54 24 28 mov 0x28(%esp),%edx
8048428: 8b 44 24 2c mov 0x2c(%esp),%eax
804842c: 89 4c 24 08 mov %ecx,0x8(%esp) /* 函数入参c */
8048430: 89 54 24 04 mov %edx,0x4(%esp) /* 函数入参b*/
8048434: 89 04 24 mov %eax,(%esp) /* 函数入参a */
8048437: e8
88 ff ff ff call 80483c4
804843c: b8 00 00 00 00 mov $0x0,%eax
8048441: c9 leave
8048442: c3 ret
分析上述汇编可以得出如下函数的栈结构:
void func(int arg1,int arg2,int arg3)
{
int v1, v2, v3;
int v4;
……
return;
}
入参arg3 |
入参arg2 |
入参arg1 |
返回地址 |
函数调用者的%ebp |
局变v1 |
局变v2 |
局变v3 |
局变v4 |
…… |
结论:
局部变量是从左向右,从上往下入栈的;
函数调用,实参是从右向左入栈(处理)的。
以上的环境为gnu c compiler + x86
对于gnuc c compiler + powerpc,
1. 局部变量是从下往上入栈的,栈是空递减。