TASM中.386模式下解决数据段32位假设及程序崩溃问题
解决你的DOSBox汇编程序问题:.386兼容与跳转优化
我来帮你搞定这两个头疼的问题,先从.386伪指令导致的延迟宏错误说起,再优化那些繁琐的跳转中继。
问题1:切换到.386后Delay宏触发Illegal Read/Write错误
原因分析
当你使用.386伪指令时,汇编器会允许生成32位指令,而DOSBox模拟的是16位实模式环境。你原来用的INT 15h 86h(等待指定时间)功能,在32位指令存在的情况下,DOSBox对寄存器的模拟可能出现冲突——比如误将16位的CX/DX当成32位的ECX/EDX处理,导致非法内存访问。
解决方案:改用兼容16/32位的延迟实现
放弃INT 15h,改用DOS的INT 21h 2Ch功能(获取系统时间)来实现延迟,这个方法在任何实模式汇编环境下都稳定:
delay macro local wait_loop, check_time push ax push dx mov ah, 2Ch int 21h ; 获取当前时间:CH=小时,CL=分,DH=秒,DL=百分秒 mov bl, dl ; 保存当前的百分秒值 wait_loop: int 21h ; 再次读取时间 cmp dl, bl je wait_loop ; 直到百分秒发生变化(约10ms延迟) pop dx pop ax endm
如果你坚持想用INT 15h,也可以在宏里显式保存/恢复32位寄存器,避免破坏:
delay macro push ecx push edx mov cx, 0fh mov dx, 4240h mov ah, 86h int 15h pop edx pop ecx endm
问题2:简化繁琐的条件跳转中继
你现在用的to_printHundred: jmp printHundred这种中继完全没必要,可以直接让条件跳转到最终目标标签,省去中间的冗余跳转。
比如原来的代码:
cmp percentage, 64h je to_printHundred to_printHundred: jmp printHundred
可以直接改成:
cmp percentage, 64h je printHundred
这样既简化了代码,又减少了一次跳转的开销,逻辑也更清晰。
修改后的完整代码
这里是整合了两个优化后的完整程序,切换到.386也能正常运行:
.386 .model small setCurPos macro x,y pusha mov ah, 02h mov bh, 0 mov dl, x mov dh, y int 10h popa endm writeChar macro char,color,ctr pusha mov ah, 9 mov al, char mov bh, 0 mov bl, color mov cx, ctr int 10h popa endm ; 优化后的delay宏 delay macro local wait_loop, check_time push ax push dx mov ah, 2Ch int 21h ; 获取当前时间:CH=小时,CL=分,DH=秒,DL=百分秒 mov bl, dl ; 保存当前的百分秒值 wait_loop: int 21h ; 再次读取时间 cmp dl, bl je wait_loop ; 直到百分秒发生变化(约10ms延迟) pop dx pop ax endm .stack 100h .data percentage db 0 ones db ? tens db ? .code org 100 main proc far mov ax, @data mov ds, ax mov es, ax mov ah, 0 mov al, 13h mov bh, 0 int 10h jmp count count: delay cmp percentage, 64h je printHundred ; 直接跳转到最终目标,省去中继 cmp percentage, 0ah jae printTens ;printOnes mov al, percentage add al, 30h mov ones, al setCurPos 10, 10 writeChar ones, 0fh, 1 inc percentage jmp count printTens: xor ax, ax mov bx, 0ah mov al, percentage div bl add al, 30h add ah, 30h mov tens, al mov ones, ah setCurPos 10,10 writeChar tens,0fh,1 setCurPos 11,10 writeChar ones,0fh,1 inc percentage jmp count printHundred: mov tens, 31h mov ones, 30h setCurPos 10,10 writeChar tens,0fh,1 setCurPos 11,10 writeChar ones,0fh,2 mov ah, 4ch int 21h endp end main
内容的提问来源于stack exchange,提问作者Mc Henry
相关产品推荐
相关产品推荐

