C语言 为什么在叶函数中rsp寄存器不像在其他函数的开头那样递减?[副本]

im9ewurl  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(106)

此问题已在此处有答案

Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?(2个答案)
Compiler using local variables without adjusting RSP(1个答案)
How system V ABI's red zone is implemented(1个答案)
上个月关门了。
以下是关于我的系统的一些信息:

  • 运行在Intel x86_64上的Ubuntu 22.04.3;
  • ggc版本11.4.0;

我注意到,在叶函数中,rsp寄存器不像在非叶函数中那样递减。
例如,考虑文件test. c中的以下C程序:

int fx(){
     
     int x = 30;
     int y = 34;
     int z = 45;
     return 30;  
}

int main(){    
    
    int a = 10;
    int b = 20;
    int c = fx();
     
}

在使用“gcc test.c -fno-stack-protector -o test”编译它之后,我运行“objdump -dw -M suffix test”,我得到:

0000000000001129 <fx>:
    1129:   f3 0f 1e fa             endbr64 
    112d:   55                      pushq  %rbp
    112e:   48 89 e5                movq   %rsp,%rbp
    1131:   c7 45 fc 1e 00 00 00    movl   $0x1e,-0x4(%rbp)
    1138:   c7 45 f8 22 00 00 00    movl   $0x22,-0x8(%rbp)
    113f:   c7 45 f4 2d 00 00 00    movl   $0x2d,-0xc(%rbp)
    1146:   b8 1e 00 00 00          movl   $0x1e,%eax
    114b:   5d                      popq   %rbp
    114c:   c3                      retq   

000000000000114d <main>:
    114d:   f3 0f 1e fa             endbr64 
    1151:   55                      pushq  %rbp
    1152:   48 89 e5                movq   %rsp,%rbp
    1155:   48 83 ec 10             subq   $0x10,%rsp
    1159:   c7 45 fc 0a 00 00 00    movl   $0xa,-0x4(%rbp)
    1160:   c7 45 f8 14 00 00 00    movl   $0x14,-0x8(%rbp)
    1167:   b8 00 00 00 00          movl   $0x0,%eax
    116c:   e8 b8 ff ff ff          callq  1129 <fx>
    1171:   89 45 f4                movl   %eax,-0xc(%rbp)
    1174:   b8 00 00 00 00          movl   $0x0,%eax
    1179:   c9                      leaveq 
    117a:   c3                      retq

正如你所看到的,在main中我们有subq $0x10,%rsp,但在fx中这不会发生。
我的问题:
1.它是否与gcc遵循的System V ABI有关,或者它只是编译器执行的优化?
1.是什么原因导致了这种行为?
1.有没有一种方法可以告诉编译器我不希望在叶函数中出现这种行为?

unguejic

unguejic1#

因为你没有通过寄存器传递任何参数,也没有调用任何其他函数,所以保留堆栈空间是没有意义的。

void nn(int x);

int fx(void){     
     volatile int x = 30;

     nn(x);
     return 30;  
}

https://godbolt.org/z/7qE4nbdcn
是否可以在Ubuntu x86_64系统中编译带有“-mno-red-zone”标志的C程序,如“gcc file. c-fno-stack-protector -mno-red-zone -o file”?这个选项是否会破坏某些东西或导致一些不兼容性,或者它只是一个优化?
它是安全的。基本上,它在用户空间代码中是毫无意义的。这是一种优化吗?- 是的,差不多保留空间是毫无意义的,除非你的堆栈大于红色区域。

int fx(void){     
     volatile int x[100] = {30,};

     return 30;  
}

它将保留堆栈减去红色区域的大小。
https://godbolt.org/z/8qb191x9E
我读到过System V ABI“命令”红色区域。这是否意味着即使我们使用-mno-red-zone选项,这个红色区域也确实存在?我的意思是,如果我们使用这个选项,我们不使用红色区域,但它仍然存在?
这与你的代码无关。信号和中断处理程序会将堆栈指针从您的指针上移开。要更改它,您需要重新编译内核并修改它的一些代码。

相关问题