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

时间:2015-12-07 09:58:19

标签: visual-studio assembly x86 masm

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

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

PUBLIC  _printf
EXTRN   __imp__getchar : PROC

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

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

_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,这是在外部定义的?

1 个答案:

答案 0 :(得分:3)

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库函数)。