使用局部变量的编译器,无需调整RSP [英] Compiler using local variables without adjusting RSP

查看:105
本文介绍了使用局部变量的编译器,无需调整RSP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In question Compilers: Understanding assembly code generated from small programs the compiler uses two local variables without adjusting the stack pointer.

不为使用局部变量而调整 RSP 似乎不是中断安全的,因此,编译器似乎依赖于硬件,当发生中断时,它们会自动切换到系统堆栈.否则,出现的第一个中断会将指令指针压入堆栈,并覆盖局部变量.

Not adjusting RSP for the use of local variables seems not interrupt safe and so the compiler seems to rely on the hardware automatically switching to a system stack when interrupts occur. Otherwise, the first interrupt that came along would push the instruction pointer onto the stack and would overwrite the local variable.

该问题的代码为:

#include <stdio.h>

int main()
{
    for(int i=0;i<10;i++){
        int k=0;
    }
}

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

The assembly code generated by that compiler is:

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.

The local variables are i at [rbp-0x8] and k at [rbp-0x4].

有人可以在这个中断问题上大放异彩吗?硬件确实切换到系统堆栈吗?如何?我的理解是否正确?

Can anyone shine light on this interrupt problem? Does the hardware indeed switch to a system stack? How? Am I wrong in my understanding?

推荐答案

这是维基百科的摘要:

在计算中,红色区域是函数堆栈中超出当前堆栈指针的固定大小区域,该区域未被该函数保留.被调用方函数可以使用红色区域存储本地变量,而无需修改堆栈指针.中断/异常/信号处理程序不能修改此内存区域. System V使用的x86-64 ABI规定了一个128字节的红色区域,该区域直接从堆栈指针的当前值开始.

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个就可以.这是叶函数(即不调用其他函数的函数)最显着使用的优化方法.

In 64-bit Linux user code it is OK, as long as no more than 128 bytes are used. It is an optimization used most prominently by leaf-functions, i.e. functions which don't call other functions,

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

If you were to compile the example program as a 64-bit Linux program with GCC (or compatible compiler) using the -mno-red-zone option you'd see code like this generated:

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会显示类似以下代码的内容:

For a 32-bit Linux user program it would be a bad thing not to adjust the stack pointer. If you were to compile the code in the question as 32-bit code (using -m32 option) main would appear something like the following code:

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

可以在此 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