Control Flow (1)

Control Flow (1)

Control flow (1) Condition codes Conditional and unconditional jumps Loops Conditional moves Switch statements 1 Conditionals and Control Flow Two key pieces 1. Comparisons and tests: check conditions 2. Transfer control: choose next instruction Familiar C constructs Processor Control-Flow State l if else Condition codes (a.k.a. flags) l while 1-bit registers hold flags set by last ALU operation l do while ZF Zero Flag result == 0 l for SF Sign Flag result < 0 l break l continue CF Carry Flag carry-out/unsigned overflow OF Overflow Flag two's complement overflow %rip Instruction pointer (a.k.a. program counter) register holds address of next instruction to execute 2 1. compare and test: conditions ex cmpq b,a computes a - b, sets flags, discards result Which flags indicate that a < b ? (signed? unsigned?) testq b,a computes a & b, sets flags, discards result Common pattern: testq %rax, %rax What do ZF and SF indicate? 3 Aside: save conditions setg: set if greater long gt(int x, int y) { stores byte: return x > y; 0x01 if ~(SF^OF)&~ZF } 0x00 otherwise cmpq %rsi,%rdi # compare: x – y setg %al # al = x > y movzbq %al,%rax # zero rest of %rax Zero-extend from Byte (8 bits) to Quadword (64 bits) %rax %eax %ah %al 4 2. jump: choose next instruction Jump/branch to different part of code by setting %rip. j__ Condition Description Always jump jmp 1 Unconditional je ZF Equal / Zero jne ~ZF Not Equal / Not Zero js SF Negative jns ~SF Nonnegative Jump iff condition jg ~(SF^OF)&~ZF Greater (Signed) jge ~(SF^OF) Greater or Equal (Signed) jl (SF^OF) Less (Signed) jle (SF^OF)|ZF Less or Equal (Signed) ja ~CF&~ZF Above (unsigned) jb CF Below (unsigned) 6 Jump for control flow Jump immediately follows comparison/test. Together, they make a decision: "if %rcx == %rax , jump to label." cmpq %rax,%rcx je label … … Executed only if … %rax ≠ %rcx label: addq %rdx,%rax Label Name for address of following item. 7 Conditional Branch Example long absdiff(long x,long y) { long result; if (x > y) { result = x-y; } else { absdiff: result = y-x; cmpq %rsi, %rdi } jle .L7 subq %rsi, %rdi return result; movq %rdi, %rax } .L8: retq Labels .L7: Name for address of subq %rdi, %rsi following item. movq %rsi, %rax jmp .L8 How did the compiler create this? 8 Introduced by Fran Allen, et al. Control-Flow Graph Won the 2006 Turing Award for her work on compilers. Code flowchart/directed graph. long absdiff(long x, long y){ Nodes = Basic Blocks: long result; Straight-line code always if (x > y) { executed together in order. result = x-y; } else { result = y-x; long result; } if (x > y) else return result; } then else result = x-y; result = y-x; Edges = Control Flow: Which basic block executes next (under what condition). return result; Choose a linear order of basic blocks. long result; long result; if (x > y) else if (!(x > y)) then else else then result = x-y; result = y-x; result = y-x; result = x-y; return result; return result; Choose a linear order of basic blocks. long result; if (!(x > y)) result = x-y; return result; result = y-x; Why might the compiler choose this basic block order instead of another valid order? Translate basic blocks with jumps + labels long result; if (!(x > y)) cmpq %rsi, %rdi jle Else result = x-y; subq %rsi, %rdi movq %rdi, %rax return result; End: retq result = y-x; Else: subq %rdi, %rsi movq %rsi, %rax jmp End Why might the compiler choose this basic block order instead of another valid order? Execute absdiff ex Registers cmpq %rsi, %rdi %rax jle Else %rdi subq %rsi, %rdi movq %rdi, %rax %rsi End: retq Else: subq %rdi, %rsi movq %rsi, %rax jmp End 13 Note: CSAPP shows translation with goto long absdiff(long x,long y){ long goto_ad(long x,long y){ int result; int result; if (x > y) { if (x <= y) goto Else; result = x-y; result = x-y; } else { End: result = y-x; return result; } Else: return result; result = y-x; } goto End; } 14 Note: CSAPP shows translation with goto long goto_ad(long x, long y){ long result; if (x <= y) goto Else; result = x-y; End: return result; absdiff: Else: cmpq %rsi, %rdi result = y-x; jle Else goto End; } subq %rsi, %rdi movq %rdi, %rax End: retq Close to assembly code. Else: subq %rdi, %rsi movq %rsi, %rax jmp End 15 But never use goto in your source code! http://xkcd.com/292/ 16 compile if-else ex long wacky(long x, long y){ int result; if (x + y > 7) { result = x; } else { result = y + 2; } return result; } Assume x available in %rdi, y available in %rsi. Place result in %rax. Encoding Jumps: PC-relative addressing 0x100 cmpq %rax, %rbx 0x1000 0x102 je 0x70 0x1002 0x104 … 0x1004 … … … 0x174 addq %rax, %rbx 0x1074 l PC-relative offsets support relocatable code. l Absolute branches do not (or it's hard). 18 Compiling Loops C code: Machine code: while ( sum != 0 ) { loopTop: testq %rax, %rax <loop body> je loopDone } <loop body code> jmp loopTop loopDone: 20 do while loop example long result = 1; C Code long fact_do(long x) { long result = 1; result = result*x; do { result = result * x; x = x-1; x = x-1; } while (x > 1); return result; (x > 1) ? Yes } No return result; 21 do while loop translation Register Variable %rdi long result = 1; Assembly %rax fact_do: movq $1,%rax result = result*x; x = x-1; .L11: imulq %rdi,%rax decq %rdi cmpq $1,%rdi (x > 1) ? jg .L11 Yes No retq return result; Why? Why put the loop condition at the end? 22 while loop translation Why? C Code long fact_while(long x){ long result = 1; while (x > 1) { long result = 1; result = result * x; x = x-1; } return result; result = result*x; } x = x-1; long result = 1; (x > 1) ? Yes (x > 1) ? No Yes No return result; result = result*x; x = x-1; This order is used by GCC for x86-64 return result; 23 while loop example int fact_while(int x) { movq $1, %rax int result = 1; jmp .L34 while (x > 1) { .L35: result = result * x; imulq %rdi, %rax x = x - 1; decq %rdi } .L34: return result; cmpq $1, %rdi } jg .L35 retq int result = 1; result = result*x; x = x-1; (x > 1) ? Yes No return result; 25 for loop translation for (Initialize; Test; Update ) { Body } for (result = 1; p != 0; p = p>>1) { if (p & 0x1) { result = result * x; Initialize; } while (Test) { x = x*x; Body ; } Update; } result = 1; Initialize if (p & 0x1) { result = result*x; Body } Update x = x*x; p = p>>1; Test ? Yes No (p != 0) ? Yes No 31 Control flow (2) Condition codes Conditional and unconditional jumps Loops Conditional moves Switch statements 35 (Aside) Conditional Move cmov_ src, dest if (Test) Dest ß Src Why? Branch prediction in pipelined/OoO processors. long absdiff(long x, long y) { long absdiff(long x, long y) { long result; return x>y ? x-y : y-x; if (x>y) { } result = x-y; } else { result = y-x; } return result; } absdiff: movq %rdi, %rax # x subq %rsi, %rax # result = x-y movq %rsi, %rdx subq %rdi, %rdx # else_val = y-x cmpq %rsi, %rdi # x:y cmovle %rdx, %rax # if <=, result = else_val ret 36 (Aside) Bad Cases for Conditional Move Expensive Computations val = Test(x) ? Hard1(x) : Hard2(x); Risky Computations val = p ? *p : 0; Computations with side effects val = x > 0 ? x*=7 : x+=3; 37 switch statements long switch_eg (long x, long y, long z) { long w = 1; switch(x) { case 1: w = y*z; break; case 2: Fall through cases w = y/z; /* Fall Through */ Missing cases case 3: w += z; break; Multiple case labels case 5: case 6: w -= z; break; default: Lots to manage, w = 2; let's use a jump table } return w; } 38 Jump Table Structure C code: Memory switch(x) { case 1: <some code> break; case 2: <some code> case 3: <some code> Code break; Blocks case 5: case 6: <some code> break; default: <some code> } Translation sketch: 6 if (0 <= x && x <= 6) 5 4 target = JTab[x]; 3 goto target; 2 else 1 Jump goto default; 0 Table 39 declaring data, not instructions Jump Table 8-byte memory alignment Jump table .section .rodata switch(x) { .align 8 case 1: // .L3 .L4: w = y*z; .quad .L8 # x = 0 break; .quad .L3 # x = 1 case 2: // .L5 .quad .L5 # x = 2 w = y/z; .quad .L9 # x = 3 /* Fall Through */ .quad .L8 # x = 4 case 3: // .L9 .quad .L7 # x = 5 w += z; .quad .L7 # x = 6 break; case 5: case 6: // .L7 w -= z; “quad” as in four 1978-era 16-bit words break; default: // .L8 w = 2; } 40 switch statement example ex long switch_eg(long x, long y, long z) { long w = 1; switch(x) { . } return w; } Jump table .section .rodata but this is signed... .align 8 .L4: Jump if above .quad .L8 # x = 0 (like jg, but switch_eg: .quad .L3 # x = 1 unsigned) movq %rdx, %rcx .quad .L5 # x = 2 cmpq $6, %rdi .quad .L9 # x = 3 Indirect .quad .L8 # x = 4 ja .L8 .quad .L7 # x = 5 jump jmp *.L4(,%rdi,8) .quad .L7 # x = 6 41 Code Blocks (x == 1) switch(x) { .L3: case 1: // .L3 movq %rsi, %rax # y w = y*z; imulq %rdx, %rax # y*z break; retq . } return w; Compiler "inlined" the return. Register Use(s) %rdi Argument x %rsi Argument y %rdx Argument z %rax Return value 42 Handling Fall-Through long w = 1; switch (x) { .

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    37 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us