Assembly x86_64 - Jumps, Calls

Assembly Code

We're going to use vim to write our code


[ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
→ vim 3.asm


section .data
        mytext db "Hello, World!", 10

section .text
        global _start

_start:
        call _printHello

        mov rax, 60
        mov rdi, 0
        syscall

_printHello:
        mov rax, 1
        mov rdi, 1
        mov rsi, mytext
        mov rdx, 14
        syscall
        ret

Now let's examine what our code does:


section .data
        mytext db "Hello, World!", 10

section .text
        global _start

As we saw in the previous tutorial, these are the 2 initial sections, in the first .data section we define our constants (here there is mytext which contains the "Hello, World!" string of text with a newline character (represented as 10 or "\n")). Then we define the label _start to be globally accessible as a function under the .text section.


_start:
        call _printHello

        mov rax, 60
        mov rdi, 0
	syscall

Here is our main function called _start, and in it we use a call, this is used to basically use another label (or function) that contains code. And then after that we make use of the syscall whose id is 60 which is the exit syscall and with the arguement 0. Which makes our binary exit with the code 0 after the function _printHello is executed.


_printHello:
        mov rax, 1
        mov rdi, 1
        mov rsi, mytext
        mov rdx, 14
        syscall
        ret

In here as we explained in the previous tutorial, we use the syscall id (rax) 1, with the first arguement (rdi) set as 1, the second arguement (rdi) contains our 'mytext' constant ("Hello, World !" with a newline character), and lastly the third arguement (rdx) is the limit of the text we want to print out (here its 14 characters).

When you use the call instruction, you basically fetch another function (or label) of your choice, in this function you can return to the original position of where the call was made with the 'ret' instruction like we put at the end of the _printHello function.

Compiling

Here we're going to use nasm and ld to compile our assembly code, and then we just execute it and see that our hello world is printed out:


[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ nasm -f elf64 3.asm -o 3.o

[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ cat 3.o
@0!'Hello, World!

<H.data.text.shstrtab.symtab.strtab.rela.text3.asmmytext_start_printHello%                                                                 
[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ld 3.o -o 3

[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ls -lash | grep 3
 12K -rwxr-xr-x 1 nothing nothing 8.7K Mar  2 20:01 3
4.0K -rw-r--r-- 1 nothing nothing  219 Mar  2 20:00 3.asm
4.0K -rw-r--r-- 1 nothing nothing  896 Mar  2 20:00 3.o

[ 192.168.0.18/24 ] [ /dev/pts/89 ] [~/binexp/asm]
→ ./3
Hello, World!

In the next tutorial we will see how to get user input, you can click here.