I am learning basic assembly using NASM and stumbled on an issue in the div
of two numbers.
Here is the code I wrote:
section .data
msg1 db "Enter first digit (a): ", 0
len1 equ $- msg1
msg2 db "Enter second digit (b): ", 0
len2 equ $- msg2
newLine db "",0xA
msg3 db "The division (a/b) is: ",0
len3 equ $- msg3
section .bss
num1 resb 2
num2 resb 2
res resb 1
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 2
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 2
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, len3
int 0x80
mov ax, [num1] ; Load the 16-bit value from num1
sub ax, '0'
mov eax, 0 ; Clear the upper 16 bits of eax
mov [num1], ax ; Store the result back in num1
mov bx, [num2] ; Load the 16-bit value from num2
sub bx, '0'
mov ebx, 0 ; Clear the upper 16 bits of eax
mov [num2], bx ; Store the result back in num2
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
mov edx, 0
div bx ; eax = quotient, edx = remainder
add ax, '0'
mov [res], ax
mov eax, 4
mov ebx, 1
mov ecx, res
mov edx, 1
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, newLine
mov edx, 1
int 0x80
mov eax, 1
int 0x80
And the output generated is
I did some research on the previous similar questions on div
on stack overflow but to no avail and also did the reading on google but couldn't solve the issue.
please help, I am stuck on this since last night
mov ax, [num1] ; Load the 16-bit value from num1 sub ax, '0' mov eax, 0 ; Clear the upper 16 bits of eax mov [num1], ax ; Store the result back in num1
Although num1 had 2 bytes reserved, only the first byte is important for your calculation. Remember you were asking the user for a single digit number? Subtracting '0' will correctly convert from the character ["0","9"] into the value [0,9], but if you move zero into EAX you will lose that value immediately. The solution is to write the following and with no need to store it back in num1:
movzx eax, byte [num1]
sub eax, '0'
mov bx, [num2] ; Load the 16-bit value from num2 sub bx, '0' mov ebx, 0 ; Clear the upper 16 bits of eax mov [num2], bx ; Store the result back in num2
Same as above, but keep the result in EBX
mov eax, [num1] sub eax, '0'
Here you are reading 4 bytes where you had only 2 bytes stored. Plus you are erroneously subtracting '0', again. The conversion had already been done before! This part can be removed.
mov ebx, [num2] sub ebx, '0'
Similar to the first number, you can remove this part too.
mov edx, 0 div bx ; eax = quotient, edx = remainder add ax, '0' mov [res], ax
From your comment, it seems like you want dword-sized division, but then you need to write div ebx
. And since the res variable had only 1 byte reserved, you should never try to store 2 bytes in it.
All together:
...
movzx eax, byte [num1]
sub eax, '0'
movzx ebx, byte [num2]
sub ebx, '0'
jz Quit ; You should not divide by zero!
xor edx, edx
div ebx ; -> EAX = quotient, EDX = remainder
add eax, '0' ; Convert to character
mov [res], al
...
Quit:
mov eax, 1
int 0x80