Home > Blockchain >  How to use div properly in Assembly language emu8086?
How to use div properly in Assembly language emu8086?

Time:04-25

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:

  1. You convert the input from character to value in the range [1,9] too late. The tests are using the ASCII code instead.
  2. 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 is mov num1,num supposed to do? Does emu8086 accept this? Whatever it does will influence the word that you load from address num.
  3. You are mistakenly referring to the opposite message in those ...Multipleof3 codes.
  4. 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.

  • Related