C语言 使用局部变量的编译器,无需调整 RSP



>有问题的编译器:了解从小程序生成的汇编代码 编译器使用两个局部变量而不调整堆栈指针。

不调整RSP以使用局部变量似乎不安全,因此编译器似乎依赖于发生中断时自动切换到系统堆栈的硬件。否则,出现的第一个中断会将指令指针推送到堆栈上并覆盖局部变量。

该问题的代码是:

#include <stdio.h>
int main()
{
for(int i=0;i<10;i++){
int k=0;
}
}

该编译器生成的汇编代码为:

00000000004004d6 <main>:
4004d6:       55                      push   rbp
4004d7:       48 89 e5                mov    rbp,rsp
4004da:       c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
4004e1:       eb 0b                   jmp    4004ee <main+0x18>
4004e3:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
4004ea:       83 45 f8 01             add    DWORD PTR [rbp-0x8],0x1
4004ee:       83 7d f8 09             cmp    DWORD PTR [rbp-0x8],0x9
4004f2:       7e ef                   jle    4004e3 <main+0xd>
4004f4:       b8 00 00 00 00          mov    eax,0x0
4004f9:       5d                      pop    rbp
4004fa:       c3                      ret    

局部变量在[rbp-0x8]i,在[rbp-0x4]k

任何人都可以阐明这个中断问题吗?硬件是否确实切换到系统堆栈?如何?我的理解有误吗?

这就是x86-64 ABI的所谓"红色区域"。来自维基百科的摘要:

在计算中,红色区域是函数堆栈

帧中超出当前堆栈指针的固定大小区域,该函数不会保留该区域。被调用方函数可以使用红色区域来存储局部变量,而无需修改堆栈指针的额外开销。此内存区域不得由中断/异常/信号处理程序修改。System V 使用的 x86-64 ABI 要求在堆栈指针的当前值下直接开始一个 128 字节的红色区域。

在 64 位 Linux 用户代码中,只要使用不超过 128 个字节就可以了。它是叶函数最突出使用的优化,即不调用其他函数的函数,


如果您要使用-mno-red-zone选项将示例程序编译为 64 位 Linux 程序,并使用GCC(或兼容的编译器),您将看到生成的代码如下:

main:
push    rbp
mov     rbp, rsp
sub     rsp, 16;     <<============  Observe RSP is now being adjusted.
mov     DWORD PTR [rbp-4], 0
.L3:
cmp     DWORD PTR [rbp-4], 9
jg      .L2
mov     DWORD PTR [rbp-8], 0
add     DWORD PTR [rbp-4], 1
jmp     .L3
.L2:
mov     eax, 0
leave
ret

可以在此 godbolt.org 链接中观察到此代码生成。


对于 32 位 Linux 用户程序,不调整堆栈指针是一件坏事。如果要将问题中的代码编译为 32 位代码(使用-m32选项),main将显示类似于以下代码:

main:
push    ebp
mov     ebp, esp
sub     esp, 16;     <<============  Observe ESP is being adjusted.
mov     DWORD PTR [ebp-4], 0
.L3:
cmp     DWORD PTR [ebp-4], 9
jg      .L2
mov     DWORD PTR [ebp-8], 0
add     DWORD PTR [ebp-4], 1
jmp     .L3
.L2:
mov     eax, 0
leave
ret

可以在此 gotbolt.org 链接中观察到此代码生成。

相关内容

  • 没有找到相关文章

最新更新