Hello!

I'm working on a project for class (Assembly Intel 8086) and am having trouble figuring out my problem with this program.

The project is to set-up to find GCD of two numbers. However, I can't figure out why the division loop I have isn't working properly. I have the full code and everything is ready to go and the output looks fine, but it just outputs the 2nd variable instead of the GCD.

Anyone with more experience know where I'm messing up?

;CPSC 2382: Introduction to Computer Systems and Assembly Language
;Spring 2010
;Project 3
;Programmer: NJW
;Descriptions: Compute GCD of two integers and display the results on the screen.

.LIST                    

TITLE Project 3 - Greatest Common Divisor (GCD.asm)        

INCLUDE Irvine32.inc                                

.data
PrintAnd BYTE " and ",0
PrintMessage BYTE " share the following Greatest Common Divisor (GCD): ",0
PrintEndline BYTE " ",0dh, 0ah, 0
value1 DWORD 0                   ; val1 and val2 are the integers used when finding GCD
value2 DWORD 0

.code  
main PROC

mov value1, 84                   ; first, we'll find the GCD of 84 and 18
mov value2, 18   

call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 84 and 18

mov value1, 111                  ; next, we'll find the GCD of 111 and 13
mov value2, 13
        
call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 111 and 13

mov value1, 180                  ; next, we'll find the GCD of 180 and 48
mov value2, 48
        
call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 180 and 48

exit                             ; halts the program
main ENDP                        ; marks the ends of the main procedure

;----------------------------------------------------------
DisplayGCD PROC
;
; When this subroutine is called, it will print out 2
; values and will prepare for when the GCD subroutine is
; called which will print the GCD. This display subroutine
; will show this each time: "[value1] and [value2] share
; the following Greatest Common Divisor (GCD): ".
;----------------------------------------------------------
    mov eax, 0
    mov edx, 0
    mov eax, value1              ; prepare to print integer
    call WriteDec                ; print value1 to the screen
    mov edx, OFFSET PrintAnd     ; mov the message to edx so it can print to the screen
    call WriteString             ; print " and " to the screen
    mov eax, value2              ; prepare to print integer
    call WriteDec                ; print value2 to the screen
    mov edx, OFFSET PrintMessage ; mov the message to edx so it can print to the screen
    call WriteString             ; print "share the following Greatest Common Divisor (GCD): "
    ret
DisplayGCD ENDP                     ; marks the ends of the main procedure

;----------------------------------------------------------
GCD PROC
;
; Takes 2 values from main and loops a set of division
; instructions in order to determine GCD. It will then
; return to main and do the same with other given integers.
;----------------------------------------------------------
    mov edx, value1               ; mov value1 (dividend) into dx
    cdq
    mov eax, value2               ; mov value2 (divisor) into ax
    div eax                       ; for 84 and 18 example, ax=4 and remainder in dx=12
    
        L1:                      ; loop these instructions until GCD is determined
        cmp edx, 0                ; if remainder is 0, then GCD is found and can end procedure
        je ENDGCD                    
        mov eax, edx              ;  GCD algorithm needs the remainder to be in divisor slot
        mov edx, value2           ; mov value2 to dividend to prepare for division
        mov value2, eax           ; for the rest of the GCD algorithm to work, must save previous remainder
        div eax                   ; for 84 and 18 example, ax=1 and remainder in dx=6
        loop L1                  ; loop until remainder is zero and GCD has been determined

        ENDGCD:
        mov eax, value2          ; mov value2, which is the remainder that resulted in the GCD to eax
        call WriteDec            ; print the GCD to the screen
        mov edx, OFFSET PrintEndline
        call WriteString
        ret                          ; return to find the GCD of other integers
GCD ENDP                          ; marks the ends of the main procedure
    
END main                          ; END directive marks the last line of the program

Solved myself!

I forget to insert a cdq in the loop itself and had my dividend/divisor registers mixed up. So I went back and made it all clearer.

Member Avatar for Juniahh

How does the final code look?

You can figure it out based on my explanation where I said I solved it. Plus, if you're in Dr. Chiang's class, I wouldn't want you to have my full project submission : P

However, I will post my code after the due date of the project (May 6th), so stay tuned :)

Member Avatar for Juniahh

haha No it's not that I don't have that teacher but I was comparing mine to yours. I had the same assignment that's why look. The only problem is that it won't print which is weird I'll figure it out though.

INCLUDE Irvine32.inc

.data
msg1 BYTE " and ",0
msg2 BYTE " GCD is: ",0
val1 DWORD ?
val2 DWORD ?

.code
main PROC

   mov val1,119
   mov val2,544
   call pmsg
   call gcd

exit
main ENDP

;-----------------------------
pmsg PROC
;
;  displays data on screen
;-----------------------------

   mov eax,val1
   call WriteDec
   mov edx,OFFSET msg1
   call WriteString
   mov eax,val2
   call WriteDec
   mov edx,OFFSET msg2
   call WriteString
   call crlf
   ret


pmsg ENDP

;------------------------
gcd PROC
;
;  finds gcd
;------------------------

   mov edx,0			;n
   mov eax,val2		;x
   mov ebx,val1		;y
   div ebx

