Call

Using call in assembler

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.