日期:2014-05-16 浏览次数:20868 次
在上一节已经探讨了空函数时的栈布局,那么,在程序运行时,会有一些局部变量,那么它们是存放在栈哪里?在这里,继续探究一下当函数有局部变量时栈是怎样布局的。
先看例子:
int func() { int a = 0x12345678; int *p = &a; return *p; } int main() { int b = 0x87654321; return b + func(); }
编译它
[buckxu@xuzhina 2]$ cc -o xuzhina_dump_c3_s2 xuzhina_dump_c3_s2.cpp
看一下main函数的汇编:
(gdb) disassemble main Dump of assembler code for function main: 0x080483ea <+0>: push %ebp 0x080483eb <+1>: mov %esp,%ebp 0x080483ed <+3>: sub $0x10,%esp 0x080483f0 <+6>: movl $0x87654321,-0x4(%ebp) 0x080483f7 <+13>: call 0x80483d0 <_Z4funcv> 0x080483fc <+18>: mov -0x4(%ebp),%edx 0x080483ff <+21>: add %edx,%eax 0x08048401 <+23>: leave 0x08048402 <+24>: ret End of assembler dump.
由于在main函数里,只有一个局部变量b,它的值是0x87654321,从指令
0x080483f0 <+6>: movl $0x87654321,-0x4(%ebp)
可以知道
在main函数这一桢里,ebp-4所指向的单元存放着局部变量b。在0x080483f7打断点,看一下是不是这样:
(gdb) i r ebp ebp 0xbffff4d8 0xbffff4d8 (gdb) x /4x $ebp-4 0xbffff4d4: 0x87654321 0x00000000 0x4a8bf635 0x00000001 (gdb) info symbol 0x4a8bf635 __libc_start_main + 245 in section .text of /lib/libc.so.6
确实如此,且紧挨着ebp所指向的单元。
再看一下func函数的汇编:
(gdb) disassemble func Dump of assembler code for function _Z4funcv: 0x080483d0 <+0>: push %ebp 0x080483d1 <+1>: mov %esp,%ebp 0x080483d3 <+3>: sub $0x10,%esp 0x080483d6 <+6>: movl $0x12345678,-0x8(%ebp) 0x080483dd <+13>: lea -0x8(%ebp),%eax 0x080483e0 <+16>: mov %eax,-0x4(%ebp) 0x080483e3 <+19>: mov -0x4(%ebp),%eax 0x080483e6 <+22>: mov (%eax),%eax 0x080483e8 <+24>: leave 0x080483e9 <+25>: ret End of assembler dump.
由于func有两个局部变量,一个是a,值为0x12345678,一个是p,初始化为&a.
从
0x080483d6 <+6>: movl $0x12345678,-0x8(%ebp)
可以知道ebp-8指向局部变量a。
从
0x080483dd <+13>: lea -0x8(%ebp),%eax 0x080483e0 <+16>: mov %eax,-0x4(%ebp)
可知,ebp-4指向局部变量p。
在
0x080483e3 <+19>: mov -0x4(%ebp),%eax
处打断点,可以看到如下内容:
(gdb) tbreak *0x080483e3 Temporary breakpoint 2 at 0x80483e3 (gdb) c Continuing. Temporary breakpoint 2, 0x080483e3 in func() () (gdb) i r ebp ebp 0xbffff4c0 0xbffff4c0 (gdb) x /4x $ebp-8 0xbffff4b8: 0x12345678 0xbffff4b8 0xbffff4d8 0x080483fc
果然,ebp-8放着0x12345678,而ebp-4则放着ebp-8,即0xbffff4b8。
从这两个函数的情况,可以看出局部变量在栈上的布局是这样的,如图: