program assembler_test; {\$mode objfpc}{\$H+} {\$asmmode INTEL} {\$R *.res} function __gcd32: longint; assembler; {-Calculate GCD of unsigned (A,B) in (eax,edx)} asm push ebx {done if A=B, otherwise if A= edx. Calculate odd parts a,b with A=a*2^e(a), B=b*2^e(b)} @@1: bsf ecx, edx {if B=0 return A} jz @@x bsf ebx, eax {ebx=e(a), A cannot be zero} shr edx, cl {edx=b} xchg ebx, ecx shr eax, cl {eax=a} cmp ebx,ecx {ebx = e = min(e(a),e(b)} jb @@2 mov ebx,ecx @@2: cmp eax,edx {compare a and b} jz @@4 {done if equal} {in the main loop both a and b are always odd} {therefore for |a-b| is even and non-zero} push esi @@3: mov esi, eax {eax=a, edx=b} {calculate max(a,b) and min(a,b) without branches} {see H.S.Warren, Hacker's Delight, Revision 1/4/07} {http://www.hackersdelight.org/revisions.pdf} sub esi, edx {esi=a-b} sbb ecx, ecx {if a>=b then ecx=0 else ecx=-1} and esi, ecx {if a>=b then esi=0 else esi=a-b} add edx, esi {if a>=b then edx=b else edx=a, i.e. edx=min(a,b)} sub eax, esi {if a>=b then eax=a else eax=a-(a-b)=b=max(a,b)} sub eax, edx {a'=max(a,b)-min(a,b), b'=min(a,b)} bsf ecx, eax {a'=|a-b| is even, divide out powers of 2} shr eax, cl cmp eax, edx {compare new a and new b} jnz @@3 {and repeat loop if not equal} pop esi @@4: mov ecx, ebx {shift by initial common exponent e} shl eax, cl @@x: pop ebx end; begin __gcd32; end.