x86 controlling program flow control flow
play

x86 CONTROLLING PROGRAM FLOW CONTROL FLOW Computers execute - PowerPoint PPT Presentation

x86 CONTROLLING PROGRAM FLOW CONTROL FLOW Computers execute instructions in sequence... ...Except when we change the flow of control. Two main ways of doing this: Jump instructions (this lecture) Call instructions


  1. x86 CONTROLLING PROGRAM FLOW

  2. CONTROL FLOW Computers execute instructions in sequence... ...Except when we change the flow of control. Two main ways of doing this: ▸ “Jump” instructions (this lecture) ▹ “Call” instructions (future lecture) ▹ 2

  3. JUMP INSTRUCTIONS Types Unconditional jumps ▸ Direct jump: jmp Label ▹ Jump target is specified by a label (e.g., jmp .L1 ) ▹ Indirect jump: jmp *Operand ▹ Jump target is specified by a register or memory location ▹ (e.g., jmp *%rax ) Conditional jumps ▸ Only jump if a certain condition is true ▹ 3

  4. RECALL CONDITIONAL STATEMENTS IN C C expressions within, if, for, and while statements: if (x) {…} else {…} while (x) {…} do {…} while (x) for (i=0; i<max; i++) {…} switch (x) { case 1: … case 2: … } 4

  5. MAPPING TO THE CPU Processor flag register eflags (extended flags) Flags are set or cleared by depending on the result of an instruction Each bit is a flag, or condition code: CF Carry Flag SF Sign Flag ZF Zero Flag OF Overflow Flag 5

  6. IMPLICIT SETTING Automatically Set By Arithmetic and Logical Operations Example: addq Src, Dest CF (for unsigned integers) ▸ set if carry out from most significant bit (unsigned overflow) ▹ (unsigned long t) < (unsigned long a) ▹ ZF (zero flag) ▸ Set if t == 0 ▹ SF (Signed integers) ▸ Set if t < 0 ▹ OF (Signed integers) ▸ Set if signed (two’s complement) overflow ▹ ▹ (a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0) Not set by lea, push, pop, mov instructions 6

  7. EXPLICIT SETTING VIA COMPARE Setting condition codes via compare instruction: Example: cmpq b, a Computes a - b without setting destination ▸ CF set if carry out from most significant bit ▸ Used for unsigned comparisons ▹ ZF set if a == b ▸ SF set if (a-b) < 0 ▸ OF set if two’s complement (signed) overflow ▸ (a>0 && b<0 && (a-b)<0) || (a<0 && b>0 && (a-b)>0) Byte, word, and double word versions: cmpb, cmpw, cmpl ▸ 7

  8. EXPLICIT SETTING VIA TEST Setting condition codes via test instruction: Example: testq b, a Computes a & b without setting destination ▸ Sets condition codes based on result ▹ Useful to have one of the operands be a mask ▹ Often used to test if a register is zero or positive ▸ ▹ testq %rax, %rax ZF set when a & b == 0 ▸ SF set when a & b < 0 ▸ Byte, word and double word versions: testb, testw, testl ▸ 8

  9. CONDITIONAL JUMP INSTRUCTIONS Jump to different part of code based on condition codes: Instruction - jxx Condition Description jmp 1 Unconditional / Always Jump je, jz ZF Equal / Zero jne ~ZF Not Equal / Not Zero js SF Negative jns ~SF Non-Negative jg ~(SF^OF) && ~ZF Greater (Signed) jge ~(SF^OF) Greater or Equal (Signed) jl (SF^OF) Less (Signed, Overflow Flips Result) jle ~(SF^OF) || ZF Less or Equal (Signed) ja ~CF && ~ZF Above (Unsigned) jb CF Below (Unsigned) 9

  10. COMPARE/JUMP EXAMPLE “ When compared to the decimal number 4, what is %rdx ? ” mySampleFunction: movq $5, %rdx cmp $4, %rdx “ If %rdx is LESS THAN 4, jl .lessthan jump here. ” jmp .greaterthanorequal ( “ Otherwise, ignore me ” ) .greaterthanorequal: movq $999, %rax jmp .done “ If %rdx is GREATER THAN OR EQUAL TO 4, jump here. ” .lessthan: ( “ Otherwise, ignore me ” ) movq $111, %rax jmp .done .done: ret 10

  11. CONDITIONAL JUMP EXAMPLE This example assumes a non-optimized compilation: gcc –Og -S –fno-if-conversion control.c 11

  12. GENERAL CONDITIONAL EXPRESSION TRANSLATION (USING BRANCHES) Consider the following ternary expression: val = Test ? Then_Expr : Else_Expr; val = x>y ? x-y : y-x ; In a “goto” form: if (!Test) goto Else val = Then_Expr; goto done; Create separate code regions for “then” & “else” expressions Else: val = Else_Expr; Execute the appropriate one Done: ... 12

  13. PRACTICE PROBLEM 3.18 /* x in %rdi, y in %rsi, z in %rdx */ long test(long x, long y, long z) test: { leaq (%rdi,%rsi), %rax x + y + z addq %rdx, %rax long val = ____________ ; cmpq $-3, %rdi x < -3 jge .L2 if ( ____________ ) cmpq %rdx,%rsi { jge .L3 y < z movq %rdi, %rax if ( ____________ ) imulq %rsi, %rax x * y ret val = ____________ ; .L3: movq %rsi, %rax else imulq %rdx, %rax y * z ret val = ____________ ; .L2: cmpq $2, %rdi } x > 2 jle .L4 else if ( ____________ ) movq %rdi, %rax x * z imulq %rdx, %rax val = ____________ ; .L4: ret return val; 13 }

  14. CPU PIPELINING Fetch Decode Execute Write-Back 14

  15. AVOIDING CONDITIONAL BRANCHES Modern CPUs have deep pipelines Instructions fetched far in advance of execution to mask latency going to ▸ memory Problem: What if you hit a conditional branch? ▸ Must stall or predict which branch to take! ▹ Branch prediction in CPUs well-studied, fairly effective ▹ But, best to avoid conditional branching altogether ▹ 15

  16. CONDITIONAL MOVES cmovXX Src, Dest - “Move value from src to dest if condition XX holds” Conditional execution handled within data execution unit ▸ Avoids stalling control unit with a conditional branch ▸ Added with P6 microarchitecture (PentiumPro onward, 1995) ▸ Example: # %rdi = x, %rsi = y, return value in %rax # returns max(x,y) movq %rdi, %rdx # Get x movq %rsi, %rax # rval=y (assume y) cmpq %rdx, %rax # x:y cmovl %rdx, %rax # If y < x, rval=x Performance: 14 cycles on all data ▸ Single control flow path ▸ But … overhead. Both branches are evaluated! ▸ 16

  17. GENERAL CONDITIONAL EXPRESSION TRANSLATION (USING CMOVE) Conditional Move template instruction supports: if (Test), Dest ← Src ▸ GCC attempts to restructure execution to avoid disruptive val = Test ? Then_Expr : Else_Expr; conditional branch Both values computed result = Then_Expr; ▸ Overwrite “then” value with ▸ eval = Else_Expr; “else” value if condition doesn’t hold if (!test) result = eval; return result; 17

  18. CONDITIONAL MOVE EXAMPLE 18

  19. PRACTICE PROBLEM 3.21 /* x in %rdi, y in %rsi */ long test(long x, long y) { test: 8 * x long val = ____________ ; leaq 0(,%rdi,8), %rax testq %rsi, %rsi y > 0 if ( ____________ ) jle .L2 { movq %rsi, %rax x < y if ( ____________ ) subq %rdi, %rax movq %rdi, %rdx y - x val = ____________ ; andq %rsi, %rdx cmpq %rsi, %rdi else cmovge %rdx, %rax x & y ret val = ____________ ; } .L2: y <= -2 else if ( ____________ ) addq %rsi, %rdi x + y cmpq $-2, %rsi val = ____________ ; cmovle %rdi, %rax return val; ret 19 }

  20. WHEN NOT TO USE CONDITIONAL MOVES Expensive Computations: val = Test(x) ? Hard_Function1(x) : Hard_Function2(x); Both Hard_Function1(x) and Hard_Function2(x) are computed ▸ Use branching when “then” and “else” expressions are more expensive than ▸ branch misprediction Computations with Side Effects: val = x > 0 ? x *= 7 : x += 3; Executing both values causes incorrect behavior ▸ Conditional Checks that Protect Against Fault e.g. Null pointer check 20 ▸

  21. LOOPS Implemented in assembly via tests and jumps Compilers try to implement most loops as do-while ▸ do { // Things to do } while (test-expr); 21

  22. ARE THESE EQUIVALENT? A Do-While Loop A While-Do Loop long factorial_do( long x) long factorial_while( long x) { { long result = 1; long result = 1; do while (x > 1) { { result *= x; result *= x; x = x-1; x = x-1; } while (x > 1); } return result; return result; } } 22

  23. ARE THESE EQUIVALENT? A Do-While Loop A While-Do Loop long factorial_do( long x) long factorial_while( long x) { { long result = 1; long result = 1; do while (x > 1) { { result *= x; result *= x; x = x-1; x = x-1; } while (x > 1); } return result; return result; } } factorial_while: factorial_do: movq $1, %rax movq $1, %rax jmp .L2 .L3: .L2: imulq %rdi, %rax imulq %rdi, %rax subq $1, %rdi subq $1, %rdi .L2: cmpq $1, %rdi cmpq $1, %rdi jg .L2 jg .L3 ret 23 ret

  24. FOR-LOOP EXAMPLE long factorial_for( long x) { long result; Recall, for-loops are in the following format: for (result=1; x > 1; x=x-1) { for ( init ; test ; update ) result *= x; { //loop body } } return result; } Init Test Update result = 1; x > 1; x = x - 1; Loop Body: result *= x; Is this code equivalent to the do-while version? Or the while-do version? 24

  25. PRACTICE PROBLEM 3.26 fun_a: long fun_a(long x, long y) { movq $0, %rax jmp .L5 long val = 0; .L6: xorq %rdi, %rax x while (_________) shrq $1, %rdi { .L5: val = val ^ x; ____________________; testq %rdi, %rdi jne .L6 x = x >> 1 ____________________; andq $1, %rax ret } val & 0x1 return _______________; } 25

  26. long switch_eg( long x) C SWITCH STATEMENTS { long result = x; switch (x) { case 100: result *= 13; Test whether an expression matches break ; one of a number of constant integer values and branches accordingly case 102: result += 10; /* Fall through */ Without a “break” the code falls through to the next case case 103: result += 11; break ; If x matches no case, then “default” is executed case 104: case 106: result *= result; break ; default : result = 0; } return result; } 26

Recommend


More recommend