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,但这对我来说仍然不起作用。
我目前也仅限于制作变量 Dividend
和 Divisor
字号。我尝试用 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=32767
和 Divisor=1
:
- 第一个乘法运算:
DX:AX = 32767*100 = 3276700
- 第一个除法:
DX:AX / 1 = 3276700 / 1 = 3276700
(余数为零),但是 3276700
太大而不适合 AX
(大于 32767
)所以产生了除法错误。
这不会发生在 32 位上,因为 3276700 可以放入 EAX
。 (当然,无论哪种情况,除以零仍然会产生错误)
另注:此代码假定初始除法的结果为正
我只能在当前流程中使用 .386。使用 intel x86 如何获得除法的小数位?基本上我希望它输出到第一百位,如:12.81
这是我当前的代码:
mov AX, Dividend
cwd
idiv Divisor
outputW AX ;Outputs Quotient (whole number)
outputW DX ;Outputs Remainder
我试过先将 AX 乘以 100,但这对我来说仍然不起作用。
我目前也仅限于制作变量 Dividend
和 Divisor
字号。我尝试用 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=32767
和 Divisor=1
:
- 第一个乘法运算:
DX:AX = 32767*100 = 3276700
- 第一个除法:
DX:AX / 1 = 3276700 / 1 = 3276700
(余数为零),但是3276700
太大而不适合AX
(大于32767
)所以产生了除法错误。
这不会发生在 32 位上,因为 3276700 可以放入 EAX
。 (当然,无论哪种情况,除以零仍然会产生错误)
另注:此代码假定初始除法的结果为正