无除零操作却触发浮点异常?汇编程序运行问题求助
问题分析与解决方案
首先,你遇到的「Floating point exception (core dumped)」其实是个误导性提示——在Linux x86系统中,这个错误不仅会在浮点运算出错时触发,整数除法溢出或者除数为0时也会抛出这个异常。你的代码里没有除数为0的情况,问题出在整数除法的溢出上,而根源是一个基础的寄存器初始化错误。
错误原因拆解
看你循环里的除法逻辑:
while: mov al, [i] mov bl, 0 cmp al, bl jz end mov bl, 10 div bl
div bl是8位无符号除法,它的被除数是整个AX寄存器(AH作为高8位,AL作为低8位),商存在AL,余数存在AH。但你每次循环只给AL赋值了[i]的值,却没有清零AH——AH里保留的是上一次除法操作留下的余数!
举个实际运行的例子:
- 第一次循环:输入字符是'A'(ASCII 65),AL=65,AH初始是0(来自sys_read返回值的高8位),
div 10得到商6(AL=6),余数5(AH=5),你把商6存入[i]。 - 第二次循环:你把
[i]的6加载到AL,但AH还是5!此时AX=5*256 +6=1306,div 10得到商130(AL=130),余数6(AH=6),你把130存入[i]。 - 第三次循环:AL=130,AH=6,AX=6*256+130=1666,
div10得到商166(AL=166),余数6(AH=6),存入[i]的是166——比之前的130还大!
这样循环不仅不会终止(商越来越大,永远到不了0),最终还会出现商超过8位无符号数范围(0-255)的情况,触发除法溢出异常,也就是你看到的错误。
修复方案
只需要在执行div bl之前,把AH清零,确保被除数只有AL里的数值:
while: mov al, [i] mov bl, 0 cmp al, bl jz end mov bl, 10 xor ah, ah ; 关键:清零AH,让被除数为AX=0x00AL div bl add ah, '0' mov [i], al mov [ecx], ah dec ecx inc edx jmp while
如果你想彻底避免8位除法的溢出风险,可以改用32位除法,逻辑更清晰:
while: movzx eax, byte [i] ; 将8位的[i]扩展为32位无符号数,高24位自动清零 test eax, eax jz end mov ebx, 10 xor edx, edx ; 32位除法需要清零edx div ebx add dl, '0' ; 余数存在dl里 mov [i], al ; 商的低8位存入[i] mov [ecx], dl dec ecx inc edx jmp while
额外优化点
如果输入的是ASCII码0(比如直接输入Ctrl+@),你的循环不会执行,最终sys_write会输出0字节,用户看不到任何内容。可以在end标签前加一段逻辑,处理这种情况:
end: cmp edx, 0 jnz write_zero mov byte [ecx], '0' inc edx write_zero: mov eax, 4 mov ebx, 1 int 0x80
这样当输入ASCII 0时,会输出一个'0'字符,行为更符合预期。
内容的提问来源于stack exchange,提问作者Polazhinets.A




