CS 105 Tour of the Black Holes of
CS 105 “Tour of the Black Holes of Computing” Machine-Level Programming II: Control Flow Topics n Condition Codes l Setting l Testing n Control Flow l If-then-else l Varieties of Loops l Switch Statements X 86. 2. ppt
Processor State (IA 32, Partial) Information about currently executing program n n %eax %ecx Temporary data ( %eax, … ) %edx Location of runtime stack ( %ebp, %esp ) %esi %ebx %edi Location of current code control point ( %eip, … ) Status of recent tests ( CF, ZF, SF, OF ) CF – 2– General purpose registers %esp Current stack top %ebp Current stack frame %eip Instruction pointer ZF SF OF Condition codes CS 105
Condition Codes Single Bit Registers CF ZF Carry Flag Zero Flag SF OF Sign Flag Overflow Flag Implicitly Set By Arithmetic Operations addl Src, Dest C analog: t = a + b n CF set if carry out from most significant bit l Used to detect unsigned overflow ZF set if t == 0 n SF set if t < 0 n n OF set if two’s complement overflow (a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0) Not Set by leal instruction – 3– CS 105
Setting Condition Codes (cont. ) Explicit Setting by Compare Instruction cmpl Src 2, Src 1 //cmpb, cmpw, cmpl n cmpl b, a like computing a-b without setting destination n CF set if carry out from most significant bit l Used for unsigned comparisons n ZF set if a == b SF set if (a-b) < 0 n OF set if two’s complement overflow n (a>0 && b<0 && (a-b)<0) || (a<0 && b>0 && (a-b)>0) – 4– CS 105
Setting Condition Codes (cont. ) Explicit Setting by Test instruction without a destination testl Src 2, Src 1 n Sets condition codes based on value of Src 1 & Src 2 l Intel thought: Useful to have one of the operands be a mask l Compiler usually sets Src 1 and Src 2 the same n n n – 5– testl b, a like computing a&b without setting destination ZF set when a&b == 0 SF set when a&b < 0 CS 105
Reading Condition Codes Set. X instructions n – 6– Set single byte based on combinations of condition codes CS 105
Reading Condition Codes (Cont. ) Set. X Instructions n n Set single byte based on combinations of condition codes One of 8 addressable byte registers l Embedded within first 4 integer registers l Does not alter remaining 3 bytes l Typically use movzbl to finish job Body int gt (int x, int y) { return x > y; } movl 12(%ebp), %eax cmpl %eax, 8(%ebp) setg %al movzbl %al, %eax – 7– %eax %ah %al %edx %dh %dl %ecx %ch %cl %ebx %bh %bl %esi %edi %esp %ebp # # eax = y Compare x : y al = x > y Move byte & Zero rest Note inverted ordering! CS 105
Jumping j. X instructions – 8– n Jump to different part of code depending on condition codes n Conditional jumps are direct, JMP allows indirect jumps CS 105
Conditional Branch Example _max: pushl %ebp movl %esp, %ebp int max(int x, int y) { if (x > y) return x; else return y; } movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle L 9 movl %edx, %eax Set Up Body L 9: movl %ebp, %esp popl %ebp ret Finish Return value in %eax – 9– CS 105
Conditional Branch Ex. (Cont. ) int goto_max(int x, int y) { int rval = y; int ok = (x <= y); if (ok) goto done; rval = x; done: return rval; } movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle L 9 movl %edx, %eax L 9: # – 10 – n C allows “goto” as means of transferring control l Closer to machine-level programming style n n # edx = # eax = # x : y # if <= # eax = Done: Nearly always very bad HLL coding style Next slides – find common format for loops x y goto L 9 x Skipped when x y CS 105
“Do-While” Loop Example C Code int fact_do (int x) { int result = 1; do { result *= x; x = x-1; } while (x > 1); return result; } n n – 11 – Goto Version int fact_goto(int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; } Use backward branch to continue looping Only take branch when “while” condition holds CS 105
“Do-While” Loop Compilation. 0 Goto Version int fact_goto (int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; } Registers %edx %eax – 12 – x result Assembly Fill in comments: _fact_goto: pushl %ebp movl %esp, %ebp movl $1, %eax movl 8(%ebp), %edx # Setup # # L 11: imull %edx, %eax decl %edx cmpl $1, %edx jg L 11 # # movl %ebp, %esp popl %ebp ret # Finish CS 105
“Do-While” Loop Compilation Goto Version int fact_goto (int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; } Assembly _fact_goto: pushl %ebp movl %esp, %ebp movl $1, %eax movl 8(%ebp), %edx # # Setup eax = 1 edx = x L 11: imull %edx, %eax decl %edx cmpl $1, %edx jg L 11 # # result *= x x-Compare x : 1 if > goto loop Registers %edx x, %eax result imult one op in %eax msb in %edx, lsb in %eax – 13 – movl %ebp, %esp popl %ebp ret # Finish CS 105
General “Do-While” Translation Goto Version C Code do loop: Body if (Test) goto loop Body while (Test); n Body done once Body can be any C statement l Typically compound statement: { } n Statement 1; Statement 2; … Statementn; Test is expression returning integer = 0 interpreted as false – 14 – 0 interpreted as true CS 105
“While” Loop Example #1 C Code int fact_while (int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } int fact_while_goto (int x) { int result = 1; loop: if (!(x > 1)) goto done; result *= x; x = x-1; goto loop; done: return result; } n Is this code equivalent to the do-while version? Must jump out of loop if test fails n Test at top of loop, update at bottom of loop n – 15 – First Goto Version CS 105
Actual “While” Loop Translation C Code Second Goto Version int fact_while(int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } int fact_while_goto 2 (int x) { int result = 1; if (!(x > 1)) goto done; loop: result *= x; x = x-1; if (x > 1) #added goto loop; n Uses same inner loop as do done: -while version return result; } n Guards loop entry with extra test – avoids loop done once – 16 – CS 105
General “While” Translation C Code while (Test) Body Do-While Version Goto Version if (!Test) goto done; do Body while(Test); done: if (!Test) goto done; loop: Body if (Test) goto loop; done: Format: while and do-while – 17 – CS 105
Summary: Loops Do-While loop C Code do Body while (Test); Goto Version loop: Body if (Test) goto loop While-Do loop Do-While Version While version while (Test) Body if (!Test) goto done; do Body while(Test); done: or just one test – 18 – Goto Version if (!Test) goto done; loop: Body if (Test) goto loop; done: goto middle; loop: Body middle: if (Test) goto CS loop; 105
“For” Loop Example: Square-and. Multiply /* Compute x raised to nonnegative power p */ int ipwr_for(int x, unsigned p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0 x 1) //only when 1 bit result *= x; x = x*x; } return result; } Algorithm n n Exploit bit representation: p = p 0 + 2 p 1 + 22 p 2 + … 2 n– 1 pn– 1 Gives: xp = z 0 · z 1 2 · (z 2 2) 2 · … · (…((zn – 12) 2 )…) 2 zi = 1 when pi = 0, 0 bit value zi = x when pi = 1, 1 bit value – 19 – n Complexity O(log p) Example n– 1 times 310 = 32 * 38 = 32 * ((32)2)2 CS 105
ipwr Computation /* Compute x raised to nonnegative power p */ int ipwr_for(int x, unsigned p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0 x 1) result *= x; x = x*x; } return result; } before iteration – 20 – 1 2 3 4 5 result x=3 p=10 1 1 9 9 59049 3 9 81 6561 43046721 10=10102 5= 1012 2= 102 1= 12 0 CS 105
– 21 – CS 105
“For” Loop Example int result; for (result = 1; p != 0; p = p>>1) { if (p & 0 x 1) result *= x; x = x*x; } General Form for (Init; Test; Update) Body Test p != 0 Init result = 1 Update p = p >> 1 Body { if (p & 0 x 1) result *= x; x = x*x; – 22 – } CS 105
“For” “While” “Do-While” For Version for (Init; Test; Update ) Body Goto Version Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done: – 23 – While Version Init; while (Test ) { Body Update ; } Do-While Version Init; if (!Test) goto done; do { Body Update ; } while (Test) done: CS 105
For-Loop: Compilation #1 For Version for (Init; Test; Update ) Body Goto Version Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done: – 24 – for (result = 1; p != 0; p = p>>1) { if (p & 0 x 1) result *= x; x = x*x; } result = 1; if (p == 0) goto done; loop: if (p & 0 x 1) result *= x; x = x*x; p = p >> 1; if (p != 0) goto loop; done: CS 105
“For” “While” (Jump-to-Middle) For Version for (Init; Test; Update ) Body Goto Version While Version Init; while (Test ) { Body Update ; } – 25 – Init; goto middle; loop: Body Update ; middle: if (Test) goto loop; done: CS 105
For-Loop: Compilation #2 For Version for (Init; Test; Update ) Body Goto Version Init; goto middle; loop: Body Update ; middle: if (Test) goto loop; done: – 26 – for (result = 1; p != 0; p = p>>1) { if (p & 0 x 1) result *= x; x = x*x; } result = 1; goto middle; loop: if (p & 0 x 1) result *= x; x = x*x; p = p >> 1; middle: if (p != 0) goto loop; done: CS 105
“For” “While” For Version for (Init; Test; Update ) Body Do-While Version Init; if (!Test) goto done; do { Body Update ; } while (Test) done: – 27 – While Version Init; while (Test ) { Body Update ; } Goto Version Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done: CS 105
typedef enum {ADD, MULT, MINUS, DIV, MOD, BAD} op_type; char unparse_symbol(op_type op) { switch (op) { case ADD : return '+'; case MULT: return '*'; case MINUS: return '-'; case DIV: return '/'; case MOD: return '%'; case BAD: return '? '; } } – 28 – Switch Statements Implementation Options n Series of conditionals l Good if few cases l Slow if many n Jump Table l Lookup branch target l Avoids conditionals l Possible when cases are small integer constants n GCC l Picks one based on case structure n Bug in example code l No default given CS 105
Jump Table Structure Switch Form switch(op) { case val_0: Block 0 case val_1: Block 1 • • • case val_n-1: Block n– 1 } Jump Table jtab: Targ 0 Jump Targets Targ 0: Code Block 0 Targ 1: Code Block 1 Targ 2: Code Block 2 Targ 1 Targ 2 • • • Targn-1 • • • Approx. Translation target = JTab[op]; goto *target; Targn-1: Targ. X is address of code block indirect thru target – Jump 29 – Code Block n– 1 CS 105
Switch Statement Example Branching Possibilities typedef enum {ADD, MULT, MINUS, DIV, MOD, BAD} op_type; char unparse_symbol(op_type op) { switch (op) { • • • } } Setup: – 30 – Enumerated Values ADD MULT MINUS DIV MOD BAD 0 1 2 3 4 5 unparse_symbol: pushl %ebp # Setup movl %esp, %ebp # Setup movl 8(%ebp), %eax # eax = op cmpl $5, %eax # Compare op : 5 ja. L 49 # If > goto done, > range jmp *. L 57(, %eax, 4) # goto Table[op] #. L 57 label of table, %eax table index, 4 word size CS 105
Assembly Setup Explanation Symbolic Labels n Labels of form. LXX translated into addresses by assembler Table Structure n n Each target requires 4 bytes Base address at. L 57 Jumping jmp. L 49 n Jump target is denoted by label. L 49 jmp *. L 57(, %eax, 4) n Start of jump table denoted by label. L 57 n Register %eax holds op n n – 31 – Must scale by factor of 4 to get offset into table Fetch target from effective Address. L 57 + op*4 CS 105
Jump Table Contents Targets & Completion . section. rodata. align 4. L 57: . long. L 51 #Addr, Op = 0. long. L 52 #Op = 1. long. L 53 #Op = 2. long. L 54 #Op = 3. long. L 55 #Op = 4. long. L 56 #Op = 5 . L 51: movl $43, %eax # ’+’ jmp. L 49. L 52: movl $42, %eax # ’*’ jmp. L 49. L 53: movl $45, %eax # ’-’ jmp. L 49. L 54: movl $47, %eax # ’/’ jmp. L 49. L 55: movl $37, %eax # ’%’ jmp. L 49. L 56: movl $63, %eax # ’? ’ # Fall Through to. L 49 Enumerated Values ADD MULT MINUS DIV MOD BAD – 32 – 0 1 2 3 4 5 CS 105
Switch Statement Completion. 0. L 49: movl %ebp, %esp popl %ebp ret # # Done: Finish Puzzle n – 33 – What value returned when op is invalid? ? ? CS 105
Switch Statement Completion. L 49: movl %ebp, %esp popl %ebp ret # # Done: Finish Puzzle n What value returned when op is invalid? Answer n Register %eax set to op at beginning of procedure n This becomes the returned value Advantage of Jump Table n – 34 – Can do k-way branch in O(1) operations CS 105
Object Code Setup n n Label. L 49 becomes address 0 x 804875 c after Linker Label. L 57 becomes address 0 x 8048 bc 0 after Linker 08048718 <unparse_symbol>: 8048718: 55 pushl 8048719: 89 e 5 movl 804871 b: 8 b 45 08 movl 804871 e: 83 f 8 05 cmpl 8048721: 77 39 ja 8048723: ff 24 85 c 0 8 b jmp – 35 – %ebp %esp, %ebp 0 x 8(%ebp), %eax $0 x 5, %eax 804875 c <unparse_symbol+0 x 44> *0 x 8048 bc 0(, %eax, 4) CS 105
Object Code (cont. ) Jump Table n Doesn’t show up in disassembled code Can inspect using GDB gdb code-examples (gdb) x/6 xw 0 x 8048 bc 0 n l Examine 6 hexadecimal format “words” (4 -bytes each) l Use command “help x” to get format documentation 0 x 8048 bc 0 <_fini+32>: 0 x 08048730 # Jump Table Entries – block addrs 0 x 08048737 0 x 08048740 0 x 08048747 0 x 08048750 0 x 08048757 – 36 – CS 105
Extracting Jump Table from Binary Jump Table Stored in Read Only Data Segment (. rodata) n Various fixed values needed by your code Can examine with objdump code-examples –s –-section=. rodata n Show everything in indicated segment. Hard to read n Contents 8048 bc 0 8048 bd 0 8048 be 0 … n – 37 – Jump table entries shown with reversed byte ordering – little endian of section. rodata: 30870408 37870408 40870408 47870408 50870408 57870408 46616374 28256429 203 d 2025 6 c 640 a 00 43686172 203 d 2025 0. . . 7. . . @. . . G. . . P. . . W. . . Fact(%d) = %ld. . Char = % E. g. , 30870408 really means 0 x 08048730, why I like Big. Endian CS 105
Disassembled Targets 8048730: b 8 8048735: eb 8048737: b 8 804873 c: eb 804873 e: 89 8048740: b 8 8048745: eb 8048747: b 8 804874 c: eb 804874 e: 89 8048750: b 8 8048755: eb 8048757: b 8 n n – 38 – 2 b 25 2 a 1 e f 6 2 d 15 2 f 0 e f 6 25 05 3 f 00 00 00 00 00 movl jmp movl jmp movl $0 x 2 b, %eax 804875 c <unparse_symbol+0 x 44> $0 x 2 a, %eax 804875 c <unparse_symbol+0 x 44> %esi, %esi $0 x 2 d, %eax 804875 c <unparse_symbol+0 x 44> $0 x 2 f, %eax 804875 c <unparse_symbol+0 x 44> %esi, %esi $0 x 25, %eax 804875 c <unparse_symbol+0 x 44> $0 x 3 f, %eax movl %esi, %esi does nothing Inserted to align instructions for better cache performance CS 105
Matching Disassembled Targets Entry 0 x 08048730 0 x 08048737 0 x 08048740 0 x 08048747 0 x 08048750 0 x 08048757 – 39 – 8048730: b 8 8048735: eb 8048737: b 8 804873 c: eb 804873 e: 89 8048740: b 8 8048745: eb 8048747: b 8 804874 c: eb 804874 e: 89 8048750: b 8 8048755: eb 8048757: b 8 2 b 25 2 a 1 e f 6 2 d 15 2 f 0 e f 6 25 05 3 f 00 00 00 00 00 movl jmp movl jmp movl CS 105
For Fun: Sparse Switch Example /* Return x/111 if x is multiple && <= 999. -1 otherwise */ int div 111(int x) { switch(x) { case 0: return 0; case 111: return 1; case 222: return 2; case 333: return 3; case 444: return 4; case 555: return 5; case 666: return 6; case 777: return 7; case 888: return 8; case 999: return 9; default: return -1; } } – 40 – n Not practical to use jump table l Would require 1000 entries n n Obvious translation into if-then-else would have max. of 9 tests What would you do? ? ? CS 105
Sparse Switch Code movl 8(%ebp), %eax cmpl $444, %eax je L 8 jg L 16 cmpl $111, %eax je L 5 jg L 17 testl %eax, %eax je L 4 jmp L 14 # get x # x: 444 # x: 111 n Compares x to possible case values n Jumps different places depending on outcomes. . . # x: 0 L 5: movl $1, %eax jmp L 19 L 6: movl $2, %eax jmp L 19 . . . L 7: movl $3, %eax jmp L 19 L 8: – 41 – movl $4, %eax jmp L 19. . . CS 105
Sparse Switch Code Structure < < 111 = 444 = > 4 > 777 < = 1 7 0 -1 = 0 222 2 -1 n – 42 – 555 = n > 5 333 = 3 < = -1 888 = > 8 666 = 6 -1 999 = 9 Organizes cases as binary tree Logarithmic performance CS 105
Summarizing C Control Standard Techniques n n if-then-else do-while All loops converted to do-while form n while n n switch Large switch statements use jump tables n Assembler Control n n jump Conditional jump Compiler n Must generate assembly code to implement more complex control Conditions in CISC machines generally have condition code registers Conditions in RISC n n n Use general registers to store condition information Special comparison instructions E. g. , on Alpha: cmple $16, 1, $1 l Sets register $1 to 1 when Register $16 <= 1 – 43 – CS 105
The End Definitions n Linker n Disassembler RISC, CISC n Problems n n n – 44 – 3. 13 3. 15 3. 18 3. 20 3. 22 3. 23 CS 105
- Slides: 44