gcc堆栈优化?

发布于 2024-10-12 15:52:18 字数 826 浏览 2 评论 0原文

我刚刚用 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   
  1. 我没有启用任何类型的优化。有人可以解释为什么我从 esp 中减去 158 而不是将值推入堆栈并调用 strcmp 方法的汇编代码吗?是因为它不依赖于任何用户输入吗?
  2. 另外,有什么方法可以生成扩展程序集(我不确定这是否是正确的术语,我只是希望看到将值推入堆栈和调用 strcmp 函数的汇编代码)。我有什么办法可以做到这一点吗?
  3. 这种行为是否特定于处理器架构或 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   
  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? 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). Is there any way I could do that?
  3. Is this kind of behavior specific to processor architectures or gcc versions or both?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

大姐,你呐 2024-10-19 15:52:18

首先,strcmp 是一个标准库函数,因此 gcc 可以自由地了解其工作原理。事实上,确实如此;它很少会生成库调用。您可以尝试使用 -fno-builtin 来禁用。

其次,您要与单位化值进行比较。我认为这是未定义的行为。因此编译器可以做任何它想做的事情,包括生成随机代码。

您可以尝试使用 -S 选项来让 gcc 获得更详细的反汇编(或者更确切地说,缺少汇编);或者,如果使用 -g 进行编译(调试),objdump -S 将显示源代码以及汇编代码。

这是我使用 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   

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 with 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   
你的往事 2024-10-19 15:52:18

对于 sub esp,0x158 指令,编译器通常不会生成大量 push 操作(这也涉及将操作数复制到堆栈,而不仅仅是保留空间)只需移动堆栈指针一次即可为所有局部变量保留足够的空间。这就是该指令的作用。 0x158 是十进制的 344,因此它为数组保留了 300 个字节,并且可能为编译器生成的结构保留了一些额外的空间(或者也可能将 strcmp 操作数放在堆栈上)。

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. 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).

不念旧人 2024-10-19 15:52:18
  1. 因为你的代码对程序执行没有任何影响。所有变量都在函数调用中使用,其返回值将被丢弃,因此编译器将其标记为未使用的代码,并认为应该将其删除。如果您想保留未使用的代码,请确保您没有使用任何优化 - 使用 -O0 进行编译。

  2. 参见我上面的观点。

  3. 我怀疑大多数编译器都会执行这种优化,与体系结构无关。

  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.

  2. See my point above.

  3. I suspect most compilers would perform this optimisation, independent of architecture.

她如夕阳 2024-10-19 15:52:18

看来确实是优化了。您可以尝试使用 -O0 标志进行编译,以确保不进行优化(但我不确定它是否有效)。

或者,您可以从 start 函数返回 cmp 结果,以向编译器显示您确实使用了它们:

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

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:

int start() {
    char phone[] = "43423432";
    return strcmp(phone, "12312312313");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文