L1:
   cmp eax,0
   je endgcd
   mov ebx,0
   mov ebx,eax
   mov eax,edx
   mov edx,0
   div ebx
   loop L1

endgcd:
   mov esi,0
   mov val1,ebx
   mov esi,OFFSET val1
   call WriteDec
   call crlf
   ret

gcd ENDP




END main

Here is the working version, as promised:

;Programmer: NJW
;Descriptions: Compute GCD of two integers and display the results on the screen.
;Due Date: May 6th, 2010
;Date Written: April 22nd, 2010
;Date Revisions: April 29th, 2010

.LIST                    

TITLE Project 3 - Greatest Common Divisor (GCD.asm)        

INCLUDE Irvine32.inc                                

.data
PrintAnd BYTE " and ",0
PrintMessage BYTE " share the following Greatest Common Divisor (GCD): ",0
PrintEndline BYTE " ",0dh, 0ah, 0
value1 DWORD 0                   ; val1 and val2 are the integers used when finding GCD
value2 DWORD 0

.code  
main PROC

mov value1, 84                   ; first, we'll find the GCD of 84 and 18
mov value2, 18   

call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 84 and 18

mov value1, 111                  ; next, we'll find the GCD of 111 and 13
mov value2, 13
        
call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 111 and 13

mov value1, 180                  ; next, we'll find the GCD of 180 and 48
mov value2, 48
        
call DisplayGCD                  ; call the DisplayGCD subroutine to print messages to screen
call GCD                         ; call the GCD subroutine to determine GCD of 180 and 48

exit                             ; halts the program
main ENDP                        ; marks the ends of the main procedure

;----------------------------------------------------------
DisplayGCD PROC
;
; When this subroutine is called, it will print out 2
; values and will prepare for when the GCD subroutine is
; called which will print the GCD. This display subroutine
; will show this each time: "[value1] and [value2] share
; the following Greatest Common Divisor (GCD): ".
;----------------------------------------------------------
    mov eax, 0
    mov edx, 0
    mov eax, value1              ; prepare to print integer
    call WriteDec                ; print value1 to the screen
    mov edx, OFFSET PrintAnd     ; mov the message to edx so it can print to the screen
    call WriteString             ; print " and " to the screen
    mov eax, value2              ; prepare to print integer
    call WriteDec                ; print value2 to the screen
    mov edx, OFFSET PrintMessage ; mov the message to edx so it can print to the screen
    call WriteString             ; print "share the following Greatest Common Divisor (GCD): "
    ret
DisplayGCD ENDP                  ; marks the ends of the main procedure

;----------------------------------------------------------
GCD PROC
;
; Takes 2 values from main and loops a set of division
; instructions in order to determine GCD. It will then
; return to main and do the same with other given integers.
;----------------------------------------------------------
    mov eax, value1              ; mov value1 (dividend) into dx
    cdq
    mov ebx, value2              ; mov value2 (divisor) into ax
    div ebx                      ; for 84 and 18 example, ax=4 and remainder in dx=12
    
        L1:                      ; loop these instructions until GCD is determined
        cmp edx, 0               ; if remainder is 0, then GCD is found and can end procedure
        je ENDGCD                    
        mov ebx, edx             ;  GCD algorithm needs the remainder to be in divisor slot
        mov eax, value2          ; mov value2 to dividend to prepare for division
        mov value2, ebx          ; for the rest of the GCD algorithm to work, must save previous remainder
        cdq
        div ebx                  ; for 84 and 18 example, ax=1 and remainder in dx=6
        loop L1                  ; loop until remainder is zero and GCD has been determined

        ENDGCD:
        mov eax, value2          ; mov value2, which is the remainder that resulted in the GCD to eax
        call WriteDec            ; print the GCD to the screen
        mov edx, OFFSET PrintEndline
        call WriteString
        ret                       ; return to find the GCD of other integers
GCD ENDP                          ; marks the ends of the main procedure
    
END main                          ; END directive marks the last line of the program
Member Avatar for Juniahh

Mine looks different from yours but it still works.

INCLUDE Irvine32.inc

.data
msg1 BYTE " and ",0
msg2 BYTE " GCD is: ",0
val1 DWORD ?
val2 DWORD ?

.code
main PROC

   mov val1,100
   mov val2,50
   call pmsg
   call gcd

   mov val1,108
   mov val2,30
   call pmsg
   call gcd

   mov val1,544
   mov val2,119
   call pmsg
   call gcd

exit
main ENDP

;-----------------------------
pmsg PROC
;
;  displays data on screen
;-----------------------------

   mov eax,val1
   call WriteDec
   mov edx,OFFSET msg1
   call WriteString
   mov eax,val2
   call WriteDec
   mov edx,OFFSET msg2
   call WriteString
   ret


pmsg ENDP

;------------------------
gcd PROC
;
;  finds gcd
;------------------------

mov eax,val1
cdq
mov ebx,val2
div ebx

L1:
   mov eax,ebx
   mov ebx,edx
   cmp ebx,0
   je endgcd
   mov val1,edx
   cdq
   div ebx
   loop L1

endgcd:
   call WriteDec
   call crlf
   ret

gcd ENDP

END main
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.