【问题标题】:x86 Assembly: Division Floating Point Exception dividing by 11x86 程序集:除法浮点异常除以 11
【发布时间】:2017-08-18 00:14:15
【问题描述】:

我试图将859091 除以11 以获得商和余数,但我在线得到浮点异常:

div bx

这是我的 SASM 代码:

%include "io.inc"
section .data
  dividend dd 859091
  divisor  dw 11

section .text
global CMAIN
CMAIN:
  push ebp
  mov ebp, esp

  xor eax, eax
  xor ebx, ebx
  xor edx, edx

  mov ax, word [dividend]
  mov dx, word [dividend + 2]
  mov bx, word [divisor]    
  test bx, bx
  jz exit

  div bx

exit:
  leave
  ret

【问题讨论】:

  • dx:ax 除以 bx 的商不适合 16 位寄存器(ax 是商所在的位置),因此您会遇到异常。 859091/11=78099。可以放入 16 位的最高无符号值是 65535。也许使用 32 位寄存器进行除法?
  • 要将内存中的 32 位双字除以内存中的 16 位字,您可以这样做 movzx ebx, word [divisor] test ebx, ebx jz exit jz exit xor edx, edx mov eax, [dividend] div ebx
  • 浮点异常 (SIGFPE) 是算术异常的全部捕获,而不仅仅是浮点异常。该错误有点欺骗性。如果它是“算术异常”恕我直言,那就更好了。在 x86 除法溢出和除以零映射到相同的硬件异常。 single unix specification 现在对 SIGFPE 这么说:SIGFPE 错误的算术运算。

标签: assembly x86 nasm division floating-point-exceptions


【解决方案1】:

因为商不适合 16 位整数,所以出现除法溢出。

您可以将被除数分成上半部分和下半部分,以产生最多 32 位商和 16 位余数。 dx = 0000 : ax = upper_dividend / divisor 的余数成为第 2 次除法的第 2 次除数的上半部分,因此第 2 次除法计算 dx = remainder : ax = lower_dividend / divisor,两者都不会溢出,因为余数严格小于除数。这个过程可以扩展到更长的被除数和商,每个被除数和商一个字,每个除法的剩余部分成为下一步的部分被除数的上半部分。

使用 MASM 语法的示例:

dvnd    dd 859091
dvsr    dw 11
;       ...
;       bx:ax will end up = quotient of dvnd/dvsr, dx = remainder
        mov     di,dvsr
        xor     dx,dx
        mov     ax,word ptr dvnd+2      ;ax = upr dvnd
        div     di                      ;ax = upr quot, dx = rmdr
        mov     bx,ax                   ;bx = upr quot
        mov     ax,word ptr dvnd        ;ax = lwr dvnd
        div     di                      ;ax = lwr quot, dx = rmdr

四字示例:

dvnd    dq 0123456789abcdefh
dvsr    dw 012h
quot    dq 0
rmdr    dw 0
;       ...
        mov     di,dvsr
        xor     dx,dx                   ;dx = 1st upr half dvnd = 0

        mov     ax,word ptr dvnd+6      ;ax = 1st lwr half dvnd
        div     di                      ;ax = 1st quot, dx = rmdr = 2nd upr half dvnd
        mov     word ptr quot+6,ax

        mov     ax,word ptr dvnd+4      ;ax = 2nd lwr half dvnd
        div     di                      ;ax = 2nd quot, dx = rmdr = 3rd upr half dvnd
        mov     word ptr quot+4,ax

        mov     ax,word ptr dvnd+2      ;ax = 3rd lwr half dvnd
        div     di                      ;ax = 3rd quot, dx = rmdr = 4th upr half dvnd
        mov     word ptr quot+2,ax

        mov     ax,word ptr dvnd        ;ax = 4th lwr half dvnd
        div     di                      ;ax = 4th quot, dx = rmdr
        mov     word ptr quot,ax

        mov     rmdr,dx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多