x64 MASM程序调用Windows API输出字符串无结果求助
问题排查与修复方案
你这段代码有几个关键问题,导致控制台无输出:
核心问题分析
1. 变量类型不匹配(最关键)
WriteConsoleA的第四个参数要求是指向32位整数的指针,但你定义的message_size是DW(16位字类型)。当API尝试往这个地址写入4字节的实际输出长度时,会越界覆盖栈内其他数据,直接导致调用失败或后续执行异常。
2. 缺少API调用错误检查
你没检查GetStdHandle的返回值——如果获取标准输出句柄失败(比如环境异常),后续调用WriteConsoleA肯定不会有输出。
补充:栈对齐细节
x64 Windows要求调用API前栈必须是16字节对齐。你代码里SUB RSP, 5*8其实刚好满足(进入main时RSP是8字节对齐,减40后变为16的倍数),所以这个不是核心问题,但给栈分配代码加注释会更便于维护。
修复后的代码
GetStdHandle PROTO ExitProcess PROTO WriteConsoleA PROTO .data message DB "Hello World",0 message_size DWORD ? ; 改为32位DWORD,匹配API要求的参数类型 .code main PROC ; 分配32字节阴影空间 + 8字节栈参数 = 40字节,保证16字节对齐 SUB RSP, 40 ; 获取标准输出句柄 MOV RCX, -11 CALL GetStdHandle ; 检查句柄是否无效(INVALID_HANDLE_VALUE = -1) CMP RAX, -1 JE ExitProg ; 句柄无效直接退出 ; 调用WriteConsoleA输出字符串 MOV RCX, RAX ; 参数1:标准输出句柄 LEA RDX, message ; 参数2:要输出的字符串指针 MOV R8, SIZEOF message - 1 ; 参数3:输出字节数(去掉末尾的空字符) LEA R9, message_size ; 参数4:接收实际输出长度的指针 MOV QWORD PTR [RSP + 32], 0 ; 参数5:预留参数,设为NULL CALL WriteConsoleA ExitProg: MOV RCX, 0 CALL ExitProcess main ENDP END
修复点说明
- 修正变量类型:把
message_size从DW改成DWORD,彻底解决内存越界问题,保证API能正常写入输出长度。 - 增加错误检查:添加句柄有效性判断,避免因无效句柄导致的无输出情况。
- 明确栈空间注释:给栈分配代码添加注释,清晰说明分配的空间用途,后续维护更方便。
内容的提问来源于stack exchange,提问作者Homayoon
相关产品推荐
相关产品推荐

