In my code i'm trying to print an array in reverse. My two main ideas were to either use the stack and the LIFO property to do it or use a loop as index from 10 to 0 zero to access the elements in reverse. I went with the second one due to alignments problems with the stack method.
I'm quite new to assembly and would appreciate some help on that one, to know where my error is. Thanks in advance !
DEFAULT REL
; external functions for inputs/outputs printf and scanf/printf
extern printf
extern scanf
section .data
prompt db "Entrez un entier : ",0
longIntFormat db "%ld",0
section .bss
entier resb 10 ; array of 10 integers
section.text
push rbp
mov rcx, 0
mov rdx, 0 ; initialise counter
lea rcx, [entier] ; load array into register rcx
; fills the array with user input
_getLoop:
; call printf
lea rdi,[prompt]
mov rax,0
call printf wrt ..plt
; call scanf
lea rdi,[longIntFormat]
lea rsi, [rcx + rdx] ; array + Index
mov rax,0
call scanf wrt ..plt
inc rdx ; inc. Index/counter
cmp rdx, 10
jl _getLoop ; While counter is less than 10 (size of array)
mov rcx, 0 ; set rcx to 0
mov rdx, 10 ; counter set to 10
lea rcx, [entier] ; load array into rcx
; print the array in reverse using the counter as Index
_printLoop:
; call printf
lea rdi, [rcx + rdx] ; rdi = [array + Index]
mov rax,0
call printf wrt ..plt
dec rdx
cmp rdx, 0 ; compare counter with 0
jge _printLoop ; Once 0 is reached the loop has gone through all the array
;restores registers
pop rbp
; returns 0 to C program
mov rax, 0
ret
There are a lot of mistakes, e.g.:
scanf
and printf
have a slightly different syntax for format strings. If you plan to modify the printf
output (e.g. with a \n
) you have to create another format string.printf
, just the address of an integer. (printf needs a format string and takes integers by value.)"%ld"
means "long integer". On my sytem this is a Quadword (8 bytes). You are strictly dealing just with one byte._start
). If you push/pop, make sure you don't leave the stack misaligned before a call._start
(the process entry point) is not a function; you can't ret
from it. Call glibc's exit
function to make sure stdio buffers are flushed, or make a raw _exit
system call.section.text
is missing a space. It gets parsed as a label name like foo.bar:
instead of a directive switching to the .text
section. So your code ended up in .data
(or perhaps .bss
somehow), and segfaulted because those sections are linked into non-executable memory pages.Take a look at my corrected - now working - program:
DEFAULT REL
; external functions for inputs/outputs printf and scanf/printf
extern printf, fflush
extern scanf
section .data
prompt db "Entrez un entier : ",0
longIntFormat db " %ld",0
section .bss
entier resq 10 ; array of 10 integers
global _start
section .text
_start:
;and rsp, -16 ; Align stack to 16 (the ABI already guarantees this for _start)
mov rbx, 0 ; initialise counter
; fills the array with user input
_getLoop:
; call printf
lea rdi,[prompt]
mov rax,0
call printf wrt ..plt
; call scanf
lea rdi,[longIntFormat]
lea rsi, [entier + rbx * 8] ; array + Index
mov rax,0
call scanf wrt ..plt
inc rbx ; inc. Index/counter
cmp rbx, 10
jl _getLoop ; While counter is less than 10 (size of array)
mov rbx, 9 ; counter set to 10
; print the array in reverse using the counter as Index
_printLoop:
; call printf
lea rdi,[longIntFormat]
mov rsi, [entier + rbx*8] ; rdi = [array + Index]
mov rax,0
call printf wrt ..plt
dec rbx
cmp rbx, 0 ; compare counter with 0
jge _printLoop
xor edi, edi ; RDI=0: all streams
call fflush wrt ..plt
mov rax,60 ; SYS_EXIT
mov rdi,0 ; Exitcode: RDI=0
syscall ; Call Linux64