Basic Instructions
Data Movement
We will frequently use data movement instructions for moving data between addresses, moving data between registers and memory addresses, and loading immediate data into registers or memory addresses.
Moving Data
Let's say rax
and rbx
, such that rax = 0
and rbx =1
And we can run ->
we can consider mov
as a copy
function
We have to remember here that the size of the loaded data depends on the size of the destination register
. For example, in the above mov rax, 1
instruction, since we used the 64-bit register rax
, it will be moving a 64-bit representation of the number 1
(i.e. 0x00000001
), which is not very efficient.
This is why it is more efficient to use a register size that matches our data size
. For example, we will get the same result as the above example if we use mov al, 1
, since we are moving 1-byte (0x01
) into a 1-byte register (al
), which is much more efficient.
Now let's assemble it and view its shellcode with objdump
We can see that the shellcode of the first instruction is more than double the size of the last instruction.
We are going to modify our code to use sub-registers to make it more efficient:
The xchg
instruction will swap the data between the two registers.
Address Pointers
In many cases, we would see that the register or address we are using does not immediately contain the final value but contains another address that points to the final value. This is always the case with pointer registers, like rsp
, rbp
, and rip
,
For example, let's assemble and run gdb
on our assembled fib
binary, and check the rsp
and rip
registers:
We see that both registers contain pointer addresses to other locations.
Moving Pointer Values
Arithmetic Instructions
Unary Instructions
The following are the main Unary Arithmetic Instructions (we will assume that rax
starts as 1
for each instruction):
Last updated