CS 251 Fall 2019 CS 240 Principles of Programming Languages - - PowerPoint PPT Presentation

cs 251 fall 2019 cs 240 principles of programming
SMART_READER_LITE
LIVE PREVIEW

CS 251 Fall 2019 CS 240 Principles of Programming Languages - - PowerPoint PPT Presentation

CS 251 Fall 2019 CS 240 Principles of Programming Languages Foundations of Computer Systems Ben Wood x86 Control Flow ( Part A , Part B) Condition codes, comparisons, and tests [Un]Conditional jumps and conditional moves Translating if-else


slide-1
SLIDE 1

CS 251 Fall 2019 Principles of Programming Languages

Ben Wood

λ

CS 240

Foundations of Computer Systems

https://cs.wellesley.edu/~cs240/

x86 Control Flow

(Part A, Part B) Condition codes, comparisons, and tests [Un]Conditional jumps and conditional moves Translating if-else, loops, and switch statements

x86 Control Flow 1

slide-2
SLIDE 2

Conditionals and Control Flow

Two key pieces

1. Comparisons and tests: check conditions 2. Transfer control: choose next instruction

Familiar C constructs

l

if else

l

while

l

do while

l

for

l

break

l

continue

x86 Control Flow 2

Instruction pointer

(a.k.a. program counter) register holds address of next instruction to execute

Condition codes (a.k.a. flags)

1-bit registers hold flags set by last ALU operation Zero Flag result == 0 Sign Flag result < 0 Carry Flag carry-out/unsigned overflow Overflow Flag two's complement overflow %rip CF ZF SF OF

Processor Control-Flow State

slide-3
SLIDE 3
  • 1. Compare and test: conditions

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?

x86 Control Flow 3

slide-4
SLIDE 4

(Aside) Saving conditions as Boolean values

x86 Control Flow 4

long gt(int x, int y) { return x > y; }

gt: cmpq %rsi,%rdi # compare: x – y setg %al # al = x > y movzbq %al,%rax # zero rest of %rax retq

Zero-extend from Byte (8 bits) to Quadword (64 bits)

setg: set if greater

stores byte: 0x01 if ~(SF^OF)&~ZF 0x00 otherwise

%rax %eax %al %ah set__ comes in same flavors as j__ (next slide)

slide-5
SLIDE 5
  • 2. Jump: choose next instruction

Jump/branch to different part of code by setting %rip.

x86 Control Flow 5

j__ Condition Description

jmp 1 Unconditional je ZF Equal / Zero jne ~ZF Not Equal / Not Zero js SF Negative jns ~SF Nonnegative 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)

Unconditional jump Conditional jumps

slide-6
SLIDE 6

Jump for control flow

x86 Control Flow 6

cmpq %rax,%rcx je label … … … addq %rdx,%rax label: Label Name for address of following item.

Jump immediately follows comparison/test. Together, they make a decision: "if %rcx == %rax then jump to label." Executed only if %rax ≠ %rcx

slide-7
SLIDE 7

Conditional branch example

x86 Control Flow 7

long absdiff(long x,long y) { long result; if (x > y) { result = x-y; } else { result = y-x; } return result; }

Labels

Name for address of following item.

How did the compiler create this?

absdiff: cmpq %rsi, %rdi jle .L7 subq %rsi, %rdi movq %rdi, %rax .L8: retq .L7: subq %rdi, %rsi movq %rsi, %rax jmp .L8

slide-8
SLIDE 8

Control-Flow Graph

x86 Control Flow 8

long absdiff(long x, long y){ long result; if (x > y) { result = x-y; } else { result = y-x; } return result; } long result; if (x > y) else result = x-y; result = y-x; return result;

Introduced by Fran Allen, et al. Won the 2006 Turing Award for her work on compilers.

Nodes = Basic Blocks:

Straight-line code always executed together in order.

Edges = Control Flow:

Which basic block executes next (under what condition).

Code flowchart/directed graph. then else

slide-9
SLIDE 9

Choose a linear order of basic blocks.

x86 Control Flow 9

long result; if (x > y) else result = x-y; result = y-x; return result; long result; if (!(x > y)) result = y-x; result = x-y; return result;

else else then then

slide-10
SLIDE 10

