以下是hello world程序的示例代码:
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
这是对象文件的反汇编:我有:
File Type: COFF OBJECT
main:
0000000000000000: 48 83 EC 28 sub rsp,28h
0000000000000016: C3 ret
__local_stdio_printf_options:
0000000000000000: 48 8D 05 00 00 00 lea rax,[?_OptionsStorage@?1??__local_stdio_printf_options@@9@9]
00
0000000000000007: C3 ret
_vfprintf_l:
0000000000000000: 4C 89 4C 24 20 mov qword ptr [rsp+20h],r9
0000000000000014: 48 83 EC 38 sub rsp,38h
0000000000000018: E8 00 00 00 00 call __local_stdio_printf_options
0000000000000039: E8 00 00 00 00 call __stdio_common_vfprintf
000000000000003E: 48 83 C4 38 add rsp,38h
0000000000000042: C3 ret
printf:
0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
0000000000000027: E8 00 00 00 00 call __acrt_iob_func
000000000000002C: 4C 8B 4C 24 28 mov r9,qword ptr [rsp+28h]
000000000000003C: E8 00 00 00 00 call _vfprintf_l
0000000000000041: 89 44 24 20 mov dword ptr [rsp+20h],eax
000000000000004E: 8B 44 24 20 mov eax,dword ptr [rsp+20h]
0000000000000056: C3 ret
在printf
函数中,我们还有两个函数调用:__acrt_iob_func
和_vfprintf_l
。
第一个功能到底是做什么的?
我们如何在目标文件中使用_vprintf_l
函数?
详细解释将不胜感激。
已编译: cl /TC main.cpp
反汇编: dumpbin /disasm main.obj
PS:我部分删除了汇编代码,以便发布问题。
答案 0 :(得分:2)
VS2015及更高版本现在包含头文件中printf的部分代码(以前它只是一个基于库的函数)。对于C / C ++,它不是一个问题,但在我的情况下,对于本来只有汇编的项目,我现在在项目中包含一个调用printf的小C源文件,它生成所需的代码以便汇编代码可以调用printf而不包含与包含头代码相关的所有其他内容。
第一个功能到底是做什么的?
__ local_stdio_printf_options返回一个指向静态整数的指针,该整数用作__stdio_common_vfprintf的输入。
我们如何在目标文件中使用_vprintf_l函数?
这是因为printf代码的一部分现在包含在头文件中,之前所有printf都包含在标准C库中。
这是当前本地printf实例所包含内容的片段。我没有推断出这两个定义,但最终结果可以在下面的汇编代码中看到。
__inline unsigned __int64* __CRTDECL __local_stdio_printf_options(void)
{
static unsigned __int64 _OptionsStorage;
return &_OptionsStorage;
}
#define _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS (*__local_stdio_printf_options())
_CRT_STDIO_INLINE int __CRTDECL _vfprintf_l(
_Inout_ FILE* const _Stream,
_In_z_ char const* const _Format,
_In_opt_ _locale_t const _Locale,
va_list _ArgList
)
{
return __stdio_common_vfprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, _Stream, _Format, _Locale, _ArgList);
}
_CRT_STDIO_INLINE int __CRTDECL printf(
_In_z_ _Printf_format_string_ char const* const _Format,
...)
{
int _Result;
va_list _ArgList;
__crt_va_start(_ArgList, _Format); /* this is a define */
_Result = _vfprintf_l(stdout, _Format, NULL, _ArgList);
__crt_va_end(_ArgList); /* this is a define */
return _Result;
}
VS2015的汇编输出片段使得它更加清晰。同样,请记住,所有这些都是printf的内部,并且可能会随着Visual Studio的更高版本而改变。
CONST SEGMENT
??_C@_0P@DOOKNNID@Hello?0?5world?$CB?6?$AA@ DB 'Hello, world!', 0aH, 00H
CONST ENDS
_TEXT SEGMENT
__local_stdio_printf_options PROC
lea rax, OFFSET FLAT:?_OptionsStorage@?1??__local_stdio_printf_options@@9@9 ;static variable
ret 0
__local_stdio_printf_options ENDP
_vfprintf_l PROC
; ...
call __local_stdio_printf_options ;local instance
; ...
call QWORD PTR __imp___stdio_common_vfprintf ;library function
; ...
ret 0
_vfprintf_l ENDP
printf PROC
; ...
call QWORD PTR __imp___acrt_iob_func ;library function
mov rbx, rax
call __local_stdio_printf_options ;local instance
; ...
call QWORD PTR __imp___stdio_common_vfprintf ;library function
ret 0
; ...
printf ENDP
main PROC
sub rsp, 40 ; 00000028H
lea rcx, OFFSET FLAT:??_C@_0P@DOOKNNID@Hello?0?5world?$CB?6?$AA@
call printf
xor eax, eax
add rsp, 40 ; 00000028H
ret 0
main ENDP
_TEXT ENDS
这是VS先前版本的程序集输出,其中printf只是一个库函数(__imp_printf):
CONST SEGMENT
??_C@_0P@DOOKNNID@Hello?0?5world?$CB?6?$AA@ DB 'Hello, world!', 0aH, 00H
CONST ENDS
_TEXT SEGMENT
main PROC
sub rsp, 40 ; 00000028H
lea rcx, OFFSET FLAT:??_C@_0P@DOOKNNID@Hello?0?5world?$CB?6?$AA@
call QWORD PTR __imp_printf
xor eax, eax
add rsp, 40 ; 00000028H
ret 0
main ENDP
_TEXT ENDS
答案 1 :(得分:1)
__acrt_iob_func
是Microsoft Visual C中的内部 C 运行时(CRT)函数。
[They] are used internally to implement the standard C and C++ libraries
__acrt_iob_func
_acrt_iob_func
可能用于设置基本I / O ,例如分配 stdin stdout 和 stderr 以及
printf(3)
通常是围绕vprintf(3)
的包装函数,它将va_list
作为参数
答案 2 :(得分:-2)
编译器使用内置函数,主要是在linux下通过libc。这个内部版本可以在多个平台上运行,也有一些优化。如果您查询谷歌,您可以查看libc的源代码。 您还可以使用调试器跟踪函数,并确切了解它正在做什么。
总结一下,这取决于你的编译器和库的实现。你好世界也可以手工做得更短。