NASM+WCC+WLINK(OW1.9)常量数据寻址异常问题求助
问题分析与解决方案
根因定位
问题的核心是Open Watcom链接器默认将数据段对齐到2字节边界:当代码段总长度为奇数时,链接器会在代码段末尾自动填充1字节空数据,让数据段起始地址对齐到偶数位。这导致C代码中字符串常量的实际运行时偏移,比编译期计算的偏移多了1字节,从而出现偶发跳过首字符的现象(添加奇数个nop会改变代码段长度的奇偶性,触发或消除填充)。
解决方案
方案1:修改C编译参数,禁用数据对齐
在wcc编译命令中添加-za1参数,强制数据按1字节对齐,避免链接器自动填充:
wcc -d0 -wx -we -ecc -ei -zpw -2 -od -zl -zld -zls -s -za1 os/src/main.c -fo=os/obj/main.obj
方案2:修改链接器脚本,全局设置1字节对齐
在os.lnk配置文件中添加OPTION ALIGN=1,强制所有段按1字节对齐:
FILE os/obj/start.obj FILE os/obj/main.obj FILE os/obj/bios.obj FORMAT RAW BIN NAME os/bin/os.bin OPTION NODEFAULTLIBS OPTION START=start_ OPTION MAP=os/lst/os.map OPTION VERBOSE OPTION ALIGN=1
方案3:显式定义汇编代码的段对齐
在汇编文件(start.asm和bios.asm)开头添加段定义,指定1字节对齐,确保和C代码的段属性一致:
; start.asm section .text align=1 global start_ global _putc start_: cli mov ax, 0x1000 mov ds, ax mov es, ax mov ss, ax mov sp, 0xFFFE mov bp, sp call _main ; 注意:Open Watcom会将C的main编译为_main,原代码的main_是错误命名 _halt: hlt jmp _halt
; bios.asm section .text align=1 global _putc _putc: push bp mov bp, sp push ax push bx mov ah, 0x0E mov al, [bp+4] mov bh, 0 mov bl, 0 int 0x10 pop bx pop ax pop bp ret
验证方法
修改完成后,查看os/lst/os.map文件,确认代码段和数据段的起始偏移连续无填充;同时用NDISASM反编译os/bin/os.bin,检查字符串Hello!的起始偏移与C代码中引用的地址是否一致。
内容的提问来源于stack exchange,提问作者Alessandro Giancane
相关产品推荐
相关产品推荐

