I wanted to learn asm, coming from C
A book suggested trying to implement this algorithm which is a quite simple sorting algorithm
begin
for i = 0 to len-1
small = arr(i)
index = i
for j = i to len-1
if ( arr(j) < small ) then
small = arr(j)
index = j
end_if
end_for
arr(index) = arr(i)
arr(i) = small
end_for
end_begin
The beginning of my code is that (can give the rest if needed)
section .bss
section .data
len dq 5
array dq 1 , 3 , 6 , 8 , 2
section .text
global _start
_start:
mov rdi , [len]
mov rsi , array
call sort
exit
sort:
push rbp
mov rbp,rsp
push qword 0 ; i_counter = rbp-8
push rdi ; len = rbp-16
push rsi ; *array = rbp -24
push qword 0 ; j = rbp - 32
dec qword [rbp-16]
i_loop:
mov r8 , [rbp-16]
cmp [rbp-8], r8 ; if counter = len - 1 (decreased above)
je end_i_loop
mov rbx , [rbp-8]
mov rax , qword [ rbp-24 - rbx * 8] ; small = array(i) and line 38
mov rcx , [rbp-8] ; index = i
mov [rbp - 32 ] , rcx ; j = i
On line 38 i get the error error: invalid effective address
At first i thought it was an alignment mistake (thus the push quadword at the beginning of the sort function )
Then i tried with movq instructions (which does not work for other reasons obviously, i since read the manual of the instruction)
moving toward a memory address seems to work, even if referenced by a register (at least mov [rax] , qword [ rbp-24 - rbx * 8] compiles), but i hardly see any point in doing that)
I might fix it with lea, which compiles, but i want the value, doesn't mov rax,, qword [ rbp-24 - rbx * 8] gives the value pointed by rbp-24-rbx*8 ?
Since i have the same problem at four different points in the code (after line 38), i'm totally stuck and have no idea what to try now
Could someone explain why this does not compile, and if possible give a solution (or at least hints)
mov rax , qword [ rbp-24 - rbx * 8]
This is illegal on its face because the SIB addressing mode can only add the scaled index register (here rbx * 8
); it cannot subtract it. But if you want array(i)
then you want to add it anyway, since rbx
here corresponds to i
.
However, it seems like you are trying to use the pointer stored at rbp-24
as the base address, and that's not supported either; the base address must be from a register. Conveniently, you already have the address of array
in register rdi
, so I think what you want is simply
mov rax, qword [rdi + rbx * 8]
Just a general tip as you improve your code: the main reason to use assembly language at all is speed, and the most important way to achieve speed is to minimize memory access. You really don't want to be keeping your local variables on the stack and accessing memory every time you touch them. The machine has plenty of registers, so just pick a register for each variable and keep it there.
You might get in the habit of overusing memory if you've been trying to learn by reading unoptimized compiler assembly output; a non-optimizing compiler will keep everything on the stack, so that it has a consistent location and a consistent address should it be needed. But try enabling optimization and you'll see it all magically vanish, and everything done with registers as much as possible. That's more what you should try to strive for.