I am just starting out with Assembly (NASM), and I try to create a variant for solving Project Euler problem 1 (add all multiples of 3 or 5 under 1000). The variant I try to make an algorithm for makes use of the fact that the multiples are spaced in a repeating pattern (+3, +2, +1, +3, +1, +2, +3 and repeat), but the loop just exits after the first iteration.
The principle should be the same as this C solution, which calculates the correct result:
int sum = 0, s = 0;
int steps[7] = {3,2,1,3,1,2,3};
for (int n = steps[s]; n < 1000; n += steps[s]) {
sum += n;
s++;
if (s == 7)
s = 0;
}
My asm looks like this:
section .data
msg db "%d", 10, 0 ;return string for printf (just the result)
steps dd 3, 2, 1, 3, 1, 2, 3 ;how the multiples of 3 and 5 are spaced
section .text
extern printf
global main
main:
xor rax, rax ;prepare rax which will store the result
xor rbx, rbx ;prepare rbx, which will be the current number
arr0:
xor rcx, rcx ;prepare rcx, which will be the array index
countup:
add rbx, [steps + rcx * 4] ;add steps@rcx to rbx
add rax, rbx ;add rbx to the result
inc rcx ;increase the array index
cmp rcx, 7 ;check if we reached the end of the array
je arr0 ;if yes, jump to arr0
cmp rbx, 1000 ;check if we reached 1000
jl countup ;if not, loop again
... print and exit come next
The program compiles fine but the result is just 3, so obivously the loop never repeats but just executes once. What would I need to change in order to get this working?
If I manually create repeating pattern like below, it is working fine, obviously just until I reach the end of the array.
add rbx, [steps + rcx * 4] ;add steps@rcx to rbx
add rax, rbx ;add rbx to the result
inc rcx ;increase the array index
add rbx, [steps + rcx * 4] ;add steps@rcx to rbx
add rax, rbx ;add rbx to the result
inc rcx ;increase the array index
add rbx, [steps + rcx * 4] ;add steps@rcx to rbx
add rax, rbx ;add rbx to the result
inc rcx ;increase the array index
...
So thanks to your comments I was able to solve the problem. As was pointed out by Erik, the main issue was the 32/64bits mixup. As soon as I either changed everything to only use the eXX registers, or adjusted the data type of the array to dq and the multiplier for the index to 8, it worked perfectly fine.
And ecm was also right of course, so I adjusted the checks and the structure a bit: