I'm limited to using the .386 with my current process. Using intel x86 how do I get the decimal places of a division? Basically I want it to output to the hundredth place like: 12.81
Here is my current code:
mov AX, Dividend
cwd
idiv Divisor
outputW AX ;Outputs Quotient (whole number)
outputW DX ;Outputs Remainder
I've tried multiplying AX by 100 first, but that still did not work for me.
I'm also currently limited to making the variables Dividend
and Divisor
Word size. I tried replacing cwd
with the cwde
command, but that didn't work for me.
Any help would be greatly appreciated!
Thanks
You can multiply the dividend by 100 before performing the division, adjust for rounding, then divide by 100 again to get the two decimal places. Since your initial code is 16-bit, here is a 16-bit solution first:
;; 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
Or, if a 32-bit solution is applicable, you can use 32-bit integers instead:
;; 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
Note: The 32-bit code is preferable since it does not produce Divide Errors from large quotients. Consider Dividend=32767
and Divisor=1
in the 16-bit case:
DX:AX = 32767*100 = 3276700
DX:AX / 1 = 3276700 / 1 = 3276700
(with a zero remainder), however 3276700
is too large to fit in AX
(it is greater than 32767
) so a Divide Error is produced.This does not happen on 32-bit because 3276700 can fit in EAX
. (Of course, dividing by zero would still produce an error in either case)
Another note: This code assumes the result of the initial division is positive