I am developing an assembly language program that will check whether an inputted number is divisible by 3 or not, now I am struggling to get things correct but my code is running..and it seems like dx register always have content zero even after div has been executed..
org 100h
jmp main
msg_prpt: db 'Enter a number (1-9): $'
msg_err: db 0dh, 0ah, 'Number out of range. $'
msg_1: db 0dh, 0ah, 'Number is divisible by 3. $'
msg_2: db 0dh, 0ah, 'Number is not divisible by 3. $'
num: db ?
num1 dw ?
display:
mov ah, 9h ; "display string" function for int 21h
int 21h
ret
dsp_prpt:
mov dx, msg_prpt ; copy contents of msg_prompt to dx
call display
ret
dsp_err:
mov dx, msg_err ; copy contents of msg_err to dx
call display
ret
get_num:
mov ah, 1h ; "character input" function for int 21h (stored in al)
int 21h
mov [num], al ; copy contents of al to space at address [num]
mov num1,num
ret
;checking if the inputted number is divisible by 3
validateDivisibleby3:
mov dx,0
mov ax,num ; copy character to ax for comparison
mov bx,03h
idiv bx
cmp dx,0
je isMultipleof3:
call isNotMultipleof3
ret
convert:
sub al, 30h ; subtract 30h from input to get numeric from ascii
ret
isMultipleof3:
; print the result:
mov dx, msg_2 ; copy contents of msg_prompt to dx
call display
ret
isNotMultipleof3:
; print the result:
mov dx, msg_1 ; copy contents of msg_prompt to dx
call display
ret
exit:
; wait for any key press:
mov ah, 0
int 16h
ret ; return control to operating system.
main:
call dsp_prpt
call get_num
call validateDivisibleby3
call convert
call exit
I will really appreciate your help....
CodePudding user response:
mov dx, msg_prpt
Are you sure that you are using emu8086? Since emu8086 uses MASM style, loading the address of a message would have to be mov dx, OFFSET msg_prpt
or (but this is one byte longer) lea dx, msg_prpt
. Your program loads many addresses, so this is important.
I am struggling to get things correct
Reasons why your code is not showing correct results:
- You convert the input from character to value in the range [1,9] too late. The tests are using the ASCII code instead.
- The value that you inspect is taken from the num variable using
mov ax, num
, but the num variable is but a byte-sized variable. The assembler should have complained about this, then again emu8086 is full of quirks...
What ismov num1,num
supposed to do? Does emu8086 accept this? Whatever it does will influence the word that you load from address num. - You are mistakenly referring to the opposite message in those ...Multipleof3 codes.
- Pay attention to syntax in
je isMultipleof3:
. Even if emu8086 accepted this trailing colon, I wouldn't trust it generated the correct code.
Seeing that you work with values in the range from 1 to 9, using the word-sized division is somewhat overkill. Next code uses the byte-sized division instead. I've also simplified the branching.
get_num:
mov ah, 01h ; "character input" function for int 21h
int 21h ; -> AL
sub al, 30h ; subtract 30h from input to get numeric from ascii
mov [num], al ; copy contents of al to space at address [num]
ret
validateDivisibleby3:
mov al, [num]
mov ah, 0 ; (*)
mov bl, 3
div bl ; AX / BL --> AL quotient, AH remainder
mov dx, OFFSET msg_1 ; Divisible
test ah, ah ; Is remainder 0 ?
jz display ; Yes
mov dx, OFFSET msg_2 ; Not Divisible
; IN (dx)
display:
mov ah, 09h
int 21h
ret
(*) Using cbw
would shave off one byte. You can use it safely since you know that the value is AL
is a positive number.
Danger
exit: mov ah, 0 int 16h ret ; return control to operating system.
You can not call
exit and then expect to return to DOS with a mere ret
instruction! The call
instruction will have placed some return address on the stack and it's not the right return address to return control to DOS.
Several options exist. The quick fix is to replace the call exit
by a jmp exit
.