gcc堆栈优化?
我刚刚用 C 编写了一个代码示例并尝试反汇编它。以下是代码示例。
void start() {
char phone[100];
strcmp(phone, "12312312313");
char name[100];
strcmp(name, "eQuiNoX");
char contact[100];
strcmp(contact, "PM twitter.com/eQuiNoX__");
}
当我反汇编启动函数时,我得到以下信息:-
08048414 <start>:
8048414: 55 push ebp
8048415: 89 e5 mov ebp,esp
8048417: 81 ec 58 01 00 00 sub esp,0x158
804841d: c9 leave
804841e: c3 ret
- 我没有启用任何类型的优化。有人可以解释为什么我从 esp 中减去
158
而不是将值推入堆栈并调用strcmp
方法的汇编代码吗?是因为它不依赖于任何用户输入吗? - 另外,有什么方法可以生成
扩展程序集
(我不确定这是否是正确的术语,我只是希望看到将值推入堆栈和调用 strcmp 函数的汇编代码)。我有什么办法可以做到这一点吗? - 这种行为是否特定于处理器架构或 gcc 版本或两者?
I just wrote a code sample in C and tried disassembling it. Following is the code sample.
void start() {
char phone[100];
strcmp(phone, "12312312313");
char name[100];
strcmp(name, "eQuiNoX");
char contact[100];
strcmp(contact, "PM twitter.com/eQuiNoX__");
}
When I disassemble the start function I get the following:-
08048414 <start>:
8048414: 55 push ebp
8048415: 89 e5 mov ebp,esp
8048417: 81 ec 58 01 00 00 sub esp,0x158
804841d: c9 leave
804841e: c3 ret
- I have not enabled any kind of optimization. Could someone explain why I get
158
subtracted from esp rather than assembly code which pushes values onto the stack and calls thestrcmp
method? Is it because it does not depend on any user input? - Also, is there any way I could generate the
extended assembly
(im not sure if thats the right term, i just wish to see the assembly code for pushing values onto the stack and the calling of the strcmp function). Is there any way I could do that? - Is this kind of behavior specific to processor architectures or gcc versions or both?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,strcmp 是一个标准库函数,因此 gcc 可以自由地了解其工作原理。事实上,确实如此;它很少会生成库调用。您可以尝试使用
-fno-builtin
来禁用。其次,您要与单位化值进行比较。我认为这是未定义的行为。因此编译器可以做任何它想做的事情,包括生成随机代码。
您可以尝试使用
-S
选项来让 gcc 获得更详细的反汇编(或者更确切地说,缺少汇编);或者,如果使用 -g 进行编译(调试),objdump -S 将显示源代码以及汇编代码。这是我使用 gcc -fno-builtin -g -O0 test.c -c 编译,然后使用 objdump -S test.o 转储的示例:
First,
strcmp
is a standard library function, so gcc is free to have special knowledge about how it works. In fact, it does; it'll seldom generate a library call. You can try-fno-builtin
to disable.Second, you're comparing to unitialized values. This is, I believe undefined behavior. So the compiler may do anything it pleases, including producing random code.
You can try the
-S
option to gcc get more detailed disassembly (or, rather, lack of assembly); alternatively, if you compile with-g
(debugging),objdump -S
will display the source along with the assembled code.Here is an example I compiled with
gcc -fno-builtin -g -O0 test.c -c
and then dumped withobjdump -S test.o
:对于
sub esp,0x158
指令,编译器通常不会生成大量push
操作(这也涉及将操作数复制到堆栈,而不仅仅是保留空间)只需移动堆栈指针一次即可为所有局部变量保留足够的空间。这就是该指令的作用。0x158
是十进制的 344,因此它为数组保留了 300 个字节,并且可能为编译器生成的结构保留了一些额外的空间(或者也可能将 strcmp 操作数放在堆栈上)。Regarding the
sub esp,0x158
instruction, rather than generate a boatload ofpush
operations (which involve copying the operand to the stack too, not just reserving space), typically the compiler will just reserve enough space for all local variables by moving the stack pointer just once. That's what this instruction is doing.0x158
is 344 in decimal, so it's reserving 300 bytes for the arrays and probably some extra space for compiler generated structures (or maybe to put the strcmp operands on the stack too).因为你的代码对程序执行没有任何影响。所有变量都在函数调用中使用,其返回值将被丢弃,因此编译器将其标记为未使用的代码,并认为应该将其删除。如果您想保留未使用的代码,请确保您没有使用任何优化 - 使用
-O0
进行编译。参见我上面的观点。
我怀疑大多数编译器都会执行这种优化,与体系结构无关。
Because your code has no effect in the program execution. All variables are used in function calls whose return values are discarded, thus the compiler tagged it as unused code, and felt it should remove. If you want to keep the unused code, be sure you're not using any optimisations - compile with
-O0
.See my point above.
I suspect most compilers would perform this optimisation, independent of architecture.
看来确实是优化了。您可以尝试使用 -O0 标志进行编译,以确保不进行优化(但我不确定它是否有效)。
或者,您可以从 start 函数返回 cmp 结果,以向编译器显示您确实使用了它们:
It seems that it really was optimized. You can try compiling with -O0 flag to ensure that no optimization is made (however I'm not sure it will work).
Or you can just return cmp results from the start function to show the compiler that you really use them: