为何无法通过DS段寄存器访问变量?实模式8086汇编故障排查
问题根源:未正确初始化DS寄存器,且中断回调时DS未必指向data段
核心错误1:主程序未初始化DS为data段地址
ASSUME ds:data只是给汇编器的提示,告诉它「把DS寄存器和data段关联起来计算内存地址」,但不会自动把data段的段地址加载到CPU的DS寄存器里。
DOS加载程序时,DS寄存器默认指向程序的PSP(程序段前缀),而不是你定义的data段。所以主程序里访问ds:default_vec8、回调里访问ds:position时,实际操作的是PSP区域的内存,不是你定义的变量,自然出错。
解决方法:在main PROC开头添加初始化DS的代码:
main PROC ; 初始化DS指向data段 mov ax, data mov ds, ax ; Initialize text mode mov al, 0 mov ah, 5 int 10 ...
核心错误2:中断回调时DS可能被外部修改
即便主程序初始化了DS,中断可能在任何时机触发(比如DOS的int 16h调用过程中,或者系统其他中断),此时CPU的DS寄存器可能已经被修改为其他值,导致回调里的ds:position依然访问不到正确的data段。
这也是为什么把变量移到code段就能正常工作的原因:回调函数的CS寄存器是我们设置的code段(中断向量里存了code段的地址),访问cs:position时,CS始终指向code段,不会出错。
更严谨的解决方法:
在回调函数开头手动加载并保护DS,避免外部修改的影响(需遵守DOS中断的寄存器约定,修改DS后要恢复原值):
callback PROC push fs push bx push ax push ds ; 保存原来的DS值 mov ax, data ; 手动加载data段到DS mov ds, ax mov bx, VRAM_SEGMENT mov fs, bx mov bx, ds:position ; 后续操作代码... pop ds ; 恢复原来的DS pop ax pop bx pop fs jmp DWORD PTR ds:default_vec8 callback ENDP
内容的提问来源于stack exchange,提问作者sajmon
相关产品推荐
相关产品推荐

