You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无除零操作却触发浮点异常?汇编程序运行问题求助

问题分析与解决方案

首先,你遇到的「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里保留的是上一次除法操作留下的余数!

举个实际运行的例子:

  1. 第一次循环:输入字符是'A'(ASCII 65),AL=65,AH初始是0(来自sys_read返回值的高8位),div 10得到商6(AL=6),余数5(AH=5),你把商6存入[i]
  2. 第二次循环:你把[i]的6加载到AL,但AH还是5!此时AX=5*256 +6=1306,div 10得到商130(AL=130),余数6(AH=6),你把130存入[i]
  3. 第三次循环: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

火山引擎 最新活动