I have been trying to debug a little assembly program where I ask for a dividend and a divisor and have to output the quotient and the remainder. For some reason however, my quotient and remainder are not output to the screen. Here is my code:
segment .data
prompt db "Please enter a number: ", 10
promptLen equ $-prompt
prompt2 db "Please enter the divisor: ", 10
prompt2Len equ $-prompt2
prompt3 db "Your quotient is: ", 10
prompt3Len equ $-prompt3
prompt4 db "Your remainder is: ", 10
prompt4Len equ $-prompt4
segment .bss
inputNum resb 2
inputDiv resb 2
quotient resb 2
remainder resb 2
segment .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, promptLen
int 80h
mov eax, 3
mov ebx, 0
mov ecx, inputNum
mov edx, 2
int 80h
mov eax, 4
mov ebx, 1
mov ecx, prompt2
mov edx, prompt2Len
int 80h
mov eax, 3
mov ebx, 0
mov ecx, inputDiv
mov edx, 2
int 80h
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'
div bx
add ax, '0'
add dx, '0'
mov [quotient], ax
mov [remainder], dx
mov eax, 4
mov ebx, 1
mov ecx, prompt3
mov edx, prompt3Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, [quotient]
mov edx, 2
int 80h
mov eax, 4
mov ebx, 1
mov ecx, prompt4
mov edx, prompt4Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, [remainder]
mov edx, 2
int 80h
jmp exit
exit:
mov eax, 1
xor ebx, ebx
int 80h
I would appreciate if someone could help me understand what I am doing wrong.
System call 4 (write) requires a char *
for its buffer address in ecx
. With your code:
mov eax, 4 ; sys_write
mov ebx, 1 ; standard output
mov ecx, [quotient] ; here, ecx <- your character code
mov edx, 2 ; two bytes (hmmm)
int 80h
you are loading ecx
with the actual data that was input, rather than the address of it.
What you need to do is to load ecx
with the address of the character, which will probably just be something like:
mov ecx, quotient ; here, ecx <- your character address
You may also want to reduce your byte count to one rather than two. The way you're turning integers into characters (adding '0'
) will only work for one-character numbers anyway so you only want the least significant byte (the one at the lowest memory address for x86).
Ditto for the remainder.
As an aside, when you do fix that, you still get a funny result. Dividing 5 by 2 gives you a quotient of 1 and a remainder of 3, clearly wrong.
This has to do with how you input the data and load the values into ax
and bx
.
Since you're reading two bytes for each number, the memory is loaded up with the digit itself '5'
, or 0x35
, followed by a newline character 0x0a
.
Then, when you load the two-byte word into ax
, it ends up with 0x0a35
.
After subtracting 0x0030
('0'
) from each, you end up with 0x0a05
and 0x0a02
which is, in decimal, 2565
and 2562
. When you divide those numbers, you do indeed get a quotient of 1
and remainder of 3
.
To fix that, you can simply throw away the 0x0a00
but when loading the value, by changing:
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'
into:
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
and ax, 0xff ; add these
and bx, 0xff ; two lines.
sub ax, '0'
sub bx, '0'