My program's supposed to perform division by using subtraction. However, I'm getting nonsense results as output. Could someone help me with my procedure and the loop within? Thank you.
div proc
pushad
mov ecx,firstInt
mov ebx,0
subtracting:
sub ebx,secondInt
loop subtracting
mov divResult,ebx
popad
ret
divt endp
You continu subtracting for as long as there is no borrow. If a borrow happened, you have the count:
mov ecx, firstInt
mov ebx, -1
subtracting:
inc ebx
sub ecx, secondInt
jnb subtracting
mov divResult, ebx
EDIT
What the above code still lacks is checking if the divider is zero. If we allow a zero-divider the code will run forever because subtracting zero will never produce a borrow!
This simple solution gets the job done, but it is unacceptably slow for big quotients. This calls for a better solution without betraying of course the task of "Division by using subtracting" aka "Don't use div
(or any similar instruction)".
In order to mimic the div
instruction:
divide:
mov eax, firstInt
xor edx, edx
div secondInt ; -> EDX is remainder, EAX is quotient
we can write:
simple:
mov edx, firstInt
mov eax, -1
.A: inc eax
sub edx, secondInt
jnb .A
add edx, secondInt ; -> EDX is remainder, EAX is quotient
The problem with this simple solution is that we could be subtracting a small number many, many times. What if we could find a way to subtract more at once?
We can, if we subtract binary multiples of the divider (*1, *2, *4, *8, *16, ...). It will be the summing of these factors that produces the quotient.
To calculate e.g. 503 / 20
we would subtract the following:
503 - (20 * 16) = 183
183 - (20 * 8) = 23
23 - (20 * 1) = 3 <-- is remainder
--
25 <-- is quotient
In code:
complex:
mov edx, firstInt
xor eax, eax
jmp .C
.A: rol ecx, 1
shl ebx, 1
jc .B
cmp ebx, edx
jbe .A
.B: rcr ebx, 1
add eax, ecx
sub edx, ebx
.C: mov ebx, secondInt
mov ecx, 80000000h
cmp edx, ebx
jnb .A
; -> EDX is remainder, EAX is quotient
To illustrate the importance of developing a better solution, I've timed a few divisions:
simple complex divide
-------------- -------- --------
4294967295 / 1 8087730.0 µsec 3.0 µsec 0.3 µsec
2147483648 / 10 405994.0 µsec 1.3 µsec 0.1 µsec
47623 / 320 0.4 µsec 0.2 µsec 0.1 µsec
4294967295 / 1
is the worst case division2147483648 / 10
is used to start displaying the number 214748364847623 / 320
is used to convert a 320x200 256-color video mode offset address 47623 into (x,y) coordinates