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。
您在调用之前有一个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)。