Choose a linear order of basic blocks.

x86 Control Flow 10

long result; if (!(x > y)) result = x-y; result = y-x; return result;

Why might the compiler choose this basic block order instead of another valid order?

slide-11
SLIDE 11

Translate basic blocks with jumps + labels

x86 Control Flow 11

cmpq %rsi, %rdi jle Else subq %rsi, %rdi movq %rdi, %rax subq %rdi, %rsi movq %rsi, %rax jmp End retq

Else: End: long result; if (!(x > y)) result = x-y; result = y-x; return result;

Why might the compiler choose this basic block order instead of another valid order?

slide-12
SLIDE 12

Execute absdiff

x86 Control Flow 12

%rax %rdi %rsi 5 3

ex

Registers

cmpq %rsi, %rdi jle Else subq %rsi, %rdi movq %rdi, %rax retq

Else: End:

subq %rdi, %rsi movq %rsi, %rax jmp End

slide-13
SLIDE 13

Execute absdiff

x86 Control Flow 15

%rax %rdi %rsi 4 7

ex

Registers

cmpq %rsi, %rdi jle Else subq %rsi, %rdi movq %rdi, %rax retq

Else: End:

subq %rdi, %rsi movq %rsi, %rax jmp End

slide-14
SLIDE 14

Note: CSAPP shows translation with goto

x86 Control Flow 18

long goto_ad(long x,long y){ int result; if (x <= y) goto Else; result = x-y; End: return result; Else: result = y-x; goto End; } long absdiff(long x,long y){ int result; if (x > y) { result = x-y; } else { result = y-x; } return result; }

slide-15
SLIDE 15

Note: CSAPP shows translation with goto

x86 Control Flow 19

long goto_ad(long x, long y){ long result; if (x <= y) goto Else; result = x-y; End: return result; Else: result = y-x; goto End; }

Close to assembly code.

cmpq %rsi, %rdi jle Else subq %rsi, %rdi movq %rdi, %rax retq

Else: End:

absdiff: subq %rdi, %rsi movq %rsi, %rax jmp End

slide-16
SLIDE 16

x86 Control Flow 20

http://xkcd.com/292/

But never use goto in your source code!

slide-17
SLIDE 17

Compile if-else

x86 Control Flow 21

ex

long wacky(long x, long y){ long result; if (x + y > 7) { result = x; } else { result = y + 2; } return result; } Assume x is available in %rdi, y is available in %rsi. Place result in %rax for return. wacky:

slide-18
SLIDE 18

