如何在Visual Studio 2017的x86程序集中使用printf?

Mik*_*e D 2 x86 assembly masm visual-studio

MASM1.exe中0x777745BA(ntdll.dll)处未处理的异常:0xC0000005:访问冲突写入位置0x00000014。我在Visual Studios 2017中使用x86程序集,并且不断返回此错误

我已包含所有库并安装了Windows 10 SDK。对于为什么在第21行返回此错误,我感到很困惑。它甚至打开一个空白窗口,然后立即将其关闭并返回错误。

            .586
            .MODEL FLAT
            .STACK 4096
            includelib libcmt.lib
            includelib libvcruntime.lib
            includelib libucrt.lib
            includelib legacy_stdio_definitions.lib
            EXTERN  printf:PROC
            EXTERN  scanf:PROC

            .DATA
                format BYTE "Enter a number", 0

            .CODE

            main PROC
                sub esp, 4
                push offset format
                call printf
                add esp, 4
                ret
            main ENDP
            END
Run Code Online (Sandbox Code Playgroud)

我创建了一个VS 2017 C ++项目,生成一个Win32控制台程序。在项目属性/ Linker/ Advanced/ entry point选项我已经设置的入口点main

Pet*_*des 5

您在调用之前有一个sub esp,4and一个push,因此要还原堆栈指针以指向您需要在before之前的返回地址,而不是add esp,8retadd esp, 4

printf是一个可变参数功能,所以它并没有跳出自己的ARGS堆栈。它使用cdecl调用约定。)

或者更好的是删除sub esp,4

32位Windows仅维护4字节堆栈对齐,因此您无需在push/ 之前对ESP进行任何额外操作,call即可使堆栈指针在-之前重新对齐call。而且您没有使用为任何内容保留的那4个字节。


更新:MichaelPetch观察到您的程序可能在内部 崩溃printf,因为您在未初始化libc的情况下调用了该程序。可能您正在使用此功能作为入口点来构建程序,而不是从常规C启动代码中调用。 (并且Visual Studio调试器错误地将崩溃报告为call,而不是崩溃实际发生的位置。)


您的错误消息似乎仍然来自问题的第一个版本,而您在此处省略了ret!在这种情况下,执行仅落在main下一个字节的末尾,将它们解码为指令。可能为零。

00 00解码为add [eax], al,并eax从printf的返回值中保留14。(printf返回字符数printf,并且格式字符串的长度为14个字节)。

但是错误消息是关于写入address的0x14,它是十进制20(16 + 4),所以我的第一个猜测并没有完全加起来。 如果您想知道,请使用调试器查找实际发生故障的指令,然后查看寄存器值。 您可能必须使用反汇编视图而不是asm源代码视图,尤其是对于版本末尾的版本main


如果stdout是行缓冲的,则屏幕上可能没有任何输出,并且printf格式字符串不以换行符结尾。因此,当您崩溃时,字符串仍位于IO缓冲区中。(尽管IIRC printf在Windows上不是那样,并且fflush()即使缓冲区没有以换行符结尾,也会执行该缓冲区。)

使用puts打印固定字符串(无%转换),并追加一个换行符。即puts(x)就像printf("%s\n", x)

  • 实际上,调试器实际上是在printf调用内发生的,调试器将在第21行(add esp,4)错误地显示该错误,而我将其重现的方式(一直到0x00000014)可以防止该错误。 _C_运行时启动代码的执行(通过使程序成为“ main”程序的入口点)而不是_C_运行时代码中的默认入口点。我的意见是问题更多是关于他们如何组装和链接,这是他们不提供的信息:( (2认同)
  • @Michael Petch和Peter Cordes这是我删除入口点main的入口点,这就是修复它的原因。谢谢您的时间和信息。你们都帮了我很多忙。再次感谢你 (2认同)