I am currently learning assembly for university, and I'd like to hear some feedback concerning what I've written. Currently I have implemented Problems 1, 2, 3 and 10 from ProjectEuler. The goal is to sum all primes ranging from 0 to 2,000,000.
For problem 10 I use the formula 6n +- 1 to check for primes. To actually check them, I test divisors 2, 3, 5, 7, ... I'm currently only using the general purpose registers of the x64 architecture.
Do you have any feedback concerning this code? Can I do something better? Optimize something?
I use NASM in x64 mode. This is my current implementation:
; CurrentPrime Current prime to test ; Sum Sum ; CurrentN n of 6n +- 1 ; PrimeMode Wether we're doing + or - 1 (0 means -) %define Sum r9 %define CurrentPrime r8 %define CurrentN r10 %define PrimeMode r12 section .text global main main: mov Sum, 5 ; 2+3 not included in 6n +- 1 mov CurrentN, 0 ; This gets inc'ed below loop: ; Increase n inc CurrentN ; Break every 10000 Ns for debugging reasons mov rax, CurrentN mov rbx, 10000 mov rdx, 0 div rbx cmp rdx, 0 jne _debug_next nop ; Break here _debug_next: ; multiply it by 6 and save it to CurrentPrime mov rax, CurrentN mov rbx, 6 mul rbx mov CurrentPrime, rax ; Start with 6n-1 dec CurrentPrime ; Reset registers for testing mov PrimeMode, 0 ; This is our divisor mov rcx, 2 next_prime_test: ; When the number to test is >= 2000000, then exit cmp CurrentPrime, 2000000 jge finish ; When divisor_to_test > (number_to_test/2), then this is prime mov rax, CurrentPrime mov rbx, 2 mov rdx, 0 div rbx cmp rax, rcx jl is_prime ; Test divisor for divisor mov rax, CurrentPrime mov rbx, rcx mov rdx, 0 div rbx cmp rdx, 0 je check_next_prime ; We only check odd numbers. ; But to get from 2 to 3, we may not inc when we're at 2. cmp rcx, 2 je skip_add inc rcx skip_add: ; This divisor isn't a divisor of our number. Let's try with the next divisor. inc rcx jmp next_prime_test is_prime: ; This number is prime, add it to our result. add Sum, CurrentPrime check_next_prime: ; If we're doing 6n-1, increase by 2 to get 6n+1, then check again cmp PrimeMode, 0 ; If we've done 6n+1, then go for the next n jne loop mov PrimeMode, 1 ; Set plus mov rcx, 2 ; Reset rcx to start over with a new prime add CurrentPrime, 2 ; 6n-1 +2 = 6n+1 ; Check 6n+1 jmp next_prime_test finish: ; Result is in rax mov rax, Sum ret