“ sub $ 16,%rsp”指令的作用是什么?

问题描述

让我们采用以下基本C函数以及它产生的有意未优化的程序集:

int main() {
    int i = 4;
    return 3;
}

它产生以下(未优化的)程序集,这对我来说都是有意义的:

main:
        pushq   %rbp
        movq    %rsp,%rbp
        movl    $4,-4(%rbp)
        movl    $3,%eax
        popq    %rbp
        ret

但是,一旦添加函数调用,就会有两条我不太了解的指令:

void call() {};
int main() {
    int i = 4;
    call();
    return 3;
}
main:
        pushq   %rbp
        movq    %rsp,%rbp
        subq    $16,%rsp     <-- why is it subtracting 16?
        movl    $4,-4(%rbp)
        movl    $0,%eax      <-- why is it first clearing the %eax register?
        call    call
        movl    $3,%eax
        leave
        ret

如果堆栈帧需要对齐16字节,subq $16,%rsp对此有何帮助?最初的pushq %rbp指令是否已经将其偏移8,而现在为+24?还是上面有问题的这两行的要点是什么?

解决方法

第一个变体将局部变量存储在红色区域中,该区域位于堆栈指针下方的128个字节区域中,signal处理程序不会更改该区域。第二种变体不能使用红色区域,因为callq指令写入(原始)红色区域,从而破坏了存储在其中的局部变量。 (当然,被调用的函数也可以写入原始的红色区域。)

%eax设置为零,因为函数定义未声明任何原型,因此编译器必须假定它是可变参数函数。 %eax(实际上是%al)用于optimize the implementation of variadic functions

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...