简体   繁体   English

无法设置堆栈边界gcc

[英]Can't set stack boundary gcc

My c code: 我的C代码:

#include <stdio.h>

foo()
{
  char buffer[8];
}

main()
{
  foo();
  return 0;
}

I compile it using gcc -ggdb -mpreferred-stack-boundary=2 -o bar bar.c 我使用gcc -ggdb -mpreferred-stack-boundary=2 -o bar bar.c

When I load it using GDB ./bar I see that inside the foo function the code is: 当我使用GDB ./bar加载它时,我看到foo函数内部的代码是:

sub $0x0c,$esp

Why is this happening? 为什么会这样呢?

I want to buffer to take 8 bytes in the stack so it should be sub $0x8,$esp ! 我想缓冲堆栈中的8个字节,因此它应该是sub $0x8,$esp

Why can't I set stack boundary to 4 bytes? 为什么不能将堆栈边界设置为4个字节?

Help! 救命!

I can't reproduce exactly what you are seeing, but on my 4.8.2 version of gcc, the option does affect the amount of stack used with this code (make sure "buffer" is used to avoid it being optimised away, and fix the warnings for no return type/argument types): 我无法完全重现您所看到的内容,但是在我的4.8.2版本的gcc上,该选项确实会影响此代码使用的堆栈量(请确保使用“缓冲区”,以避免对其进行优化,然后修复没有返回类型/参数类型的警告):

#include <stdio.h>

void foo(void)
{
    char buffer[8];
    buffer[0] = 'a';
    buffer[1] = '\n';
    buffer[2] = 0;
    printf("my first program! %s\n", buffer);
}

int main()
{
    foo();
    return 0;
}

Compiled with -mpreferred-stack-boundary=2 and -mpreferred-stack-boundary=4, and the difference between the generated assembler is notable: 使用-mpreferred-stack-boundary = 2和-mpreferred-stack-boundary = 4进行编译,生成的汇编器之间的区别非常明显:

$ diff -u stb-2.s stb-4.s 
--- stb-2.s 2014-04-10 09:00:39.546038191 +0100
+++ stb-4.s 2014-04-10 09:00:58.895108979 +0100
@@ -15,11 +15,11 @@
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
-   subl    $16, %esp
-   movb    $97, -8(%ebp)
-   movb    $10, -7(%ebp)
-   movb    $0, -6(%ebp)
-   leal    -8(%ebp), %eax
+   subl    $40, %esp
+   movb    $97, -16(%ebp)
+   movb    $10, -15(%ebp)
+   movb    $0, -14(%ebp)
+   leal    -16(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
 .LEHB0:
@@ -67,9 +67,10 @@
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
+   andl    $-16, %esp
    call    _Z3foov
    movl    $0, %eax
-   popl    %ebp
+   leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret

So, at least in gcc 4.8.2. 因此,至少在gcc 4.8.2中。 for x86-32, the option has an effect. 对于x86-32,该选项有效。

Of course, the default according to the docs is -mpreferred-stack-boundary=2, so maybe that's why you can't see any difference from "without" (Although in my experiments, it seems that it's -mpreferred-stack-boundary=4). 当然,根据文档,默认值为-mpreferred-stack-boundary = 2,所以这也许就是为什么您看不到与“ without”没有任何区别的原因(尽管在我的实验中,它似乎是-mpreferred-stack-boundary = 4)。 [Moment passes] Ah, the default has been changed over time, so the 4.4.2 docs online says 2, my info gcc for 4.8.2 says 4, which explains the difference. [瞬间过去]啊,默认值已经随着时间而改变,所以在线4.4.2文档说2,我的4.8.2的信息gcc说4,这解释了差异。

As to why your code is allocating twelve bytes of stack-space - look at how printf is called: 至于为什么代码要分配十二个字节的堆栈空间,请看一下printf的调用方式:

movl    $.LC0, (%esp)
call    printf

If the compiler can, it will pre-allocate argument space for function calls at the start of the function, rather than use push $.LC0 as it would be in this case. 如果编译器可以,它将在函数开始时为函数调用预分配参数空间,而不是像在这种情况下那样使用push $.LC0 It's not much difference, but it saves at least one instruction for cleanup at the other side of printf (and it makes it MUCH easier to deal with stack-relative offsets within the produced code, since the compiler doesn't have to keep track of where the current stack-pointer is - it's always at a constant place after the prologue code at the beginning of the function, all the way to the end of the function). 差别不大,但是它在printf的另一侧保存了至少一条指令用于清理(并且这使得在生成的代码中更容易处理相对于堆栈的偏移量,因为编译器不必跟踪当前堆栈指针所在的位置-它始终在函数开始处的序言代码之后,一直到函数结束处的恒定位置。 Since the space is ultimately required anyway, there's no point in "saving 4 bytes". 由于最终还是需要空间,因此“节省4个字节”毫无意义。

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

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