gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 06:27:06 25 4
gpt4 key购买 nike

MASM1.exe 中 0x777745BA (ntdll.dll) 处的未处理异常:0xC0000005:访问冲突写入位置 0x00000014。我在 Visual Studio 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

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

最佳答案

你有一个 sub esp,4 和一个 push 在调用之前,所以要恢复堆栈指针指向你需要的返回地址 add esp,8ret 之前,而不是 add esp, 4

(printf 是一个可变参数函数,因此它不会将自己的参数从堆栈中弹出。它使用 cdecl 调用约定。)

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

32 位 Windows 仅维护 4 字节堆栈对齐,因此您无需在 push/call 之前对 ESP 做任何额外的操作来获取堆栈指针在 call 之前重新对齐。而且你没有使用你为任何东西保留的那 4 个字节。


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


您的错误消息似乎仍然来自问题的第一个版本,您遗漏了 ret!在这种情况下,执行只是从 main 的末尾到接下来的任何字节,将它们解码为指令。可能是零。

00 00 解码为 add [eax], aleax 保存 printf 返回值的 14。 (printf 返回 printf 的字符数,你的格式字符串是 14 字节长)。

但错误信息是关于写入地址 0x14,即十进制 20 (16 + 4),所以我的第一个猜测并不完全符合。 如果您想知道,请使用调试器查找实际出错的指令,并查看寄存器值。您可能必须使用反汇编 View 而不是 asm 源代码 View ,尤其是对于您使用的版本从 main 的末尾掉下来。


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

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

关于visual-studio - 如何在 Visual Studio 2017 的 x86 程序集中使用 printf?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56100677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com