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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:37:12