My task was to implement Euler's totient function, and I'm looking for any and all criticism.
.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.code
;------------------------------------------------------------------------------
; _phi@4 (int x)
;
; Calculates Euler's totient function using the product formula.
;
; param:
x TEXTEQU <[ebp+8]> ;integer argument
;
; Exit: The result is stored in eax
;------------------------------------------------------------------------------
_phi@4:
push ebp ; setup stack, save regs
mov ebp, esp
push ebx
push ecx
push edx
mov ecx, x ; init result as x
; Consider the prime factors of x and subtract their multiples
; from the result
mov ebx, 2 ; initialize loop counter p
L3: mov eax, ebx
mul ebx
cmp DWORD PTR x, eax ; loop if( x >= p * p)
jnge endL3;
; Check if p is a prime factor
cdq
mov eax, x
div ebx
cmp edx, 0 ; if(x % p == 0)
jne noprime
;if yes, update x and result
L2: cdq
mov eax, x
div ebx
cmp edx, 0 ; if(x % p == 0)
jne endL2
mov x , eax ; x /= p
jmp L2
endL2:
cdq
mov eax, ecx
div ebx
sub ecx, eax ;result -= result / p
noprime:
inc ebx
jmp L3
endL3:
; If x has a prime factor greater than sqrt(x)
cmp DWORD PTR x, 1
jle finish
cdq
mov eax, ecx
div DWORD PTR x
sub ecx, eax
finish:
mov eax, ecx
pop edx
pop ecx
pop ebx
pop ebp
ret 4
main:
push 100
call _phi@4
INVOKE ExitProcess, 0
END main
Is there any way I can make the code more efficient? - possibly with fewer instructions? Also, I'm looking for pointers on style. Is the code readable?
x
into a register (say esi) rather than repeatedly read/writing memory? You could read it once on entry, and write it once at exit. \$\endgroup\$