从进程入口点调用printf时触发访问违例问题排查
Windows x64汇编Hello World程序访问违例问题
我是汇编语言初学者,正在使用Visual Studio 2022编写Windows平台下的Hello World程序,但无论尝试何种方式,始终遇到相同错误。已查阅相关资料,代码看起来并无问题,肯定遗漏了某些细节。
汇编代码
includelib libcmt.lib includelib libvcruntime.lib includelib libucrt.lib includelib legacy_stdio_definitions.lib ExitProcess proto printf proto .data fmt byte "%s",13,10,0 hello byte "Hello world!",0 .code main proc push rbp mov rbp, rsp sub rsp, 40 lea rcx, fmt lea rdx, hello call printf add rsp, 40 mov rcx, 0 call ExitProcess main endp end
错误信息
调用printf时触发访问违例,程序在执行到函数收尾代码前崩溃:
Exception thrown at 0x00007FFF2FAD34F6 (ntdll.dll) in hello_world.exe: 0xC0000005: Access violation writing location
链接器命令行
/OUT:"x64\Debug\hello_world.exe" /MANIFEST /NXCOMPAT /PDB:"x64\Debug\hello_world.pdb" /DYNAMICBASE "libucrt.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X64 /ENTRY:"main" /INCREMENTAL /PGD:"x64\Debug\hello_world.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\hello_world.exe.intermediate.manifest" /LTCGOUT:"x64\Debug\hello_world.iobj" /ERRORREPORT:PROMPT /ILK:"x64\Debug\hello_world.ilk" /NOLOGO /TLBID:1
问题原因及解决方案
核心问题
错误根源在于跳过了C运行时(CRT)的初始化流程:你在链接器命令行中指定了/ENTRY:"main",直接将自己写的main作为程序入口,但正常情况下,Visual Studio的CRT会通过默认入口(如mainCRTStartup)完成全局环境初始化、IO缓冲区设置等必要操作,再调用你的main函数。跳过这一步会导致printf等CRT函数因依赖未初始化的资源而触发访问违例。
解决步骤
- 移除链接器的
/ENTRY:"main"参数:
在Visual Studio中,右键项目 → 属性 → 链接器 → 高级 → 入口点,清空该字段,让链接器使用默认的CRT入口。这样CRT初始化代码会自动执行,printf就能正常工作。 - 栈对齐验证:
你的代码中sub rsp, 40是正确的:x64 Windows调用约定要求调用者为被调用函数预留32字节的shadow space,加上push rbp导致的8字节栈偏移,总共40字节调整后,栈指针(rsp)在调用printf前保持16字节对齐,符合调用约定要求,无需修改。
内容的提问来源于stack exchange,提问作者user2187032
相关产品推荐
相关产品推荐

