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.

我的问题是下一行如何 0xc

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

我的理解是: 0x12345678 占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:为什么 main() 需要与 16 个字节对齐(通过“sub $0x10,%rsp”)而 func 不是(0x0c 未对齐,对吗?)?

4

1 回答 1

10

Linux 2.6.18-194.el5 #1 SMP 2010 年 3 月 16 日星期二 21:52:39 EDT x86_64

...后跟指针“p”的 4 个字节...

您使用的是 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
+----------+

然后,您将 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
+----------+
于 2013-07-09T08:56:22.857 回答