FASM编写DOS下Hello World程序x64环境运行失败求助
问题分析与解决方法
嘿,我来帮你拆解下这个问题哈!你现在的核心问题是把DOS实模式程序和64位Windows程序的运行逻辑完全混在一起了,这俩根本不是一个生态,自然跑不起来~
你的代码里的核心问题
- 格式与运行环境不匹配:你用了
format PE64(64位Windows的PE可执行格式),却调用了DOS专属的int 21h中断——x64 Windows完全不支持DOS中断!DOS中断是16位实模式下的产物,x64系统运行在长模式,这套中断机制早就被替换了,Windows 64位程序根本没法通过int 21h实现输出或退出。 - 错误的地址约定:
org 100h是16位DOS COM程序的起始地址规范,PE64格式完全不需要这个,PE程序的加载地址由Windows加载器统一管理,硬加这个只会导致地址混乱。 - 不符合64位程序规范:x64模式下虽然兼容16位寄存器(比如AX),但PE64程序的入口逻辑有严格规范,你直接上来就
mov ax, cs的写法完全不适用64位Windows环境。
两种正确的实现方案
1. 写可在DOS(或DOSBox)运行的16位程序
用DOS的COM格式,这是DOS下最简单的可执行格式,代码如下:
format binary as 'COM' org 100h ; DOS功能号09h:输出以$结尾的字符串 mov dx, msg mov ah, 09h int 21h ; DOS功能号4Ch:终止程序 mov ah, 4Ch int 21h msg db 'Hello, World!$'
说明:COM程序默认
CS=DS=ES=SS,所以不需要手动设置DS,编译后生成的.COM文件可以直接在DOSBox中运行。
2. 写可在x64 Windows运行的64位程序
需要用PE64格式,调用Windows系统API(而非DOS中断),FASM代码示例:
format PE64 Console entry start section '.data' data readable writeable ; 字符串结尾添加回车换行,0为字符串终止符 msg db 'Hello, World!', 0Dh, 0Ah, 0 section '.text' code readable executable start: ; x64 Windows API要求分配32字节阴影空间并保持栈16字节对齐 sub rsp, 8*5 ; 调用WriteFile输出字符串到控制台 mov rcx, 1 ; 第一个参数:标准输出句柄(1) mov rdx, msg ; 第二个参数:待输出字符串地址 mov r8, 14 ; 第三个参数:字符串长度(含回车换行共14字节) mov r9, 0 ; 第四个参数:接收写入字节数的指针(此处设为0) mov qword [rsp+32], 0 ; 第五个参数:重叠结构指针(此处设为0) call [WriteFile] ; 调用ExitProcess终止程序 mov rcx, 0 ; 退出码设为0 call [ExitProcess] section '.idata' import data readable writeable ; 导入Kernel32.dll中的系统函数 library kernel32, 'KERNEL32.DLL' import kernel32, \ WriteFile, 'WriteFile', \ ExitProcess, 'ExitProcess'
说明:64位Windows程序必须通过系统API与系统交互,同时要遵守x64的调用约定:前4个参数使用
RCX/RDX/R8/R9传递,后续参数压栈,调用前需分配32字节的阴影空间并保证栈16字节对齐。
内容的提问来源于stack exchange,提问作者TheFnafException
相关产品推荐
相关产品推荐

