Search code examples
assemblyx86dosx86-16

Assembly code calculation of the GCD of two numbers is not working


.MODEL small
.STACK 100h
.DATA
    A dw 0
    B dw 0
    C Dw 0
.CODE
MAIN PROC
    mov AX,@DATA
    mov DS,AX

PROMPT:
    mov AH,1
    int 21h
    mov A,Ax    
    mov AH,2
    mov DL,20H
    int 21H
    mov AH,1
    int 21h
    mov B,Ax
    mov AH,2
    mov DL,20H
    int 21H

    mov Ax,A
    ;sub AL,'0'
    mov Bx,B
    ;sub BL,'0'

    cmp Ax,Bx
    JE EXIT
    JA GCD 
    JB EXCG

GCD:
    MOV AH,0D
    DIV AL
    CMP AH,0D
    JE EXIT
    MOV Bx,Ax
    MOV bL,AL 
    JMP GCD

EXCG:
    MOV AH,0D
    XCHG Ax,Bx
    JMP GCD

 EXIT:
    MOV Dx,Ax
    MOV AH,2
    ;MOV DL,AL
    INT 21H

  MOV AH,4CH
  INT 21H

MAIN ENDP 
END MAIN

I expect the output would be the greatest common divisor of the two numbers. but my code shows some ASCII value of unexpected characters.


Solution

  • mov AH,1
    int 21h
    mov A,Ax
    

    This DOS function returns a character in AL. You should not store the whole of AX as your first number! What you need is:

    mov ah, 1
    int 21h
    sub al, '0'   ;Convert to a true number, no longer a character
    mov A, al
    

    Same for your second number.


    cmp Ax,Bx
    

    Compare bytes here. Write cmp al, bl.


    MOV AH,0D
    DIV AL
    CMP AH,0D
    JE EXIT
    

    It's fine to zero extend the dividend but think a moment about what DIV AL does. It will divide AX by AL. Since AL is just the low portion of AX, this division will always return a quotient of 1 with a 0 remainder. Not very useful because the EXIT will always be chosen.


    EXIT:
    MOV Dx,Ax
    MOV AH,2
    ;MOV DL,AL
    INT 21H
    

    To display a result you have to convert it back into a character. You must add 48 to do this:

    EXIT:
     mov dl, al
     add dl, '0'
     mov ah, 02h
     int 21h