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

MASM/UASM中DIV指令执行23÷10触发SIGFPE异常问题排查

问题分析与解决方案

你的问题核心是16位无符号除法指令DIV bx的使用规范被忽略,导致触发除法溢出异常(对应Linux下的SIGFPE信号)。

关键原因

DIV bx是16位无符号除法指令,它默认使用DX:AX组成的32位无符号数作为被除数,运算后AX存储商,DX存储余数。如果每次执行DIV bx前没有清零DX,DX中残留的上一次运算的余数会和当前AX组合成远大于预期的32位被除数。当这个被除数除以10的商超过AX的16位最大值(0xFFFF,即65535)时,就会触发除法溢出异常,也就是你遇到的SIGFPE。

结合你的场景:第一次运算后DX=3,若第二次循环未清零DX,被除数会是3*65536 + AX(假设AX此时是2)=196610,除以10商19661,这在AX范围内;但如果你的循环逻辑错误(比如未将AX更新为商,仍用初始值23循环),被除数会是3*65536+23=196631,商19663仍在范围内,但如果DX累积到>=10时,被除数除以10的商就会超过65535,直接触发异常。

修复方案

在每次执行DIV bx之前,必须用XOR DX,DX清零DX寄存器,确保被除数是AX对应的16位值(DX为0,即0:AX)。

正确的数字拆分打印示例代码:

prN PROC
    push bx          ; 保存寄存器现场
    push cx
    mov bx, 10       ; 除数固定为10
    xor cx, cx       ; CX记录余数个数

loop_div:
    xor dx, dx       ; 关键:清零DX,准备无符号除法
    div bx           ; DX:AX / 10 → AX=商,DX=余数
    push dx          ; 将余数压栈(后续逆序打印)
    inc cx
    test ax, ax      ; 判断商是否为0
    jnz loop_div     ; 商不为0则继续拆分

loop_print:
    pop dx
    add dl, '0'      ; 将余数转换为ASCII字符
    ; 以下是DOS环境下的打印逻辑,若为Linux可替换为对应系统调用
    mov ah, 02h
    int 21h
    dec cx
    jnz loop_print

    pop cx           ; 恢复寄存器
    pop bx
    ret
prN ENDP

额外说明

Linux下的SIGFPE信号不仅对应浮点异常,整数除法的溢出、除零错误都会触发该信号,这是容易混淆的点。你排除了除零、溢出、下溢,但实际上你遇到的就是商溢出,只是之前对溢出的判断未考虑DX未清零导致的32位被除数场景。

内容的提问来源于stack exchange,提问作者Maximilian Wittmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:35:29