Assembly
Assembly¶
Code and compiled assembly back to back
Tutorials:
ASCII table
x86_64 NASM Assembly Quick Reference
x86 Architecture Overview
ARM Assembly to HEX
Intel Introduction to x64 Assembly
x86 and amd64 instruction reference
ARM Assembly Basics
Basics¶
Stack operations:
- push value: pushes a value into the stack (decrements ESP by 4, the size of one stack ‘unit’).
- pop register: pops a value to a register (increments ESP by 4).
Data transfer:
- mov destination, source: moves copies a value from/to a register.
- mov destination, [expression]: copies a value from a memory address resolved from a ‘register expression’ (single register or arithmetic expression involving one or more registers) into a register.
Flow control:
- jmp destination: jumps into a code location (sets EIP (instruction pointer)).
- jz/je destination: jumps into a code location if ZF (the zero flag) is set.
- jnz/jne destination: jumps into a code location if ZF is not set.
Operations:
- cmp operand1, operand2: compares the 2 operands and sets ZF if they’re equal.
- add operand1, operand2: operand1 += operand2;
- sub operand1, operand2: operand1 -= operand2;
Function transitions:
- call function: calls a function (pushes current EIP, then jumps to the function).
- retn: returns to caller function (pops back the previous EIP).
Functions¶
Function prologue:
A function prologue is some initial code embedded in the beginning of most functions, it serves to set up a new stack frame for said function.
55 push ebp ; preserve caller function's base pointer in stack
8B EC mov ebp, esp ; caller function's stack pointer becomes base pointer (new stack frame)
83 EC XX sub esp, X ; adjust the stack pointer by X bytes to reserve space for local variables
Function epilogue:*
The epilogue is simply the opposite of the prologue - it undoes its steps to restore the stack frame of the caller function, before it returns to it:
8B E5 mov esp, ebp ; restore caller function's stack pointer (current base pointer)
5D pop ebp ; restore base pointer from the stack
C3 retn ; return to caller function
Now at this point, you might be wondering - how do functions talk to each other? How exactly do you send/access arguments when calling a function, and how do you receive the return value? That’s precisely why we have calling conventions.
Calling conventions¶
__cdecl:
;func(1, 2, 3);
6A 03 push 3
6A 02 push 2
6A 01 push 1
E8 XX XX XX XX call func
Putting it together¶
int __cdecl func(int, int, int):
prologue:
55 push ebp ; save base pointer
8B EC mov ebp, esp ; new stack frame
body:
8B 45 08 mov eax, [ebp+8] ; load first argument to EAX (return value)
03 45 0C add eax, [ebp+0Ch] ; add 2nd argument
03 45 10 add eax, [ebp+10h] ; add 3rd argument
epilogue:
5D pop ebp ; restore base pointer
C3 retn ; return to caller