Reputation: 133
I am attempting to write a program in Assembly to take a plus or minus sign as the first input ( deciding whether to plus or minus two numbers together ) and then taking two 2 digit numbers and adding/subtracting and displaying the result. I have the following code so far, but I am having troubles in the output. I know in the code snippet below it is simply displaying a single char, but I would like it to display the actual output but I have no idea how, attempting to use a normal string display interrupt does not work because the size of num2 or al does not match the size of dx (the output string register)
.MODEL SMALL
.STACK 100h
.DATA
choice_msg db 13,10,'Addition or Subtraction?',13,10,'$'
first_msg db 13,10,'Enter the first number:',13,10,'$'
second_msg db 13,10,'Enter the second number:',13,10,'$'
result_msg db 13,10,'The result is:',13,10,'$'
new_line db 13,10,'$'
val1 db ?
num2 db ?
num3 db ?
num4 db ?
ten db 10
.CODE ;where the code is written
start:
mov ax, @data ;Moves the address of the variables under .DATA into ax
mov ds,ax ;moves ax into ds. the two lines allow you to display string using the 21h interrupt sequence 9
mov ah,09
mov dx, offset choice_msg
int 21h ;displays the string in choice_msg
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
mov val1,al ;moves the value in the al to the variable val1
cmp val1,'+' ;compares the entered value in val1 with "+"
je addition ;if the enterd value is "+" then it jumps to addition else it jumps to subtraction
addition:
mov ah,09
mov dx, offset first_msg
int 21h ;displays the string in first_msg
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the vaule in the al
mov num2,al ;moves the value in the al to the variable num2
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num3,al ;moves the value in the al to the variable num3
mov al,num2 ;moves the value in num2 into the al
mul ten ;multiplies the value in the al by ten
add al,num3 ;adds the value in num3 to the al, to get the two-digit number
mov num2,al ;moves the two digit value into
mov ah,09
mov dx, offset new_line
int 21h ;goes to the next line, i.e. "enter"
mov ah,09
mov dx, offset second_msg ;displays the string in second_msg
int 21h
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num3,al ;moves the new value in the al into the variable num3
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num4,al ;moves the new value in the al into the variable num4
mov al,num3 ;moves the value in num3 into the al
mul ten ;multiplies the value in the al by ten
add al,num4 ;adds the value in num4 to the al, to get a two-digit number
mov num3,al ;moves the value in the al into the variable num3
mov ah,09
mov dx, offset new_line
int 21h ;goes to the next line, i.e. "enter"
mov ah,09
mov dx, offset result_msg
int 21h ;displays the string in reslut_msg
; mov the value of num 3 into bl
mov bl, num3
add num2,bl ;adds num3 and num2 to form the sum
add num2,48 ;adds 48 to num2
mov al,num2
mov ah,02
mov dl, al
int 21h ;displays the value that was in the al
mov ah,09
mov dx, offset new_line
int 21h ; goes to next line, i.e. "enter"
mov ax,4c00h
int 21h ;ends the program
subtraction:
mov ah,09
mov dx, offset first_msg
int 21h ;displays the string in first_msg
mov ah,01
int 21h ;copies a value into the al, using subfunction 001
sub al,48 ;subtracts 48 from the value in the al
mov num2,al ;moves the value in the al into the variable num2
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num3,al ;moves the value in the al into the variable num3
mov al,num2 ;moves the value in num2 into the al
mul ten ;multiplies the value in the al by ten
add al,num3 ;adds the value in num3 to the al, to get a two-digit number
mov num2,al ;moves the value in the al into the variable num2
mov ah,09
mov dx, offset new_line
int 21h ;goes to the next line, i.e. "enter"
mov ah,09
mov dx, offset second_msg
int 21h ;displays the string in second_msg
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num3,al ;moves the value in the al into the variable num3
mov ah,01
int 21h ;copies a value into the al, using subfuntion 01
sub al,48 ;subtracts 48 from the value in the al
mov num4,al ;moves the value in the al into the variable num4
mov al,num3 ;moves the value in num3 into the al
mul ten ;multiplies the value in the al by ten
add al,num4 ;adds the value in num4 to the al, to get a two-digit number
mov num3,al ;moves the value in the al into the variable num3
mov ah,09
mov dx, offset new_line
int 21h ;goes to next line, i.e. "enter"
mov ah,09
mov dx, offset result_msg
int 21h ;displays the string in result_msg
mov bl, num3 ;move value of num3 to bl
sub num2,bl ;subtracts the value in num3 from the value in num2
add num2,48 ;adds 48 to the new value in num2
mov al,num2 ;moves the value in num2 into the al
mov ah,02
mov dh,al
int 21h ;displays the resulting value
mov ah,09
mov dx, offset new_line
int 21h ;goes to the next line, i.e. "enter"
mov ax,4c00h
int 21h ;ends the program
END
Upvotes: 1
Views: 51532
Reputation: 133
Thanks for the help! I found a way that works quite well, for my code. See it below:
About the duplicate code: Yes I realised that (this is not actually my code, it was a friends that needed fixing), I fixed up the code and proceduralised a lot of it to minimalise code re-use. And the result is the final program here: I know the code is not perfect, and there are many performance improvements that can be made but the outcome is a working program with an okay execution time.
.MODEL SMALL
.STACK 100h
.DATA
choice_msg db 13,10,'Addition or Subtraction?',13,10,'$'
first_msg db 13,10,'Enter the first number:',13,10,'$'
second_msg db 13,10,'Enter the second number:',13,10,'$'
result_msg db 13,10,'The result is:',13,10,'$'
new_line db 13,10,'$'
val1 db ?
num1 db ?
num2 db ?
num3 db ? ; purely a buffer variable
ten db 10
t1 db 0
t2 db 0
result db 0
.CODE ;where the code is written
start:
mov ax, @data ;Moves the address of the variables under .DATA into ax
mov ds,ax ;moves ax into ds. the two lines allow you to display string using the 21h interrupt sequence 9
mov ah,09
mov dx, offset choice_msg
int 21h ;displays the string in choice_msg
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
cmp al,'+' ;compares the entered value in with "+"
jne subtraction ;if the enterd value is "+" then it jumps to addition else it jumps to subtraction
addition:
call read ;Read the input
call endl ;output new line
mov bl, num2 ;move the value of num 2 into bl
add num1,bl ;adds num2 and num1 to form the sum1
mov al, num1 ;mov num1 to al
mov result, al ;store the result of the sum in result
call write ;write the output
jmp exit
subtraction:
call read ;Read the input
call endl ;output new line
mov bl, num2 ;move value of num2 to bl
sub num1,bl ;subtracts the value in num2 from the value in num1
mov al, num1 ;move result to a register
mov result, al ;move the result of the subtraction to result
call write ;display result with write procedure
jmp exit
;-----------------------
;procedure declarations:
proc endl
mov ah,09
mov dx, offset new_line
int 21h ;goes to next line, i.e. "enter"
ret
endp
proc read
mov ah,09
mov dx, offset first_msg
int 21h ;displays the string in first_msg
mov ah,01 ;read char
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the vaule in the al
mov num1,al ;moves the value in the al to the variable num1
mov ah,01 ;read second char
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num2,al ;moves the value in the al to the variable num2
mov al,num1 ;moves the value in num1 into the al
mul ten ;multiplies the value in the al by ten
add al,num2 ;adds the value in num2 to the al, to get the two-digit number
mov num1,al ;moves the two digit value into
call endl
mov ah,09
mov dx, offset second_msg ;displays the string in second_msg
int 21h
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num2,al ;moves the new value in the al into the variable num2
mov ah,01
int 21h ;copies a value into the al, using subfunction 01
sub al,48 ;subtracts 48 from the value in the al
mov num3,al ;moves the new value in the al into the variable num3
mov al,num2 ;moves the value in num2 into the al
mul ten ;multiplies the value in the al by ten
add al,num3 ;adds the value in num3 to the al, to get a two-digit number
mov num2,al ;moves the value in the al into the variable num2
ret ;first number in num1, second in num2
endp
;The write procedure writes the decimal stored in result.
;by dividing by ten it seperates the two digits as quotient
;and remainder. Then it outputs the quotient and remainder
;in ascii form.
proc write
mov dx,offset result_msg
mov ah,09h
int 21h ;display the result_msg string
mov al,result ;move the result from add/sub to al
mov ah,00 ;initialize ah
div ten ;div al by ten, quotient is in al
;remainder is stored in ah.
mov dl,ah ;move the remainder to dl
mov t2,dl ;store the remainder in t2
mov dl,al ;move quotient into dl
add dl,48 ;add 48 to dl, to convert it to ascii
mov ah,02h ;char display interupt code
int 21h ;display char in dl register
mov dl,t2 ;move remainder to t2
add dl,48 ;convert it to ascii by adding 48
mov ah,02h ;display character in dl interupt code
int 21h ;diplays contents of dl
call endl ;output a new line
ret
endp
exit:
mov ax, 4c00h ;This is just a failsafe exit
int 21h
END
Upvotes: 1
Reputation: 58507
Here's a procedure (in NASM syntax) that will print any unsigned 16-bit integer:
; Converts the integer value in AX to a string in
; decimal representation and prints it.
; The digits are placed in a string buffer in reverse
; order - i.e. for the value 123, '3' would be placed
; last in the buffer, then '2' before that, and '1'
; before that, so that we'd end up with the string "123".
print_int:
mov byte [buffer+9],'$' ; add a string terminator at the end of the buffer
lea si,[buffer+9]
mov bx,10 ; divisor
print_loop:
xor dx,dx ; clear dx prior to dividing dx:ax by bx
div bx ; AX /= 10
add dl,'0' ; take the remainder of the division and convert it from 0..9 -> '0'..'9'
dec si ; store characters in reverse order
mov [si],dl
test ax,ax
jnz print_loop ; repeat until AX==0
mov ah,9 ; print string
mov dx,si
int 21h
ret
buffer: resb 10
I noticed that you've got a lot of duplicate code in your program. It would be better if you only read the input numbers in once place in your program, and then performed the appropriate operation on them based on the operator specified by the user.
Upvotes: 1