我正在努力更好地理解编译器和汇编,目前正在努力理解为什么这个简单的“Hello, World”程序在调用 printf 之前修改堆栈和 %al 寄存器。
这是 gcc 生成的程序集,优化关闭(一些编译器指令已被删除):
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
movl $0, -4(%rbp)
movb $0, %al
callq _printf
xorl %ecx, %ecx
movl %eax, -8(%rbp) ## 4-byte Spill
movl %ecx, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "Hello, World!\n"
这是(非常简单的)C 程序:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
我特别想知道在“call _printf”指令之前的两行中发生了什么。似乎堆栈的一部分被清零了,%al 也注册了,但我不知道为什么。
我也很困惑为什么 %ecx 寄存器在返回之前被清除并填充了 %eax 的内容,我认为这是 printf 的返回值。
在此先感谢您的帮助。
最佳答案
清理 %ecx
并转移到%eax
只是确保主函数返回 0。就在这之前,_printf
的返回值函数复制自 %eax
使用 movl %eax, -8(%rbp)
到堆栈帧,但是当堆栈开始使用 addq $16, %rsp
释放帧时,这个值被简单地丢弃了说明。
关于c - 为什么在从 gcc 编译的 C "Hello World"程序调用 printf x86 程序集之前修改 %al 寄存器和堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54155419/