Summary

This lecture focuses on control flow in assembly language. It builds upon previous knowledge of data movement, arithmetic, and logical operations to explain how assembly handles conditional execution (if/else) and loops (while, for). Key to this is the concept of “condition codes,” which are special registers that store the results of operations and are used by conditional jump instructions. The lecture also covers specific assembly instructions related to comparisons, setting bytes based on conditions, conditional moves, and jumps.

1. Recap: Arithmetic and Logic

  • Some registers have special roles:
    • %rax: return value
    • %rdi, %rsi, %rdx: function parameters 1-3
    • %rip: next instruction address
    • %rsp: stack top address
  • mov instruction variants (movb, movw, movl, movq) move data of different sizes. movl to a register also zeroes out the upper 4 bytes.
  • lea instruction copies the address of the source, not the data at the address.
  • nop (no-op) instruction does nothing; used for alignment.
  • mov %ebx, %ebx zeroes out the top 32 bits of %rbx.
  • xor %ebx, %ebx also sets %ebx to zero (and may be more efficient).

2. Control Flow

  • C uses if, else, while, for for control flow.
  • Assembly uses condition codes and conditional jumps to achieve this.

3. Condition Codes

  • CPU has single-bit condition code registers.
  • Common condition codes:
    • CF (Carry Flag): Carry-out from most significant bit (unsigned overflow).
    • ZF (Zero Flag): Result is zero.
    • SF (Sign Flag): Result is negative.
    • OF (Overflow Flag): Two’s-complement overflow.
  • Arithmetic/logic instructions update condition codes. lea does not. Logical operations set CF and OF to 0. Shift operations set CF to the last bit shifted out and OF to 0. inc and dec affect OF and ZF but not CF.
  • cmp and test instructions only set condition codes (don’t store results). cmp is like subtraction, test is like AND.
    • CMP S1, S2: Calculates S2 - S1 and sets flags.
    • TEST S1, S2: Calculates S2 & S1 and sets flags.

4. Assembly Instructions for Control Flow

  • Setting Bytes Conditionally: set instructions set a byte to 0 or 1 based on condition codes.
    • sete D / setz D: Set if equal / zero (ZF = 1)
    • setne D / setnz D: Set if not equal / not zero (ZF = 0)
    • sets D: Set if negative (SF = 1)
    • setns D: Set if non-negative (SF = 0)
    • setg D / setnle D: Set if greater (signed >) (SF = 0 and SF = OF)
    • (and others for >=, <, <=, unsigned >, >=, <, <=)
  • Conditionally Moving Data: cmov instructions conditionally move data.
    • cmove S, R / cmovz S, R: Move if equal / zero (ZF = 1)
    • cmovne S, R / cmovnz S, R: Move if not equal / not zero (ZF = 0)
    • cmovs S, R: Move if negative (SF = 1)
    • (and others corresponding to set conditions)
  • Jump Instructions: jmp jumps to another instruction.
    • jmp Label: Direct jump (target is in the instruction)
      • jmp 404f8 <loop+0xb>
    • jmp *Operand: Indirect jump (target address is in a register/memory)
      • jmp *%rax
    • Conditional jumps (je, jne, js, jns, jg, etc.) jump only if a condition is true.
      • je Label / jz Label: Jump if equal / zero (ZF = 1)
      • jne Label / jnz Label: Jump if not equal / not zero (ZF = 0)
      • (and others corresponding to set conditions)

5. Implementing Control Flow

  • If/Else:
    • Assembly: Calculate condition, jump past if body if false, jump past else after if body.
    • Example C:
      if (num > 3) {
        x = 10;
      } else {
        x = 7;
      }
      num++;
      
    • Assembly structure:
      ; Test (num > 3)
      ; Jump past if-body if test fails
      ; If-body (x = 10)
      ; Jump past else-body
      ; Else-body (x = 7)
      ; Past else body
      ; num++;
      
  • While Loop:
    • Assembly: Jump to the test, execute the body, test again, jump back to the body if the test succeeds.
    • Example C:
      void loop() {
        int i = 0;
        while (i < 100) {
          i++;
        }
      }
      
    • Assembly:
      0x0000000000400570 <+0>:    mov    $0x0,%eax       ; i = 0
      0x0000000000400575 <+5>:    jmp    0x40057a <loop+10> ; Jump to test
      0x0000000000400577 <+7>:    add    $0x1,%eax       ; i++
      0x000000000040057a <+10>:   cmp    $0x63,%eax       ; i < 99?
      0x000000000040057d <+13>:   jle    0x400577 <loop+7> ; Jump if i <= 99
      0x000000000040057f <+15>:   repz retq
      
  • For Loop:
    • Assembly: Similar to while, but initialization and update are also included. Compiler optimizations can change the exact structure.
    • C Equivalent While Loop
      for (init; test; update) {
        body
      }
      
      init;
      while (test) {
        body
        update
      }
      
    • For Loop Assembly
      Init
      Jump to test
      Body
      Update
      Test
      Jump to body if success
      
    • GCC For Loop Output
      Initialization
      Test
      Jump past loop if fails
      Body
      Update
      Jump to test
      

6. Optimizations

  • Conditional moves can avoid jumps, which can be slow due to branch prediction.