MASM汇编骰子游戏异常排查:胜负判定错误及崩溃问题
问题排查与修复方案
核心问题分析
你的代码出现胜负判定错误(如玩家1点、电脑5点却显示"You Win!"),大概率是寄存器被意外修改导致的。虽然DOS中断int 21h的09h功能理论上会保留bx寄存器,但部分DOS兼容环境或汇编器可能存在异常,导致存储在bl、bh中的点数被意外篡改,进而让比较逻辑失效。
另外,随机数生成部分存在小瑕疵:使用16位除法div bx时,余数存储在16位寄存器dx中,虽然当前逻辑(取dl)能得到正确的0-5余数,但可以优化为更简洁的8位除法,避免潜在的寄存器混淆。
修复后的完整代码
.model small .stack 100h .data msg_sep db 13,10,'----------------------',13,10,'$' msg1 db 13,10,'Your roll: $' msg2 db 13,10,'Computer roll: $' msg_win db 13,10,'You Win!$' msg_lose db 13,10,'You Lose!$' msg_draw db 13,10,'Draw!$' ; 使用内存变量存储点数,避免寄存器被篡改 user_roll db ? comp_roll db ? .code start: mov ax, @data mov ds, ax loop_start: ; 输出分隔线 lea dx, msg_sep mov ah, 09h int 21h ; 生成玩家点数 call get_random mov user_roll, dl ; 存储到内存变量 lea dx, msg1 mov ah, 09h int 21h mov dl, user_roll add dl, '0' mov ah, 02h int 21h ; 生成电脑点数 call get_random mov comp_roll, dl ; 存储到内存变量 lea dx, msg2 mov ah, 09h int 21h mov dl, comp_roll add dl, '0' mov ah, 02h int 21h ; 胜负判定(使用内存变量比较,不受寄存器修改影响) mov al, user_roll cmp al, comp_roll je draw jb user_lose ja user_win user_win: lea dx, msg_win mov ah, 09h int 21h jmp wait_key user_lose: lea dx, msg_lose mov ah, 09h int 21h jmp wait_key draw: lea dx, msg_draw mov ah, 09h int 21h jmp wait_key wait_key: mov ah, 08h ; 无回显读取键盘输入 int 21h jmp loop_start ; 优化后的随机数生成函数(8位除法,逻辑更简洁) get_random: mov ah, 00h int 1Ah ; 获取系统计时器:CX=高16位,DX=低16位 mov al, dl ; 取计时器低8位作为随机源 xor ah, ah ; 将AL扩展为16位AX(AH清零) mov bl, 6 div bl ; 8位除法:AX / BL,余数存AH(0-5),商存AL mov dl, ah add dl, 1 ; 转换为1-6的点数 ret end start
关键修复点
- 用内存变量存储点数:将原代码中存储在
bl、bh的点数改为存储到user_roll、comp_roll内存变量中,彻底避免寄存器被意外修改导致的比较错误。 - 优化随机数生成:改用8位除法
div bl,逻辑更清晰,减少16位寄存器操作带来的潜在问题。 - 保持原有功能不变:保留了原程序的所有交互逻辑,仅修复核心问题。
崩溃问题说明
程序崩溃大概率是由于寄存器异常修改导致的内存访问错误,修复上述问题后,崩溃情况应该会消失。如果仍出现崩溃,可检查DOS环境的兼容性,或尝试增大栈空间(将.stack 100h改为.stack 200h)。
内容的提问来源于stack exchange,提问作者LEE
相关产品推荐
相关产品推荐

