I am trying to create a calculator program using Assembly Language but it is required for us to show 4 digit number operations.
In this code, I can add, subtract and divide numbers with 4 digits each, but when multiplying 4 digit by 4 digit numbers, the answer is different and wrong
Example: 9999x9999= 37601 (which is wrong and the answer should be 99980001)
Here is the part of the code for Multiplication:
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
Here is the FULL code:
.model small
.stack 100h
.data
msg1 db 13, 10, 13, 10,"MENU "
db 10, 13,"1. Add "
db 10, 13,"2. Subtract "
db 10, 13,"3. Multiply "
db 10, 13,"4. Divide "
db 10, 13,"5. Exit "
db 13,10,13,10, "Enter 1st Number : $"
msg2 db 13,10, "Enter 2nd Number : $"
msgEr db 13,10, "Error $"
choiceseu db 13,10, "Enter choice: $ "
sumseu db 13,10,13,10, "***Sum is : $"
Diffseu db 13,10,13,10, "***Difference is : $"
Divseu db 13,10,13,10, "***Quotient is : $"
Mulseu db 13,10,13,10, "***Product is : $"
temp db ?
.code
start:
mov ax, @data
mov ds, ax
lea dx, msg1
mov ah, 09h
int 21h
mov bx, 0
ph1:
mov ah, 01h
int 21h
cmp al,0dh
je input1
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph1
input1:
push bx
lea dx,msg2
mov ah,09h
int 21h
mov bx,0
ph2:
mov ah,01h
int 21h
cmp al,0dh
je choice
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph2
choice:
lea dx, choiceseu
mov ah, 09h
int 21h
mov ah, 01h
int 21h
cmp al,'4'
je divd
cmp al,'1'
je addz
cmp al,'2'
je subt
cmp al,'3'
je mult
cmp al,'5'
mov ah, 4ch
int 21h
error:
lea dx,msgEr
mov ah,09h
int 21h
jmp start
divd:
pop ax
mov dx, 0
div bx
push ax
lea dx,Divseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
addz:
pop ax
add ax,bx
push ax
lea dx,sumseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
subt:
pop ax
sub ax,bx
push ax
lea dx,Diffseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
wrong:
mov dx, 0
div bx
push dx
mov dx,0
inc cx
or ax,ax
jne wrong
ans:
pop dx
add dl,30h
mov ah,02h
int 21h
loop ans
jmp start
end start
mult: pop ax mul bx push ax lea dx,Mulseu mov ah,09h int 21h pop ax mov cx,0 mov dx,0 mov bx,10d jmp wrong
Since you want to display the full 32-bit result (in DX:AX
) from the multiplication, you can't let the DX
register go to waste! You need to preserve it just like you did with AX
.
Because your current conversion/displaying routine (Why o why is this named wrong ?) only knows about 16-bit numbers, you'll need another routine that I'll present below. This routine comes from another answer that I wrote some time ago. You should definitely read it. It explains in great detail how these things work and so I shall not repeat that explanation here.
mult:
pop ax
mul bx
push ax
push dx
lea dx, Mulseu
mov ah, 09h
int 21h
pop dx
pop ax
jmp DisplayNumber32
...
DisplayNumber32:
mov bx,10 ;CONST
push bx ;Sentinel
.a: mov cx,ax ;Temporarily store LowDividend in CX
mov ax,dx ;First divide the HighDividend
xor dx,dx ;Setup for division DX:AX / BX
div bx ; -> AX is HighQuotient, Remainder is re-used
xchg ax,cx ;Temporarily move it to CX restoring LowDividend
div bx ; -> AX is LowQuotient, Remainder DX=[0,9]
push dx ;(1) Save remainder for now
mov dx,cx ;Build true 32-bit quotient in DX:AX
or cx,ax ;Is the true 32-bit quotient zero?
jnz .a ;No, use as next dividend
pop dx ;(1a) First pop (Is digit for sure)
.b: add dl,"0" ;Turn into character [0,9] -> ["0","9"]
mov ah,02h ;DOS.DisplayCharacter
int 21h ; -> AL
pop dx ;(1b) All remaining pops
cmp dx,bx ;Was it the sentinel?
jb .b ;Not yet
For all the remaining operations (addz, subt, divd) you can also use this new DisplayNumber32 routine. Just make sure to zero the DX
register beforehand.
subt:
pop ax
sub ax, bx
push ax
lea dx, Diffseu
mov ah, 09h
int 21h
pop ax
xor dx, dx ;Add this for the 32-bit version!
jmp DisplayNumber32