x86 Control Flow

Memory & Word Size

B, W, L, Q

  • Big-Endian: MS byte is put at the starting address.
  • Little-Endian: LS byte is put at the starting address.

  • $ indicates the constant.
  • If hex without $, it’s address

mov

Destination

  • register
    • Only when destination is register and it’s movl, the rest of bytes are cleared to zero.
  • memory location
    • Can’t move memory address to memory address

      Zero / Sign Extension

  • Destination should be register
  • movzxy: zero-extend
    • No movzlq!!!
  • movsxy: sign-extend
    • cltq is equivalent to movslq
  • Imm -> Reg
  • Imm -> Mem
  • Reg -> Reg
  • Reg -> Mem
  • Mem -> Reg

Whenever there’s 4 bytes(l) operation, clear 4 bytes out!!!

Arithmetic Instructions

  • Both operands cannot be memory

mul

  • Unsigned: mul[l,q] src
  • Signed: imul[l,q] src
  • Long: %edx:%eax = %eax * src (mull)
  • Quad: %rdx:%rax = %rax * src (mulq)

div

  • Unsigned: div[l,q] src
  • Signed: idiv[l,q] src
  • Divisor: src, Quotient: %eax (%rax), Remainder: %edx (%rdx)
  • Long: %eax = %edx:%eax / src (divl) %edx = %edx % src
  • Quad: %rax = %rdx:%rax / src (divq) %rdx = %rdx:%rax % src

Translation to Assembly

4 steps to translate C to assembly

  1. Setup a pointer in a register
  2. Load data from memory to a register (mov)
  3. Process data (add, sun, and, or, shift, etc.)
  4. Store data back to memory (mov)

Inputs & Output:

  • rdi, rsi, rdx, rcx, r8, r9
  • Additional: pass on stack
  • Output: rax

Condition Codes (Flags)

  • SF: sign flag (copy MSB)
  • ZF: zero flag
  • OF: 2’s complement overflow flag
  • CF: Unsigned overflow
  • When test, OF and CF always set to 0.
  • mov and lea leave the condition codes unaffected.
  • and, or, xor update only SF and ZF and *clear OF and CF to 0**
  • not does not affect the condition codes

Shifts and Condition Codes

All shift instructions

  • Set SF and ZF
  • CF: last bit shifted out
  • OF: undef for shifts of more than 1 bit
    • Left shift by 1-bit
      • OF: 1 if MSB changed
    • Right shift by 1-bit
      • Logical: OF: original MSB of the input value
      • Arithmetic: OF is always set to 0

Conditional Jump Instructions

  • je jumps if ZF
  • jge jumps if ~(SF^OF)
  • js jumps if SF

  • Conditional moves are more pipelining friendly

System Stack

  • Tip of stack is accessed and maintained using %rsp (stack pointer) register
  • %rsp points at top occupied location of the stack
  • pushq %reg is equivalent to subq $8, %rsp movq %rax, (%rsp)
  • popq %reg is equivalent to movq (%rsp), %rdx addq $8, %rsp
  • pushw and popw are also available.
  • If address is saved in register -> can’t use it

Caller & Callee-Saved Convention

  • Callee-saved: preserved
    • Callee must ensure the value is not modified
    • Push values before overwriting them
    • Restore before returning
    • %rbp, %rbx, %r12-r15, %rsp*
  • Caller-saved: overwritten freely
    • Caller must save the value if it wants to preserve it across a function call
    • Push if the register value is needed after the function call
    • Callee can freely overwrite
    • Caller will restore upon return
    • all other registers

Updated: