为什么 printf 是在本地定义的,而 getchar 是在外部定义的?
Why is printf defined locally as opposed to getchar, which is defined externally?
在 MASM(x86 架构)中使用汇编语言时,可以通过包含库来使用标准 C 函数。例如:printf
和 getchar
。
在 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 库函数)。
在 MASM(x86 架构)中使用汇编语言时,可以通过包含库来使用标准 C 函数。例如:printf
和 getchar
。
在 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 库函数)。