为什么 printf 是在本地定义的,而 getchar 是在外部定义的?

Why is printf defined locally as opposed to getchar, which is defined externally?

在 MASM(x86 架构)中使用汇编语言时,可以通过包含库来使用标准 C 函数。例如:printfgetchar

Visual Studio 中使用 Asembly With Source Code/FAs 进行编译并检查生成的汇编文件时,我偶然发现了以下内容:

PUBLIC  _printf
EXTRN   __imp__getchar : PROC

_printf 声明为 PUBLIC 并在 本地 定义(内联 在同一文件中,因此未定义在库文件的外部),而 _imp_getchar 被定义为 externally

这是编译器在 debug 中编译时生成的结果 _printf 定义:

_TEXT   SEGMENT
__ArgList$ = -20                    ; size = 4
__Result$ = -8                      ; size = 4
__Format$ = 8                       ; size = 4
_printf PROC                        ; COMDAT

; 950  : {

push    ebp
mov ebp, esp
sub esp, 216                ; 000000d8H
push    ebx
push    esi
push    edi
lea edi, DWORD PTR [ebp-216]
mov ecx, 54                 ; 00000036H
mov eax, -858993460             ; ccccccccH
rep stosd

; 951  :     int _Result;
; 952  :     va_list _ArgList;
; 953  :     __crt_va_start(_ArgList, _Format);

call    ??$__vcrt_va_start_verify_argument_type@QBD@@YAXXZ ; __vcrt_va_start_verify_argument_type<char const * const>
lea eax, DWORD PTR __Format$[ebp+4]
mov DWORD PTR __ArgList$[ebp], eax

; 954  :     _Result = _vfprintf_l(stdout, _Format, NULL, _ArgList);

mov eax, DWORD PTR __ArgList$[ebp]
push    eax
push    0
mov ecx, DWORD PTR __Format$[ebp]
push    ecx
mov esi, esp
push    1
call    DWORD PTR __imp____acrt_iob_func
add esp, 4
cmp esi, esp
call    __RTC_CheckEsp
push    eax
call    __vfprintf_l
add esp, 16                 ; 00000010H
mov DWORD PTR __Result$[ebp], eax

; 955  :     __crt_va_end(_ArgList);

mov DWORD PTR __ArgList$[ebp], 0

; 956  :     return _Result;

mov eax, DWORD PTR __Result$[ebp]

; 957  : }

pop edi
pop esi
pop ebx
add esp, 216                ; 000000d8H
cmp ebp, esp
call    __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
_printf ENDP
_TEXT   ENDS

我的问题

为什么 _printf 是在本地定义的,而 getchar 是在外部定义的?

printf 的代码就在您的列表中。如果删除程序集,您将得到:

; 950  : {
; 951  :     int _Result;
; 952  :     va_list _ArgList;
; 953  :     __crt_va_start(_ArgList, _Format);
; 954  :     _Result = _vfprintf_l(stdout, _Format, NULL, _ArgList);
; 955  :     __crt_va_end(_ArgList);
; 956  :     return _Result;
; 957  : }

因此,printf 是一个调用 _vfprintf_l 的(内联?)函数,它完成所有繁重的工作(并且可能也用于实现其他 C 库函数)。