You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用fasm编写64位Windows Hello World:宏代码无输出问题排查

Win64 FASM 宏版本HelloWorld无输出问题排查

你遇到的问题核心大概率是栈对齐破坏、字符串寻址错误或参数传递顺序不符Win64约定,结合你提到的rsp和message地址差异,具体分析如下:

1. 栈对齐问题(RSP操作差异)

Win64调用约定强制要求:调用API前栈必须保持16字节对齐,且需要预留32字节的shadow space(用于被调用方保存RCX/RDX/R8/R9寄存器)。

  • 无宏版本你可能手动做了正确的栈调整(比如sub rsp, 32),确保了对齐;
  • 但win64ax.inc的invoke宏已经自动处理了shadow space和栈对齐,如果你额外手动修改了RSP(比如重复sub rsp, 8或sub rsp, 32),会直接破坏16字节对齐,导致API调用失败(MessageBox不会执行)。

排查方式:对比反汇编中调用MessageBox前的RSP值,宏版本若比无宏版本多了额外的栈偏移,删掉手动的RSP调整代码。

2. 字符串寻址错误(Message地址差异)

Win64 PE文件运行时采用动态基址,访问数据必须用RIP相对寻址(而非32位绝对地址)。

  • 无宏版本你可能用了lea rcx, [rel message]这种正确的RIP相对寻址;
  • 宏版本若生成了mov rcx, message(绝对地址),运行时该地址会指向无效内存,MessageBox因接收错误的字符串参数(空或无效指针)而不显示。

排查方式:反汇编看宏版本传递字符串的指令,若不是lea rcx, [rip+xxxx],检查win64ax.inc的addr宏是否正确配置,或手动在字符串前加rel前缀(比如lea rcx, [rel msg_text])。

3. 参数传递顺序不符约定

Win64调用约定规定前4个参数依次放入RCX、RDX、R8、R9,对应MessageBoxA的参数顺序是:
MessageBoxA(hWnd, lpText, lpCaption, uType)

  • 若invoke宏错误地颠倒了参数顺序(比如把字符串放到RCX位置,当成窗口句柄),MessageBox会因参数无效而不触发弹窗。

排查方式:对比无宏版本和宏版本的寄存器赋值,确认RCX(窗口句柄,通常为NULL)、RDX(消息文本)、R8(标题)、R9(弹窗类型)的内容是否对应。

正确的宏版本示例代码

format PE64 GUI 4.0
entry start

include 'win64ax.inc'

section '.text' code readable executable
start:
    invoke MessageBoxA, NULL, msg_text, msg_title, MB_OK
    invoke ExitProcess, 0

section '.data' data readable writeable
msg_title db 'Hello', 0
msg_text db 'Hello World!', 0

section '.idata' import data readable writeable
library kernel32, 'kernel32.dll', user32, 'user32.dll'
import kernel32, ExitProcess, 'ExitProcess'
import user32, MessageBoxA, 'MessageBoxA'
  • 注意:如果是控制台输出(比如用WriteConsole),需把format PE64 GUI 4.0改成format PE64 CONSOLE,否则控制台窗口会一闪而过或无输出。

内容的提问来源于stack exchange,提问作者Thomas S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:25:26