- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下是 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:我删除了部分汇编代码,以便我可以发布问题。
最佳答案
VS2015 及更高版本现在在头文件中包含 printf 的部分代码(以前它只是一个基于库的函数)。对于 C/C++,这不是问题,但就我而言,对于仅汇编项目,我现在在调用 printf 的项目中包含一个小的 C 源文件,该文件生成所需的代码,以便汇编代码可以调用 printf没有与 header 包含的代码相关的所有其他内容。
What exactly does the first function do?
__local_stdio_printf_options 返回一个指向静态整数的指针,该指针用作 __stdio_common_vfprintf 的输入。
How do we have the _vprintf_l function in the object file?
这是因为部分 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
关于c - C 语言 hello world 程序的汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47948234/
我的 CS2 讲师给出了一个 java 正则表达式,用于检查单词是否重复: \\b(\\w+)\\s+\\1\\b 如何修改它来检查某个单词是否重复两次,如“hello hello hello”或“h
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
这个问题已经有答案了: printf anomaly after "fork()" (3 个回答) 已关闭 3 年前。 #include #include Void main() { Printf
我一直在分配以下作业来解释 3 个语句中发生的事情,但我无法弄清楚。 cout << ("hello" + 1); // ello cout << (*"hello") + 1; // 10
如何确定用户是否使用 hello.js 登录? 使用 Google Sign-In SDK,我可以使用 gapi.auth2.init() 注册回调,当设置 SDK 并准备好回答诸如“你是登录了吗?”
执行String S1 = "hello";后,JVM将在SCP中创建一个String对象,该对象将在value字段中保存一个字符数组,如 s1.value = {'h', 'e', 'l', 'l'
我正在 build gomobile Hello示例应用程序,但遇到以下问题:在 Xcode (7.1) 中打开应用程序后尝试构建并运行该应用程序时,出现错误“找不到 hello/Hello.h”文件
#coding=utf-8 '''Tkinter module''' from Tkinter import * import time root=Tk() t=Text(root,fg='red')
在C/C++中,下面两行代码有什么区别: char *str1="hello"; char *str2={"hello"}; 最佳答案 根据 2011 C 标准,条款 6.7.9 初始化,第 11
我对在 android studio 中导入 import.hello.Hello 时出错有疑问,如下图所示。请给我解决方案如何解决这个错误 最佳答案 请参阅此处 @Arpit Patel answe
hello/ 忽略文件夹结构中任何位置名为“hello”的所有文件夹 hello/* 仅忽略顶级文件夹“hello”。 这是为什么?请指出http://git-scm.com/docs/gitigno
请解释以下程序中发生了什么。 我在程序的开头和结尾检查了 strerror(errno) 返回的地址,并确认它每次都返回相同的地址。然后一旦确定这一点,在第一种情况下我继续将相同的地址分配给 ptr,
在整个互联网上你都会看到这个命令 alias hello='echo Hello' 是的,我知道以上是一个蹩脚的例子,但它不是重点。如果我执行它,它就会起作用。但是当我重新启动计算机时,它丢失了。为什
我正在学习 C++ 指针,而 -> 运算符对我来说似乎很奇怪。代替ptr->hello(); 可以写成 (*ptr).hello(); 因为它似乎也可以工作,所以我认为前者只是更方便方式。 是这样还是
这个问题在这里已经有了答案: About the changing id of an immutable string (5 个回答) 关闭4年前。 为什么 "hello"is "hello" 在 P
我需要Prolog的源代码,它用于与Weka连接,并且能够在Windows环境下使用Weka算法进行预测。我尝试通过 Java 连接,但无法使用 Java 和 Prolog 进行连接和预测。 最佳答案
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Capitalize First Char of Each Word in a String Java 编写进行以下
当我在 ruby 控制台中运行以下示例时,我感到很惊讶。它们都产生相同的输出。 "hello".length 和 "hello" .length ruby
我创建了一个Hello World应用,系统生成了下面大部分的Android语言。在没有 System.out 语句的情况下运行应用程序时,模拟器中不会显示“Hello”。然后,使用 Eclipse
是的,所以我正在制作一个沼泽标准 Hello world 以确保 android 正常工作。这是我第一次使用 android,所以我正在设置环境。我按照以下程序制作了程序:http://develop
我是一名优秀的程序员,十分优秀!