Compile if-else (solution #1)

x86 Control Flow 22

ex

long wacky(long x, long y){ long result; if (x + y > 7) { result = x; } else { result = y + 2; } return result; } Assume x is available in %rdi, y is available in %rsi. Place result in %rax for return. wacky: movq %rdi, %rdx addq %rsi, %rdx cmpq $7, %rdx jle Else movq %rdi, %rax End: retq Else: addq $2, %rsi movq %rsi, %rax jmp End

slide-19
SLIDE 19

Compile if-else (solution #2)

x86 Control Flow 23

ex

long wacky(long x, long y){ long result; if (x + y > 7) { result = x; } else { result = y + 2; } return result; } Assume x is available in %rdi, y is available in %rsi. Place result in %rax for return. wacky: leaq (%rdi, %rsi), %rdx cmpq $7, %rdx jle Else movq %rdi, %rax End: retq Else: leaq 2(%rsi), %rax jmp End

slide-20
SLIDE 20

Encoding jumps: PC-relative addressing

PC-relative offsets support relocatable code. Absolute branches do not (or it's hard).

x86 Control Flow 24

0x100 cmpq %rax, %rbx 0x1000 0x102 je 0x70 0x1002 0x104 … 0x1004 … … … 0x174 addq %rax, %rbx 0x1074

slide-21
SLIDE 21

CS 251 Fall 2019 Principles of Programming Languages

Ben Wood

λ

CS 240

Foundations of Computer Systems

https://cs.wellesley.edu/~cs240/

x86 Control Flow

(Part A, Part B) Condition codes, comparisons, and tests [Un]Conditional jumps and conditional moves Translating if-else, loops, and switch statements

x86 Control Flow 25

slide-22
SLIDE 22

long fact_do(long x) { long result = 1; do { result = result * x; x = x - 1; } while (x > 1); return result; }

do while loop

x86 Control Flow 26

long result = 1; result = result*x; x = x - 1; (x > 1) ? return result;

Yes No

slide-23
SLIDE 23

do while loop

x86 Control Flow 27

Register Variable

%rdi %rax

fact_do: movq $1,%rax .L11: imulq %rdi,%rax decq %rdi cmpq $1,%rdi jg .L11 retq

Why put the loop condition at the end?

long result = 1; result = result*x; x = x - 1; (x > 1) ? return result;

Yes No

slide-24
SLIDE 24

long fact_while(long x){ long result = 1; while (x > 1) { result = result * x; x = x - 1; } return result; }

while loop

x86 Control Flow 28

long result = 1; result = result*x; x = x - 1; (x > 1) ? return result; long result = 1; result = result*x; x = x - 1; (x > 1) ? return result;

This order is used by GCC for x86-64. Why? Yes No Yes No

slide-25
SLIDE 25

long fact_while(long x){ long result = 1; while (x > 1) { result = result * x; x = x - 1; } return result; }

fact_while: movq $1, %rax jmp .L34 .L35: imulq %rdi, %rax decq %rdi .L34: cmpq $1, %rdi jg .L35 retq

while loop

x86 Control Flow 29

int result = 1; result = result * x; x = x - 1; (x > 1) ? return result;

Yes No

slide-26
SLIDE 26

for (result = 1; p != 0; p = p>>1) { if (p & 0x1) { result = result * x; } x = x * x; }

for loop translation

x86 Control Flow 30

for (Initialize; Test; Update ) { Body } Initialize; while (Test) { Body ; Update; }

Initialize Body Update Test ?

Yes No

result = 1; if (p & 0x1) { result = result*x; } x = x * x; p = p >> 1; (p != 0) ?

Yes No

slide-27
SLIDE 27

for loop: square-and-multiply

Algorithm

Exploit bit representation: p = p0 + 2p1 + 22p2 + … 2n–1pn–1 Gives: xp = z0 · z1 2 · (z2 2) 2 · … · (…((zn –12) 2 )…) 2

zi = 1 when pi = 0 zi = x when pi = 1

Complexity O(log p) = O(sizeof(p))

x86 Control Flow 31

/* Compute x raised to nonnegative power p */ int power(int x, unsigned int p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) { result = result * x; } x = x*x; } return result; } n–1 times Example 311 = 31 * 32 * 38 = 31 * 32 * ((32)2)2

xm * xn = xm+n ... 0 1 0 1 1 = 11 12^31 * ... * 116 * x8 * 14 * x2 * x1 = x11 1 = x0 x = x1

  • ptional
slide-28
SLIDE 28

for loop: power iterations

x86 Control Flow 32

/* Compute x raised to nonnegative power p */ int power(int x, unsigned int p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) { result = result * x; } x = x*x; } return result; }

iterations result x p 1 3 11 = 10112 1 3 9 5 = 1012 2 27 81 2 = 102 3 27 6561 1 = 12 4 177147 43046721 02

  • ptional
slide-29
SLIDE 29

(Aside) Conditional Move

x86 Control Flow 33

cmov_ src, dest if (Test) Dest ß Src

absdiff: movq %rdi, %rax subq %rsi, %rax movq %rsi, %rdx subq %rdi, %rdx cmpq %rsi, %rdi cmovle %rdx, %rax ret

long absdiff(long x, long y) {

return x>y ? x-y : y-x;

} long absdiff(long x,long y) { long result; if (x > y) { result = x - y; } else { result = y - x; } return result; } Why? Branch prediction in pipelined/OoO processors.

slide-30
SLIDE 30

Expensive Computations

(Aside) Bad uses of conditional move

x86 Control Flow 34

val = Test(x) ? Hard1(x) : Hard2(x);

Risky Computations

val = p ? *p : 0;

Computations with side effects

val = x > 0 ? x*=7 : x+=3;

slide-31
SLIDE 31

long switch_eg (long x, long y, long z) { long w = 1; switch(x) { case 1: w = y * z; break; case 2: w = y - z; case 3: w += z; break; case 5: case 6: w -= z; break; default: w = 2; } return w; }

