GreatestCommonDivisor<GCD>

VSBrown 0 Tallied Votes 648 Views Share

A test program that will call the PROC findGCD, passing in the integer values input by the user and then it will display the results to the screen.

TITLE: GreatestCommonDivisor<GCD> (GCD.asm)

;------------------------------------------------------------
; Name: 
;
; Filename: GCD.asm
;
; Project #: 5
;
; Completed: March 9, 2003
;
; Description: My fifth assembly program. A test program that
;              will call the PROC findGCD, passing in the integer
;              values input by the user and then it will diplay
;              the results to the screen.
;              From Assembly Language For Intel-Based Computers,
;              4th Ed. by Kip R. Irvine. Problem #6 on pg. 257.
;
; Reference:   Assembly Language For Intel-Based Computers,
;              4th Ed. by Kip R. Irvine
;------------------------------------------------------------
INCLUDE Irvine32.inc

.data
int1 sdword ?
int2 sdword ?
caseTable byte '1'                ;lookup value
          dword enterInt          ;address of lookup value
entrySize = ($ - caseTable )
          byte '2'
          dword endTest
          numberOfEntries = 2
msgIntro  byte "This is Your Name's fifth assembly program. A test program that",0dh,0ah
          byte "will call the PROC findGCD, passing in the integer values input by",0dh,0ah
          byte "the user and then it will display the results to the screen.",0dh,0ah,0
msgSelMn  byte "---------------------------------",0dh,0ah
          byte "Select 1 to Run Prog or 2 to Quit ",0dh,0ah
          byte "---------------------------------",0dh,0ah
          byte "Enter Selection: ",0
msgInt1   byte "Enter first integer: ",0
msgInt2   byte "Enter second integer: ",0
msgAns    byte "Greatest common divisor is: ",0
msgEnd    byte "GoodBye",0dh,0ah,0

.code
main PROC
;///////Intro Message/////////////////////////////////
	mov edx,OFFSET msgIntro  ;intro message into edx
        call WriteString         ;display msgIntro
        call Crlf                ;endl
        call WaitMsg             ;pause message
        call Clrscr              ;clear screen
        call Menu                ;menu procedure

ExitProg::exit                   ;global label to exit
main ENDP

;------------------------------------------------
Menu PROC
;
; Receives: Nothing
; Returns: Nothing
;------------------------------------------------
	mov  edx,OFFSET msgSelMn ;ask user for input
	call WriteString         ;display msgSelMn
	call ReadChar		 ;read one character
	call Clrscr
        mov  ebx,OFFSET caseTable;point EBX to the table
	mov  ecx,numberOfEntries ;loop counter

        L1:
	cmp  al,[ebx]		 ;match found?
	jne  L2		         ;no: continue
	call NEAR PTR [ebx + 1]	 ;yes: call the procedure
	call WriteString	 ;display message
	call Crlf                ;endl
	call Clrscr              ;clear screen
	jmp  L3		         ;exit the search

        L2:
	add  ebx,5		 ;point to the next entry
	loop L1		         ;repeat until ECX = 0

        L3:
	jmp Menu	         ;run Menu again

Menu ENDP

;------------------------------------------------
enterInt PROC
;
; Finds the GCD
; Receives: EAX = 1, EBX = 1
; Returns: EAX = GCD
;------------------------------------------------
        push edx

        mov  edx,OFFSET msgInt1  ;ask user for input
	call WriteString         ;display msgInt1
	call ReadInt		 ;read integer
        mov  int1,eax
	mov  edx,OFFSET msgInt2  ;ask user for input
        call WriteString         ;display msgInt2
	call ReadInt		 ;read integer
        mov  int2,eax

        mov eax,int1
        mov ebx,int2
        call findGCD
	mov  edx,OFFSET msgAns
	call WriteString
	call WriteDec
	call Crlf

        call WaitMsg
        pop edx

enterInt ENDP

;------------------------------------------------
findGCD PROC
;
; Finds the GCD
; Receives: EAX = 1, EBX = 1
; Returns: EAX = GCD
;------------------------------------------------
	push ebx
	push edx

	or eax,eax                ;explicitly set sign flag
	.IF SIGN?                 ;in the event of a neg int
	  neg eax
	.ENDIF
	or ebx,ebx
	.IF SIGN?
	  neg ebx
	.ENDIF

        L1:
        mov  edx,0
	div ebx		          ;divide int1 by int2
	cmp  edx,0		  ;does remainder = 0 ?
	je   L2		          ;yes: quit
	mov  eax,ebx		  ;no: prepare for
	mov  ebx,edx		  ;next iteration
	jmp  L1

        L2:
        mov eax,ebx		  ;EAX = GCD

	pop edx
	pop ebx
	ret

findGCD ENDP

;------------------------------------------------
endTest PROC
;
; Receives: Nothing
; Returns: EDX = offset of message
;          Sets CF = 1 to signal end of program
;------------------------------------------------
        mov  edx,OFFSET msgEnd   ;msgEnd into edx
	call WriteString	 ;display message
	call Crlf                ;endl
	stc	                 ;CF = 1
	jc ExitProg    	         ;if CF=1 then jump to Global ExitProg

endTest ENDP

END main

Dani AI

Generated

Nice, compact Euclidean implementation — and thanks to for posting the full source. A few targeted, practical notes to harden the program and avoid runtime traps when someone runs this later.

First, protect against divide-by-zero. The GCD loop uses a divide with the second operand as divisor; if the user enters 0 (or both numbers are 0) the program will fault. Add an early check that returns |a| when b==0, and treat the (0,0) pair explicitly (either print “undefined” or decide to return 0). Second, the Menu calls WriteString after a table-call without resetting EDX; that can print a leftover pointer/string. Either remove that post-call WriteString/Crlf block or reload EDX with the menu text before calling WriteString. Third, negating INT_MIN (0x80000000) overflows — consider handling that edge or operate on unsigned values.

Small assembly sketch to handle divisor-zero (insert at start of your findGCD):

cmp ebx, 0
je  .divisor_zero
; normal Euclid loop here...
jmp .done

.divisor_zero:
or eax, eax
jz  .both_zero       ; both inputs zero
.IF SIGN?
  neg eax            ; make result positive
.ENDIF
ret

.both_zero:
; choose behavior: set eax=0 (or print message) then return
mov eax, 0
ret

.done:
; continue normal return

Other micro-tweaks: use xor edx, edx instead of mov edx,0 for the zero remainder, and keep only the registers you must preserve (Irvine32 calls may clobber some regs). Test with pairs like (48,18)->6, (0,5)->5, (5,0)->5, (0,0)->explicit behavior, and negatives like (-24,18)->6 to confirm correct handling.

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.