One other important instruction for control flow in assembler is call
. call
has one distinguishing feature over jmp
, there
is the option of using the ret
instruction. ret
will return the control back to just after the point from where call
was invoked.
We want to write a program to print two different lines of text:
section .data
greetings db "Greetings earthling.", 10
peace db "We come in peace!", 10
To print a line of text normally takes 4 lines of text:
mov rax, 1
mov rdi, 1
mov rsi, greetings
mov rdx, 21
syscall
Rather than repeating these over and over, we can abstract the repeated lines into a separate section:
_print:
mov rax, 1
mov rdi, 1
syscall
ret
Now, we can just set the registers that will be different for each different line we want to print (the text to print and it’s
length) and then call _print
:
mov rsi, greetings
mov rdx, 21
call _print
Full code here:
section .data
greetings db "Greetings earthling.", 10
peace db "We come in peace!", 10
section .text
global _start
_print:
mov rax, 1
mov rdi, 1
syscall
ret ; Move back to where we were before this was called
_exit:
mov rax, 60
mov rdi, 0
syscall
_start:
mov rsi, greetings
mov rdx, 21
call _print ; print the greetings text
mov rsi, peace
mov rdx, 18
call _print ; print we come in peace!
call _exit
How it works
(Roughly speaking, there are a lot of details here that I’m not totally down with…)
The processor keeps track of the next instruction to execute using a special register called eip
. When call
is called, it takes
the value of this register and pushes it onto the stack. The stack is just an area of memory. There is another register - rsp
that
points to the top of the stack. Pushing a value onto the stack means increasing the value of eip
by 8 bytes and then setting the
value at the address pointed to by rsp
to eip
.
When we call ret
it takes the value pointed to by rsp
, sets eip
to that value and then reduces the value of rsp
by 8 bytes.
Since the stack is just an area of memory, it is possible to use it all up if you make too many nested call
calls. This will crash
the program.