switch statement

x86 Control Flow 35

Fall through cases Multiple case labels Missing cases use default Lots to manage: use a jump table.

slide-32
SLIDE 32

switch jump table structure

x86 Control Flow 36

switch(x) { case 1: <some code> break; case 2: <some code> case 3: <some code> break; case 5: case 6: <some code> break; default: <some code> }

6 5 4 3 2

Jump Table Code Blocks Memory Translation sketch: if (0 <= x && x <= 6) addr = jumptable[x]; goto addr; else goto default; C code:

1

slide-33
SLIDE 33

switch jump table assembly declaration

x86 Control Flow 37

.section .rodata .align 8 .L4: .quad .L8 # x == 0 .quad .L3 # x == 1 .quad .L5 # x == 2 .quad .L9 # x == 3 .quad .L8 # x == 4 .quad .L7 # x == 5 .quad .L7 # x == 6 switch(x) { case 1: // .L3 w = y * z; break; case 2: // .L5 w = y - z; case 3: // .L9 w += z; break; case 5: case 6: // .L7 w -= z; break; default: // .L8 w = 2; } “quad” = q suffix = 8-byte value read-only data (not instructions) 8-byte alignment

slide-34
SLIDE 34

switch case dispatch

x86 Control Flow 38

switch_eg: movl $1, %eax cmpq $6, %rdi ja .L8 jmp *.L4(,%rdi,8)

long switch_eg(long x, long y, long z) { long w = 1; switch(x) { . . . } return w; } Jump table

.section .rodata .align 8 .L4: .quad .L8 # x == 0 .quad .L3 # x == 1 .quad .L5 # x == 2 .quad .L9 # x == 3 .quad .L8 # x == 4 .quad .L7 # x == 5 .quad .L7 # x == 6 indirect jump Jump if above (unsigned, but…)

slide-35
SLIDE 35

switch cases

x86 Control Flow 39

.L3: movq %rsi, %rax imulq %rdx, %rax retq .L5: movq %rsi, %rax subq %rdx, %rax .L9: addq %rdx, %rax retq .L7: subq %rdx, %rax retq .L8: movl $2, %eax retq switch(x) { case 1: // .L3 w = y * z; break; case 2: // .L5 w = y - z; case 3: // .L9 w += z; break; case 5: // .L7 case 6: // .L7 w -= z; break; default: // .L8 w = 2; } return w;

"inlined" Fall-through.

Aside: movl is used because 2 is a small positive value that fits in 32 bits. High order bits of %rax get set to zero automatically. It takes fewer bytes to encode a literal movl vs a movq.

Reg. Use %rdi x %rsi y %rdx z %rax w

slide-36
SLIDE 36

switch machine code

x86 Control Flow 40

00000000004004f6 <switch_eg>: . . . 4004fd: 77 2b ja 40052a <switch_eg+0x34> 4004ff: ff 24 fd d0 05 40 00 jmpq *0x4005d0(,%rdi,8) switch_eg: . . . cmpq $6, %rdi ja .L8 jmp *.L4(,%rdi,8)

Assembly Code Disassembled Object Code

Inspect jump table contents using GDB.

Examine contents as 7 addresses

(gdb) x/7a 0x4005d0

0x4005d0: 0x40052a <switch_eg+52> 0x400506 <switch_eg+16> 0x4005e0: 0x40050e <switch_eg+24> 0x400518 <switch_eg+34> 0x4005f0: 0x40052a <switch_eg+52> 0x400521 <switch_eg+43> 0x400600: 0x400521 <switch_eg+43> Address of code for case 0 Address of code for case 1 Address of code for case 6

slide-37
SLIDE 37

Would you implement this with a jump table?

x86 Control Flow 41

switch(x) { case 0: <some code> break; case 10: <some code> break; case 52000: <some code> break; default: <some code> break; }

slide-38
SLIDE 38

CS 251 Fall 2019 Principles of Programming Languages

Ben Wood

λ

CS 240

Foundations of Computer Systems

https://cs.wellesley.edu/~cs240/

x86 Control Flow

(Part A, Part B) Condition codes, comparisons, and tests [Un]Conditional jumps and conditional moves Translating if-else, loops, and switch statements

x86 Control Flow 42