home *** CD-ROM | disk | FTP | other *** search
- ; Finds and returns the greatest common divisor of two integers.
- ; Uses Euclid's Algorithm: divides the larger integer by the
- ; smaller; if the remainder is 0, the smaller integer is the gcd,
- ; otherwise the smaller integer becomes the larger integer, the
- ; remainder becomes the smaller integer, and the process is
- ; repeated. Avoids code recursion.
- ;
- ; Tested with MASM 5.1.
- ;
- ; C near-callable as:
- ; unsigned int gcd(unsigned int int1, unsigned int int2);
-
- ; Parameter structure:
- parms struc
- dw ? ;pushed BP
- dw ? ;pushed return address
- int1 dw ? ;integers for which to find
- int2 dw ? ; the gcd
- parms ends
-
- .model small
- .code
- public _gcd
- align 2
- _gcd proc near
- push bp ;preserve caller's stack frame
- mov bp,sp ;set up our stack frame
- push si ;preserve caller's register variables
- push di
-
- ;Swap if necessary to make sure that int1 >= int2
- mov ax,int1[bp]
- mov bx,int2[bp]
- cmp ax,bx ;is int1 >= int2?
- jnb IntsSet ;yes, so we're all set
- xchg ax,bx ;no, so swap int1 and int2
- IntsSet:
-
- ; Now loop, dividing int1 by int2 and checking the remainder, until
- ; the remainder is 0. At each step, if the remainder isn't 0, assign
- ; int2 to int1, and the remainder to int2, then repeat.
- GCDLoop:
- ;if the remainder of int1 divided by
- ; int2 is 0, then int2 is the gcd
- sub dx,dx ;prepare int1 in DX:AX for division
- div bx ;int1/int2; remainder is in DX
- and dx,dx ;is the remainder zero?
- jz Done ;yes, so int2 (BX) is the gcd
- ;no, so move int2 to int1 and the
- ; remainder to int2, and repeat the
- ; process
- mov ax,bx ;int1 = int2;
- mov bx,dx ;int2 = remainder from DIV
-
- ;---start of loop unrolling; the above is repeated three times---
- sub dx,dx ;prepare int1 in DX:AX for division
- div bx ;int1/int2; remainder is in DX
- and dx,dx ;is the remainder zero?
- jz Done ;yes, so int2 (BX) is the gcd
- mov ax,bx ;int1 = int2;
- mov bx,dx ;int2 = remainder from DIV
- ;---
- sub dx,dx ;prepare int1 in DX:AX for division
- div bx ;int1/int2; remainder is in DX
- and dx,dx ;is the remainder zero?
- jz Done ;yes, so int2 (BX) is the gcd
- mov ax,bx ;int1 = int2;
- mov bx,dx ;int2 = remainder from DIV
- ;---
- sub dx,dx ;prepare int1 in DX:AX for division
- div bx ;int1/int2; remainder is in DX
- and dx,dx ;is the remainder zero?
- jz Done ;yes, so int2 (BX) is the gcd
- mov ax,bx ;int1 = int2;
- mov bx,dx ;int2 = remainder from DIV
- ;---end of loop unrolling---
- jmp GCDLoop
-
- align 2
- Done:
- mov ax,bx ;return the gcd
- pop di ;restore caller's register variables
- pop si
- pop bp ;restore caller's stack frame
- ret
- _gcd endp
- end