2013-07-09 28 views
5

源代码:抵消如何进入堆栈?

1  int func() 
2  { 
3   int a = 0x12345678; 
4   int *p = &a; 
5   return *p; 
6  } 

8  int main() 
9  { 
10   int b = 0x87654321; 
11   return b + func(); 
12  } 

拆卸:

(gdb) disass main 
Dump of assembler code for function main(): 
0x0000000000400544 <main()+0>: push %rbp 
0x0000000000400545 <main()+1>: mov %rsp,%rbp  
0x0000000000400548 <main()+4>: sub $0x10,%rsp 
0x000000000040054c <main()+8>: movl $0x87654321,-0x4(%rbp) 
0x0000000000400553 <main()+15>: callq 0x400528 <func()> 
0x0000000000400558 <main()+20>: add -0x4(%rbp),%eax 
0x000000000040055b <main()+23>: leaveq 
0x000000000040055c <main()+24>: retq 
End of assembler dump. 
(gdb) disass func 
Dump of assembler code for function func(): 
0x0000000000400528 <func()+0>: push %rbp 
0x0000000000400529 <func()+1>: mov %rsp,%rbp 
0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp) <=how -0xc comes? 
0x0000000000400533 <func()+11>: lea -0xc(%rbp),%rax 
0x0000000000400537 <func()+15>: mov %rax,-0x8(%rbp) 
0x000000000040053b <func()+19>: mov -0x8(%rbp),%rax 
0x000000000040053f <func()+23>: mov (%rax),%eax 
0x0000000000400541 <func()+25>: leaveq 
0x0000000000400542 <func()+26>: retq 
End of assembler dump. 

我的问题是

"0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp)" comes. 

我的理解如何位于0xC中下面的行是:0×12345678占用4个字节用于可变a,随后4个字节用于指针p,其余4个字节用于什么?

谢谢。

编辑:

Linux 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39 EDT 2010 x86_64 

编辑1 :: 一个问题: 什么是以下行?

的汇编代码转储为main()函数:

0x0000000000400544 <main()+0>: push %rbp 
0x0000000000400545 <main()+1>: mov %rsp,%rbp  
0x0000000000400548 <main()+4>: sub $0x10,%rsp <== ? 

编辑2:为什么主()需要16个字节对齐 (由 “子$为0x10,%RSP”),而FUNC不(0x0c不对齐,对吧?)?

+0

看起来你的机器是64位,并在你的机器地址为8个字节不是4个字节 –

+0

是的,非常感谢你。 –

回答

10

的Linux 2.6.18-194.el5#1 SMP星期二03月16日21时52分三十九秒EDT 2010 x86_64的

...接着4个字节用于指针 “P” .. 。

你是在64位体系结构,因此指针占据64位= 8个字节:

#include <stdio.h> 

int main() { 
    int a = 0x12345678; 
    int *p = &a; 

    printf("%zu\n", sizeof(p)); 
    printf("%zu\n", sizeof(a)); 

    return 0; 
} 
$ gcc -std=c99 -Wall -pedantic -o sample sample.c 
$ ./sample 
8 
4 

详细堆分析:

当进入func(),在执行前两个指令后,堆栈看起来像这样(假设每个矩形是4个字节的存储器):

0x0000000000400528 <func()+0>: push %rbp 
0x0000000000400529 <func()+1>: mov %rsp,%rbp 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
|   | <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
|   | <== -0x8(%rbp) /
+----------+    -/ 
|   | <== -0xc(%rbp)  int a 
+----------+ 

您然后存储一个值到本地a变量:

0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp) <=how -0xc comes? 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
|   | <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
|   | <== -0x8(%rbp) /
+----------+    -/ 
|0x12345678| <== -0xc(%rbp)  int a 
+----------+ 

然后,你是sto响64位指针到p变量:

0x0000000000400533 <func()+11>: lea -0xc(%rbp),%rax ; load address of a into RAX 
0x0000000000400537 <func()+15>: mov %rax,-0x8(%rbp) ; store address into pointer (64 bit) 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
| &a (high)| <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
| &a (low) | <== -0x8(%rbp) /
+----------+    -/ 
|0x12345678| <== -0xc(%rbp)  int a 
+----------+ 
+0

我很好的选择,OP给出了问题的答案! –

+1

是的,祝你好运他发布了拱名:) –

+0

注意main():'movl $ 0x87654321,-0x4(%rbp)'它的'4'字节。 ..如何反汇编main()和func()可以是不同的 –