c - 为什么在从 gcc 编译的 C "Hello World"程序调用 printf x86 程序集之前修改 %al 寄存器和堆栈

标签 c x86 x86-64

我正在努力更好地理解编译器和汇编,目前正在努力理解为什么这个简单的“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/

相关文章:

c - 使用 fwrite 函数在 C 中写入 txt 文件

C while无限循环打印错误

将CPU切换到用户模式和内核模式的汇编指令?

C 纤维在 printf 上崩溃

c - 如何防止gcc优化破坏rep movsb代码?

c - C中的静态局部变量是什么意思?

c - c 指针段错误

debugging - IDE工具选择-跨平台x86 ASM调试

assembly - x86 - 通过 RETF 从 32 位切换到 64 位

assembly - 使用 gdb 检查寄存器的值