Registers and Memory

Registers

Small but extremely fast units of storage for the CPU. Referenced by name.

  • General Purpose Registers for computations etc.
  • Special Purpose Registers that store the instruction pointer (program counter) etc.

Memory (RAM)

Large(r) chunk of data. Referenced by address.

  • Contains code, heap, and stack.

Data Movement :

  • mov dst, src - Move data from src to dst
  • push src - Push src onto the stack
  • pop dst - Pop value from the stack and store it in the dst

Warning

There exists two flavours for the x86-64 syntax. We use the Intel syntax. The AT&T syntax swaps some of the arguments (and registers have a % before the name).

gdb defaults to the AT&T syntax, you can switch with: set disassembly-flavor intel

Common Instructions

Arithmetic :

  • add dst, src - dst += src
  • sub dst, src - dst -= src
  • imul dst, src - dst *= src (signed multiply) After an arithmetic operation, flags are set :
  • ZF : zero flag, set to 1 if the result is 0.
  • SF : sign flag, set to 1 if the result is negative.
  • OF : overflow flag, set to 1 if the operation overflowed.

Control Flow

  • jump label - Jump to label
  • call fn - Pushes instruction pointer (IP) onto stack, jump to function.
  • ret - Pops IP from stack (and continues there).
  • cmp a, b - Calculates b-a and sets flags.
  • tst a, b - Calculates a&b and sets flags.
  • je label - Jumps to label if zero flag is set.
  • jne label - Jumps to label if zero flag is not set.
  • nap - No-op instruction – doesn’t do anything.

Bitwise Operations :

  • and dst, src - dst &= src
  • or dst, src - dst |= src
  • xor dst, src - dst ^= src

Memory Addressing

Square brackets indicate that the operand is a memory address, rather than a direct value or register.

  • Direct Memory Access : [address] Example: mov eax, [0x1234] ; Move the value at address 0x1234 into eax.
  • Register-based Memory Access : [register] Example: mov eax, [ebp] ; Move the value at the address in ebp into eax.
    • Optionally with offset : [register + offset] Example : mov eax, [rbp-4

Common Patterns

Data is moved to a register, operation is called, result stored in memory location or register.

mov eax, [esp+1] ; eax = [esp+1]
add [esp+18], eax ; [esp+18] += eax

Data is compared and then a jump is made based on the result.

cmp [esp+1], 3 ; if ([esp+1] == 3)
je label1      ; jump to label1
			   ; else continue below

The Stack

Note

The top of the stack is the lowest address that belongs to the stack.

  • The RSP (stack pointer) always points to the top of the stack.
  • The push rax instructions is equivalent to
sub rsp, 8
mov [rsp], rax
  • The pop rax instruction is equivalent to :
mov rax, [rsp]
add rsp, 8

Calling Conventions (Linux)

There exists a convention on how function arguments should be passed.

  • The first 6 integer and pointer arguments should be passed by register (rdi, rsi, rdx, rcx, r8, r9).
  • Any further argument is passed on the stack.
  • Result is normally passed in rax.
int main() {
	long a = myfunc(1, 2, 3, 4, 5, 6, 7, 8);
}
long myfunc(long a, long b, long c, long d, long e, long f, long g, long h)
{
	long xx = a * b * c * d * e * f * g * h;
	long yy = a + b + c + d + e + f + g + h;
	long zz = utilfunc(xx, yy, xx % yy);
	return zz + 20;
}