x86 程序集 - idiv 获取小数位

x86 Assembly - idiv to get decimal places

我只能在当前流程中使用 .386。使用 intel x86 如何获得除法的小数位?基本上我希望它输出到第一百位,如:12.81

这是我当前的代码:

mov AX, Dividend
cwd
idiv Divisor

outputW AX ;Outputs Quotient (whole number)
outputW DX ;Outputs Remainder

我试过先将 AX 乘以 100,但这对我来说仍然不起作用。 我目前也仅限于制作变量 DividendDivisor 字号。我尝试用 cwde 命令替换 cwd,但这对我不起作用。

如有任何帮助,我们将不胜感激!

谢谢

您可以在除法前将被除数乘以100,调整四舍五入,然后再除以100得到两位小数。由于您的初始代码是 16 位的,这里先给出 16 位的解决方案:

    ;; Perform the initial division (100 * Dividend / Divisor)
    MOV AX, Dividend    ; Load the Dividend into AX
    IMUL OneHundred     ; DX:AX = AX * 100
    IDIV Divisor        ; DX:AX / Divisor... AX=Quotient, DX=Remainder

    ;; Handle the remainder
    SHL DX, 1           ; DX now equals the remainder times two
    CMP DX, Divisor     ; Compare Remainder*2 to the Divisor
    JL l1               ; If Remainder*2 is <, we round down (nothing changes)
    INC AX              ; If Remainder*2 is >=, we round up (increment the quotient)
l1:

    ;; Divide by 100 again to get the final result
    CWD                 ; Sign-extend AX to DX:AX
    IDIV OneHundred     ; DX:AX / 100... AX=Quotient, DX=Remainder
    MOV IntegerPart, AX ; Now AX is the integer part
    MOV DecimalPart DX  ; And DX is the fractional part

OneHundred DW 100

或者,如果 32 位解决方案适用,您可以改用 32 位整数:

    ;; Perform the initial division (100 * Dividend / Divisor)
    MOVSX EAX, Dividend ; Sign-extend the Dividend into EAX
    IMUL OneHundred     ; EDX:EAX = EAX * 100
    MOVSX ECX, Divisor  ; Sign-extend the Divisor into ECX
    IDIV ECX            ; EDX:EAX / Divisor... EAX=Quotient, EDX=Remainder

    ;; Handle the remainder
    SHL EDX, 1          ; EDX now equals the remainder times two
    CMP EDX, ECX        ; Compare Remainder*2 to the Divisor
    JL l1               ; If Remainder*2 is <, we round down (nothing changes)
    INC EAX             ; If Remainder*2 is >=, we round up (increment the quotient)
l1:

    ;; Divide by 100 again to get the final result
    CDQ                 ; Sign-extend EAX to EDX:EAX
    IDIV OneHundred     ; EDX:EAX / 100... EAX=Quotient, EDX=Remainder
    MOV IntegerPart, EAX ; Now EAX is the integer part
    MOV DecimalPart EDX  ; And EDX is the fractional part

OneHundred DD 100

注意:最好使用 32 位代码,因为它不会从大商中生成 Divide Errors。考虑 16 位情况下的 Dividend=32767Divisor=1

  • 第一个乘法运算:DX:AX = 32767*100 = 3276700
  • 第一个除法:DX:AX / 1 = 3276700 / 1 = 3276700(余数为零),但是 3276700 太大而不适合 AX(大于 32767)所以产生了除法错误。

这不会发生在 32 位上,因为 3276700 可以放入 EAX。 (当然,无论哪种情况,除以零仍然会产生错误)

另注:此代码假定初始除法的结果为正