源代码:
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占用变量a
的4个字节,后跟占用p
的4个字节,其余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没有对齐,对吧?)?
答案 0 :(得分:10)
Linux 2.6.18-194.el5#1 SMP Tue Mar 16 21:52:39 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
+----------+
然后,您将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
+----------+