简体   繁体   English

gcc堆栈优化?

[英]gcc stack optimization?

I just wrote a code sample in C and tried disassembling it. 我刚刚在C中编写了一个代码示例,并尝试将其拆解。 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   
  1. 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 the strcmp method? 有人可以解释为什么我从esp中减去158而不是将值推入堆栈并调用strcmp方法的汇编代码吗? Is it because it does not depend on any user input? 是因为它不依赖于任何用户输入吗?
  2. 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). 另外,有什么方法可以生成extended assembly (我不确定这是否是正确的术语,我只是希望看到用于将值推送到堆栈和调用strcmp函数的汇编代码)。 Is there any way I could do that? 有什么办法可以吗?
  3. Is this kind of behavior specific to processor architectures or gcc versions or both? 这种行为是特定于处理器体系结构还是gcc版本或两者兼有?

First, strcmp is a standard library function, so gcc is free to have special knowledge about how it works. 首先, strcmp是一个标准的库函数,因此gcc可以自由地了解它的工作原理。 In fact, it does; 事实上,它确实; it'll seldom generate a library call. 它很少会产生库调用。 You can try -fno-builtin to disable. 您可以尝试-fno-builtin来禁用。

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); 您可以尝试使用-S选项来获取更详细的反汇编(或者更确切地说,缺少汇编); alternatively, if you compile with -g (debugging), objdump -S will display the source along with the assembled code. 或者,如果使用-g (调试)进行编译,则objdump -S将显示源以及汇编代码。

Here is an example I compiled with gcc -fno-builtin -g -O0 test.c -c and then dumped with objdump -S test.o : 这是我用gcc -fno-builtin -g -O0 test.c -c编译的一个例子,然后用objdump -S test.o转储:

test.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
#include <string.h>

int main() {
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
    const char foo[] = "foo";
   8:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # e <main+0xe>
   e:   89 45 f0                mov    %eax,-0x10(%rbp)
    return strcmp(foo, "bar");
  11:   48 8d 45 f0             lea    -0x10(%rbp),%rax
  15:   be 00 00 00 00          mov    $0x0,%esi
  1a:   48 89 c7                mov    %rax,%rdi
  1d:   e8 00 00 00 00          callq  22 <main+0x22>
}
  22:   c9                      leaveq 
  23:   c3                      retq   

Regarding the sub esp,0x158 instruction, rather than generate a boatload of push 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. 关于sub esp,0x158指令,而不是生成sub esp,0x158 push操作(包括将操作数复制到堆栈,而不仅仅是保留空间),通常编译器将通过移动堆栈指针为所有局部变量保留足够的空间就一次。 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). 0x158是十进制的344,因此它为数组保留了300个字节,并且可能为编译器生成的结构留出了一些额外的空间(或者也可能将strcmp操作数放在堆栈上)。

  1. 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 . 如果你想保留未使用的代码,请确保你没有使用任何优化 - 使用-O0编译。

  2. See my point above. 看到我的观点。

  3. I suspect most compilers would perform this optimisation, independent of architecture. 我怀疑大多数编译器会执行此优化,而不依赖于体系结构。

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). 您可以尝试使用-O0标志进行编译,以确保不进行任何优化(但我不确定它是否可行)。

Or you can just return cmp results from the start function to show the compiler that you really use them: 或者你可以从start函数返回cmp结果,以显示你真正使用它们的编译器:

int start() {
    char phone[] = "43423432";
    return strcmp(phone, "12312312313");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM