ASM (x86-64)

Learn about the assembly language understood by our home computers

Easy

ASM (x86-64)
Control Flow

ASM_(x86-64)::Control_Flow

So far, all our programs have been linear, meaning that they run from the first instruction to the last instruction without any change. This is great for simple programs, but it is very inefficient/impossible when we start to use programming concepts like loops or if/else statements.

Loops

Let's try to use our existing knowledge to create a function like this.

int foo(int a){
    for(int i = 0; i < 5; i++){
        a += 1
    }
    return a;
}

To provide context, our argument a will come from the rdi register, and we will "return" the final value into the rax register. If rdi starts at 0, our assembly snippet should thus end with rax = 5.

A naive attempt would lead us to the following code snippet.

Initializing...

CODE [0x400000]
Registers
rax:
rbx:
rcx:
rdx:
rdi:
rsi:
r8 :
r9 :
r10:
r11:
r12:
r13:
r14:
r15:
rbp:
rsp:
rip:

And this in fact works very well.

However, what if our loop was dynamic?

int foo(int a, int b){
    for(int i = 0; i < b; i++){
        a += 1
    }
    return a;
}
Argument b will be in register rsi

Now, we're in trouble. We do not know how many times we need to create the add rdi, 1 instruction, as it is dependent on the value of rsi.

Let there be jumps

This is where we need to learn more instructions!

The family of instructions we need here are jumps. There are a variety of jumps, but the simplest to understand is jmp.

jmp takes one operand, which is the memory (relative address) / register that you shold jump to. It'd be easiest to understand this through an example. Here is an infinite loop (do not use Play, only Step through).

Initializing...

CODE [0x400000]
Registers
rax:
rbx:
rcx:
rdx:
rdi:
rsi:
r8 :
r9 :
r10:
r11:
r12:
r13:
r14:
r15:
rbp:
rsp:
rip:

You can observe that rdi's value will increment forever*! With jmp, we've managed to create non-linear code execution, allowing for constructs such as loops.

Obviously, we've still not been able to replicate the C code snippet, but we're getting closer!

Comparisons

The next class of instructions we require are comparison operators. There are a whole group of them, but in general they just aid to perform comparisons between two operands.

The cmp instruction takes 2 operands, and compares their value. It will then implicitly set a special register called RFLAGS according to the result of the comparison. Then, future instructions can check the RFLAGS register to determine the result of the comparison that just occured. We will not delve into the details to prevent too much confusion, but you can read more about this special register here (RFLAGS).

Here, we show the instruction in action!

We will be using the je instruction, which is the jump if equal type of jump. As its name suggests, it only jumps if the previous comparison has equal operands, if not it will do a single step as usual.

Initializing...

CODE [0x400000]
Registers
rax:
rbx:
rcx:
rdx:
rdi:
rsi:
r8 :
r9 :
r10:
r11:
r12:
r13:
r14:
r15:
rbp:
rsp:
rip:
Try changing the code above to modify the values of rax or rbx
How will the code run differently?

Bring it all together

Now that we understand these two core concepts of jumps and comparisons, let's try to piece it together to create our function defined above.

See if you can implement it yourself! This can be done using the instructions we've covered thus far (reminder: cmp, je, jmp, mov).

But if you need extra instructions, here's some more useful "jumps" we can provide you with (reference).

InstructionPurpose
jajump if above
jaejump if above or equal
jbjump if below
jbejump if below or equal
jejump if equal
jgjump if greater
jgejump if greater or equal
jljump if lesser
jlejump if lesser or equal
After/below are the unsigned equivalents of greater/lesser (signed).

For reference, we are trying to recreate the following function (rdi=a, rsi=b, rax=return_value):

int foo(int a, int b){
    for(int i = 0; i < b; i++){
        a += 1
    }
    return a;
}

Edit the following omulator box to write and debug your answer:

Initializing...

CODE [0x400000]
Registers
rax:
rbx:
rcx:
rdx:
rdi:
rsi:
r8 :
r9 :
r10:
r11:
r12:
r13:
r14:
r15:
rbp:
rsp:
rip:
Click for answer