I'm trying to do in assembly the equivalent to:
const array = ["ola", "mundo"]
for (i = 0; i < array.length; i++){
console.log(array[i])
}
global main
section .data
newline db 0xa
array db "ola","mundo"
arrayLength equ $ - array
section .text
main:
mov ecx, 0
beginLoop:
cmp ecx, arrayLength
je exit
mov r8d, ecx
push ecx
mov eax, 4
mov ebx, 1
mov ecx, array+r8d
mov edx, arrayLength
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
pop ecx
inc ecx
jmp beginLoop
exit:
mov eax, 1
mov ebx, 0
int 0x80
But when I compile it, it throws an error whenever I use the register r8d
to access the index:
nasm -f elf64 -o array.o array.asm
array.asm:22: error: invalid operand type
The line 22 is mov ecx, array+r8d
.
but when I compile it, it throws an error whenever I use the register
r8d
to access the index:
NASM can't load the address via mov ecx, array+r8d
because the r8d
component is not an immediate value, it's a register whose value is only available at runtime. You could use LEA and write lea rcx, [array + r8]
. Use the whole qword register in an addressing mode.
array db "ola","mundo"
There's no way for your program to know where one array element ends and where the next array element begins. All your program 'sees' is an 8-character string of characters "olamundo".
One solution could be using zero-termination like in array db "ola", 0, "mundo", 0
. Another solution could do with strings of equal size using a filler like in array db "ola ", "mundo "
. And yet another solution could be prefixing the array elements with a byte that holds a length indication:
array db 3, "ola", 5, "mundo"
arrayLength equ $ - array
A first draft:
main:
mov rsi, array
mov ebx, 1
.Loop:
movzx edx, byte [rsi] ; Load RDX with length byte
inc rsi ; Make RSI point at current text string
mov rcx, rsi
add rsi, rdx ; Now RSI points at next array element
mov eax, 4
int 0x80
mov edx, 1
mov rcx, newline
mov eax, 4
int 0x80
cmp rsi, array + arrayLength
jb .Loop