您可以在执行除法之前将被除数乘以 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。 (当然,除以零在任何一种情况下都会产生错误)
另外说明:此代码假设初始除法的结果为正