"sub , %rsp" 指令的用途是什么?
What is the "sub $16, %rsp" instruction being used for?
让我们采用以下基本 C 函数及其生成的有意未优化的程序集:
int main() {
int i = 4;
return 3;
}
它生成以下(未优化的)程序集,这对我来说很有意义:
main:
pushq %rbp
movq %rsp, %rbp
movl , -4(%rbp)
movl , %eax
popq %rbp
ret
但是,当我添加一个函数调用时,有两个指令我不太明白:
void call() {};
int main() {
int i = 4;
call();
return 3;
}
main:
pushq %rbp
movq %rsp, %rbp
subq , %rsp <-- why is it subtracting 16?
movl , -4(%rbp)
movl [=14=], %eax <-- why is it first clearing the %eax register?
call call
movl , %eax
leave
ret
如果堆栈帧需要 16 字节对齐,subq , %rsp
有何帮助?最初的 pushq %rbp
指令不是已经将它偏移了 8 而现在是 +24 吗?或者上面那两行的要点是什么?
第一个变体将局部变量存储在红色区域,堆栈指针下方的 128 字节区域未被 signal 处理程序更改。第二个变体不能使用红色区域,因为 callq
指令写入(原始)红色区域,破坏存储在那里的局部变量。 (当然,被调用的函数也可以写入原始的红色区域。)
%eax
设置为零,因为函数定义没有声明原型,因此编译器必须假定它是可变参数函数。 %eax
(实际上是%al
)用于optimize the implementation of variadic functions。
让我们采用以下基本 C 函数及其生成的有意未优化的程序集:
int main() {
int i = 4;
return 3;
}
它生成以下(未优化的)程序集,这对我来说很有意义:
main:
pushq %rbp
movq %rsp, %rbp
movl , -4(%rbp)
movl , %eax
popq %rbp
ret
但是,当我添加一个函数调用时,有两个指令我不太明白:
void call() {};
int main() {
int i = 4;
call();
return 3;
}
main:
pushq %rbp
movq %rsp, %rbp
subq , %rsp <-- why is it subtracting 16?
movl , -4(%rbp)
movl [=14=], %eax <-- why is it first clearing the %eax register?
call call
movl , %eax
leave
ret
如果堆栈帧需要 16 字节对齐,subq , %rsp
有何帮助?最初的 pushq %rbp
指令不是已经将它偏移了 8 而现在是 +24 吗?或者上面那两行的要点是什么?
第一个变体将局部变量存储在红色区域,堆栈指针下方的 128 字节区域未被 signal 处理程序更改。第二个变体不能使用红色区域,因为 callq
指令写入(原始)红色区域,破坏存储在那里的局部变量。 (当然,被调用的函数也可以写入原始的红色区域。)
%eax
设置为零,因为函数定义没有声明原型,因此编译器必须假定它是可变参数函数。 %eax
(实际上是%al
)用于optimize the implementation of variadic functions。