; 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