2
votes

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)

1
You may find great benefit in the godbolt.org compiler explorer!ti7

1 Answers

5
votes
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.