c - 如果我不包含标题,为什么在调用函数之前清除 EAX?

标签 c assembly x86-64 calling-convention

在以下 C 代码中:

#include <stdio.h>
int main(void){getchar();}
它产生以下汇编:
main:
        push    rbp
        mov     rbp, rsp
                 # no extra instruction here when header is included
        call    getchar
        mov     eax, 0
        pop     rbp
        ret
但是,如果我不包括 stdio.h在文件中,然后它仍然编译,但添加了看起来像随机的 mov eax, 0操作说明:
enter image description here
这是编译器资源管理器:https://godbolt.org/z/3fTcss .这只是“未定义行为”的一部分,还是有特殊原因导致 call getchar 之前的指令?在那里添加?

最佳答案

如果没有标题,gcc 提供了一个隐式声明 getchar当你使用它时,就好像你之前已经声明过一样

int getchar();
(此行为由旧版本的 C 标准保证。当前版本使使用先前未声明的函数成为未定义行为,但 gcc 仍提供旧行为作为扩展。)
此声明不提供有关参数类型的信息 getchar期待。 (请记住,与 C++ 不同的是,带有 () 的声明不会将函数声明为不带参数,而是带未指定的参数,让程序员知道函数期望什么并传递正确数量和类型的参数。)对于所有编译器都知道的,它甚至可以是可变参数,并且根据 x86-64 SysV ABI,可变参数函数期望在 al 中。用于传递参数的 vector 寄存器的数量。这里没有使用 vector 寄存器,所以编译器设置 al0在通话之前。 (实际上将 rax 全部归零会更有效,所以它会这样做。)

关于c - 如果我不包含标题,为什么在调用函数之前清除 EAX?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66572227/

相关文章:

C、数学字符串计算?

c - 这个程序如何知道存储这个字符串的确切位置?

linux - Perf 启动开销 : Why does a simple static executable which performs MOV + SYS_exit have so many stalled cycles (and instructions)?

linux - 汇编 - 将参数传递给函数调用

C数组指针段错误

使用正则表达式 c 检查 url

c - 使用 MPI 收集来自不同流程的小矩阵部分

c - 'asm' 、 '__asm' 和 '__asm__' 之间有什么区别?

c - 当 -mavx2 打开时为 __builtin_popcount 生成臃肿的代码

assembly - PE 二进制文件中的部分名称真的有限制吗?