在汇编中进行除法时出现浮点异常(核心转储)

Posted

技术标签:

【中文标题】在汇编中进行除法时出现浮点异常(核心转储)【英文标题】:Floating Point Exception (Core Dumped) while doing division in assembly 【发布时间】:2013-06-24 03:05:35 【问题描述】:

我正在尝试添加 2 个两位数,这必然会产生一个两位数或三位数。

这是我目前所拥有的,当我尝试打印进位时,它显示 Floating Point Exception (Core Dumped)

section .data
    msg db "Enter 2 numbers: "
    msgLen equ $-msg

section .bss
    numa1 resb 1
    numa2 resb 1
    numb1 resb 1
    numb2 resb 1
    carry resb 1

section .text
    global _start

_start: 
    ;print message
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, msgLen
    int 80h

    ;accept first number (1st digit)
    mov eax, 3
    mov ebx, 0
    mov ecx, numa1
    mov edx, 1
    int 80h

    ;accept first number (2nd digit)
    mov eax, 3
    mov ebx, 0
    mov ecx, numa2
    mov edx, 2
    int 80h

    ;accept second number (1st digit)
    mov eax, 3
    mov ebx, 0
    mov ecx, numb1
    mov edx, 1
    int 80h

    ;accept second number (2nd digit)
    mov eax, 3
    mov ebx, 0
    mov ecx, numb2
    mov edx, 2
    int 80h

    ;character to number conversion
    sub byte[numa1], 30h
    sub byte[numa2], 30h
    sub byte[numb1], 30h
    sub byte[numb2], 30h
    sub byte[carry], 30h

    ;;;;;;;;;;;;;;;;;;;;;;;;;;

    ;add ones digit
    mov al, [numa2]
    add byte[numb2], al
    add byte[numb2], 30h

    ;get carry of sum of ones digit
    mov ax, [numb2]
    mov byte[carry], 10
    div byte[carry]

    mov eax, 4
    mov ebx, 1
    mov ecx, carry
    mov edx, 1
    int 80h


    mov eax, 1
    mov ebx, 0
    int 80h

  carry
  numa1   numa2
+ numb2   numb2
---------------
          numb2

where numb2 = numb2 % 10
      carry = numb2 / 10

【问题讨论】:

这是什么操作系统? Linux? 是的,我忘了说对不起。 32位Linux 哪一行产生异常?引发异常的指令的参数是什么?请注意,某些指令有隐含的参数。 可能是On which platforms does integer divide by zero trigger a floating point exception? 和/或8086 assembly on DOSBox: Bug with idiv instruction? 的副本。 DIV 溢出 -> SIGFPE 【参考方案1】:

首先,xor ebx, ebx is shorter and faster than mov ebx, 0

另外,两个 1 位数字相加的最大进位为 1 (9 + 9 = 18),因此无需除法,只需将数字减去 10 即可。此外,您通常应该避免使用 16 位寄存器,因为它更长(由于 66h 前缀)和更慢(由于部分寄存器更新)。这意味着

mov ax, [numb2]
mov byte[carry], 10
div byte[carry]

会比下面慢很多

movzx eax, word ptr [numb2]
sub   eax, 10

但毕竟,当 x86 已经有 BCD instructions 用于此目的时,为什么还要使用如此复杂的方式。此外,这些指令有 AF 和 CF 用于 BCD 数学进位,所以不需要你自己管理它

您也可以直接使用二进制数学,然后在输入/输出中进行转换。大多数情况下,转换成本可以忽略不计

【讨论】:

【参考方案2】:

请注意“浮点异常”,但这些行可能会导致除法溢出:

mov ax, [numb2]
mov byte[carry], 10
div byte[carry]

您正在从numb2 移动到ax,这意味着您将在ah 中获得存储在carry 的任何内容。如果我们假设.bss 部分在启动时为零,那么当您将carry 加载到ah 时,其值将是0xD0,因为您已经完成了sub byte[carry], 30h

因此,您将 0xD0nn 除以 10,这将导致商太大而无法放入 al

您可以将mov ax, [numb2] 替换为movzx ax,byte [numb2]

【讨论】:

当然,sub byte[carry], 30h 本身是有问题的,应该是 mov byte[carry], 0... 依靠 carry 进行零初始化通常是可以的,除非它不是' t,结果被扯头发,咬牙切齿……

以上是关于在汇编中进行除法时出现浮点异常(核心转储)的主要内容,如果未能解决你的问题,请参考以下文章

为 Linux 创建 C 程序时出现浮点异常(核心转储)

汇编 - 收到浮点异常

浮点异常(核心转储)cpp

STM32 M0和M3内核单片机做浮点除法运算和整型除法运算,分别的用时。希望能给大概数据参考。

浮点除法的软件实现,舍入问题

在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误