【问题标题】:Doubts with stack pointer堆栈指针的疑问
【发布时间】:2016-01-07 09:26:36
【问题描述】:

考虑一个程序:

#include <stdio.h>

void function(int a, int b, int c){
    char buffer1[5];
    char buffer2[10];
}

void main(){
        function(1,2,3);
}

编译这个
gcc test.c -m32 -g -o test -fno-stack-protector
和做
objdump -S test > test.dis

我得到了函数“function”的以下转储

void function(int a, int b, int c){
 80483ed:       55                      push   %ebp
 80483ee:       89 e5                   mov    %esp,%ebp
 80483f0:       83 ec 10                sub    $0x10,%esp
        char buffer1[5];
        char buffer2[10];
}

考虑同一程序的另一个变体:

#include <stdio.h>

void function(int a, int b, int c){
        char buffer1[7];
        char buffer2[10];
}

void main(){
        function(1,2,3);
}

关于使用我得到的相同命令编译和生成转储:

void function(int a, int b, int c){
 80483ed:       55                      push   %ebp
 80483ee:       89 e5                   mov    %esp,%ebp
 80483f0:       83 ec 20                sub    $0x20,%esp
        char buffer1[7];
        char buffer2[10];
}

我的问题是什么导致堆栈指针在第一种情况下减少 16,在第二种情况下减少 32,而在第二种情况下只需要 2 个字节?

我在英特尔处理器上运行 64 位 ubuntu 14.04

【问题讨论】:

  • 看起来像堆栈对齐。 ceil(log2(15)) == 4, 2^4 == 16. ceil(log2(17)) == 5, 2^5 == 32。
  • 我不明白其中的奥秘。这不是很明显吗?了解您的期望或您想要解释的内容真的很有帮助。
  • @DavidSchwartz 我认为他只是在解释为什么实际上只需要多 2 个字节时使用了 16 个字节以上的堆栈空间。
  • @MichaelWalz 那么我们对他的问题有三种可能的解读!

标签: c assembly x86


【解决方案1】:

来自the GCC documentation

-mpreferred-stack-boundary=num
尝试保持堆栈边界与 2 提升到 num 字节边界对齐。如果未指定 -mpreferred-stack-boundary默认为 4(16 字节 或 128 位),除非优化代码大小 (-Os),在这种情况下默认是最小正确对齐方式(x86 为 4 字节,x86-64 为 8 字节)。

因此,当在堆栈上为数组分配空间时,堆栈也会在 16 字节的默认边界上对齐。在第一种情况下,您有 15 个字节的数据小于 16,因此分配了 16 个字节。在第二种情况下,您有 17 个字节的数据,大于 16 但小于(16 的下一个倍数)32,因此分配了 32 个字节的空间。

【讨论】:

  • 这种对齐有什么重要性?我的意思是为什么编译器要费心做这种对齐?
  • AFAIK GCC 这样做是为了能够将 SSE 数据存储在堆栈上,因为某些 SSE 指令具有对齐要求。
  • @Siddhant,@Michael:不仅仅是 SSE。在 x86 中,未对齐的读/写是 SLOW。在 ARM(和许多其他架构)中,情况更糟:它会使程序崩溃(通常通过总线错误)。
  • 除了效率之外,您会发现操作系统上标准库中的调用约定将强制执行此操作。
猜你喜欢
  • 2015-11-16
  • 2013-01-20
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 2015-08-05
  • 1970-01-01
  • 2021-09-17
相关资源
最近更新 更多