装配中局部变量的大小

Ant*_*Rak 0 c assembly gcc x86-64 word-size

我有以下C功能:

void function(int a) {
  char buffer[1];
}
Run Code Online (Sandbox Code Playgroud)

它产生以下汇编代码(gcc,0优化,64位机器):

function:
  pushq %rbp
  movq  %rsp, %rbp
  movl  %edi, -20(%rbp)
  nop
  popq  %rbp
  ret
Run Code Online (Sandbox Code Playgroud)

问题:

  • 为什么缓冲区占用20个字节?
  • 如果我声明char buffer而不是char buffer[1]偏移是4个字节,但我希望看到8,因为机器是64位,我认为它将使用qword(64位).

在此先感谢,如果问题重复,我很抱歉,我无法找到答案.

Pet*_*des 6

movl %edi, -20(%rbp)将函数arg从寄存器溢出到堆栈指针下面的红色区域.它长4个字节,在RSP下面留下16个字节的空间.

gcc -O0(天真的反优化)代码为你的功能实际上并没有触及它预留的内存buffer[],所以你不知道它在哪里.

你无法推断出红色区域中buffer[]上面的所有16个字节都用完了a,只是因为gcc做了-O0很好的有效打包本地的工作(因为你编译了所以它甚至没有尝试).但它肯定不是20,因为没有那么多的空间.除非它放在buffer[] 下面 a,否则在128字节红区的其余部分.(提示:它没有.)


如果我们为数组添加初始化器,我们可以看到它实际存储字节的位置.

void function(int a) {
  volatile char buffer[1] = {'x'};
}
Run Code Online (Sandbox Code Playgroud)

由gcc8.2 -xc -O0 -fverbose-asm -Wall 编译的Godbolt编译器资源管理器:

function:
    pushq   %rbp
    movq    %rsp, %rbp               # function prologue, creating a traditional stack frame

    movl    %edi, -20(%rbp) # a, a

    movb    $120, -1(%rbp)  #, buffer

    nop                             # totally useless, IDK what this is for
    popq    %rbp                    # tear down the stack frame
    ret     
Run Code Online (Sandbox Code Playgroud)

所以buffer[]实际上是一个字节长,右侧下方的保存RBP值.

对于至少16字节长的自动存储阵列,x86-64 System V ABI需要16字节对齐,但这不是这种情况,因此规则不适用.

我不知道为什么gcc在溢出的寄存器arg之前留下额外的填充; gcc经常有这种错过的优化.它没有给出a任何特殊的对齐方式.

如果添加额外的本地数组,它们将填充溢出的arg上方的16个字节,仍会溢出-20(%rbp).(参见function2Godbolt链接)

我也包括在内clang -O0,并icc -O3和MSVC优化的输出,在Godbolt链接.有趣的事实:ICC选择优化volatile char buffer[1] = {'x'};而不实际存储到内存,但MSVC在阴影空间中分配它.(Windows x64使用不同的调用约定,并且在返回地址上方有32B阴影空间,而不是堆栈指针下方的128B红色区域.)

clang/LLVM -O0选择a在RSP下面溢出,并将数组放在其下方1字节.


随着只是 char buffer代替char buffer[1]

我们movl %edi, -4(%rbp) # a, a来自gcc -O0.它显然完全优化了未使用和未初始化的局部变量,并且a在保存的RBP下方溢出.(我没有在GDB下运行它或查看调试信息以查看是否&buffer会给我们.)

如此反复,你混了abuffer.

如果我们用它初始化它char buffer = 'x',我们回到旧的堆栈布局,用bufferat -1(%rbp).

或者,即使我们只是使它volatile char buffer;没有初始化,那么对于空间存在堆栈上,并a会溢出到-20(%rbp)即使没有店面做buffer.