【发布时间】:2020-12-28 04:59:47
【问题描述】:
这个问题是关于 x86 程序集的,但我提供了一个 C 语言示例,因为我试图检查 GCC 正在做什么。
当我遵循各种汇编指南时,我注意到人们,至少是我一直在阅读其资料的少数人,似乎习惯于将堆栈变量分配为更接近 rsp 而不是 rbp。
然后我检查了 GCC 会做什么,它似乎是一样的。
在下面的反汇编中,前 0x10 个字节被保留,然后调用叶子的结果通过 eax 到 rbp-0xc,常量值 2 到 rbp-0x8,在 rbp-0x8 和 rbp 之间为变量“q”留出空间”。
我可以想象在另一个方向上做,首先在 rbp 分配一个地址,然后在 rbp-0x4,即在 rbp 到 rsp 的方向上做,然后在 rbp-0x8 和 rsp 之间留一些空间“ q"。
我不确定的是,我所观察到的事情是否应该是由于一些我更好地了解并遵守的架构限制,或者它纯粹是这种特定实现的产物和习惯的表现我读到的代码我不应该赋予任何意义的人,例如这需要在一个方向或另一个方向上完成,只要它是一致的,哪个方向都没有关系。
或者我现在只是在阅读和编写一些琐碎的代码,而这将是双向的,因为我会在一段时间内获得更实质性的东西?
我只是想知道我应该如何在我自己的汇编代码中处理它。
所有这些都在 Linux 64 位、GCC 版本 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 上。谢谢。
00000000000005fa <leaf>:
5fa: 55 push rbp
5fb: 48 89 e5 mov rbp,rsp
5fe: b8 01 00 00 00 mov eax,0x1
603: 5d pop rbp
604: c3 ret
0000000000000605 <myfunc>:
605: 55 push rbp
606: 48 89 e5 mov rbp,rsp
609: 48 83 ec 10 sub rsp,0x10
60d: b8 00 00 00 00 mov eax,0x0
612: e8 e3 ff ff ff call 5fa <leaf>
617: 89 45 f4 mov DWORD PTR [rbp-0xc],eax ; // <--- This line
61a: c7 45 f8 02 00 00 00 mov DWORD PTR [rbp-0x8],0x2 ; // <-- And this too
621: 8b 55 f4 mov edx,DWORD PTR [rbp-0xc]
624: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
627: 01 d0 add eax,edx
629: 89 45 fc mov DWORD PTR [rbp-0x4],eax
62c: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
62f: c9 leave
630: c3 ret
这是 C 代码:
int leaf() {
return 1;
}
int myfunc() {
int x = leaf(); // <--- This line
int y = 2; // <-- And this too
int q = x + y;
return q;
}
int main(int argc, char *argv[]) {
return myfunc();
}
我如何编译它:
gcc -O0 main.c -o main.bin
我如何拆解它:
objdump -d -j .text -M intel main.bin
【问题讨论】:
-
是的,您可以随心所欲地使用本地人。如果由于对齐而分配了更多空间,则可以将填充放在任何地方。 PS:您正在查看未优化的代码,这通常是个坏主意。
-
@Jester 谢谢,但我不确定在这种情况下查看未优化的代码有什么不好?在 -O2 上 gcc 发出“nop WORD PTR cs:[rax+rax*1+0x0]”,根本不使用堆栈变量,这并不是我真正想要展示的。我大致了解优化级别之间的区别,但鉴于我正在编写程序集而 C 只是一项附加资产,我不清楚在此示例中使用 -O0 有什么注意事项?
-
您声称 GCC 在保存的 RBP 下方留下了一些空间,但实际上使用了
dword [rbp-0x4]。 (对于q它看起来像。) -
这不是“声明” :-) 它似乎与 x 和 y 无关。但是你是对的,我忘记了 q 并且似乎我的意思是留下了未使用的空间。我将进行编辑以使其更清楚地表明它适用于 q。谢谢。
-
-O0表示快速编译而不尝试优化(包括不尝试优化堆栈帧布局)。因此,如果您希望了解有关如何布置本地人的任何信息,那么这不是一个好的开始。 (但就像 Jester 所说的那样;如何布置它们并不重要,除了可能将它们分组以便您可以使用单个 qword 存储同时初始化两个)。
标签: assembly x86-64 local-variables stack-frame