gpt4 book ai didi

编译器使用局部变量而不调整 RSP

转载 作者:太空宇宙 更新时间:2023-11-04 04:23:58 31 4
gpt4 key购买 nike

有问题Compilers: Understanding assembly code generated from small programs编译器使用两个局部变量而不调整堆栈指针。

不调整 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 的所谓“红区” .来自 wikipedia 的摘要:

In computing, a red zone is a fixed-size area in a function's stack frame beyond the current stack pointer which is not preserved by that function. The callee function may use the red zone for storing local variables without the extra overhead of modifying the stack pointer. This region of memory is not to be modified by interrupt/exception/signal handlers. The x86-64 ABI used by System V mandates a 128-byte red zone which begins directly under the current value of the stack pointer.

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


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

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 处观察到链接。

关于编译器使用局部变量而不调整 RSP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43430090/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com