CS 208 w20 lecture 10 outline
1 Review
- write one sentence on the difference between
lea
andmov
instructions
2 Practice
Translate assembly to C
f(long, long): subq %rsi, %rdi jne .L3 movq %rdi, %rax ret .L3: movq %rsi, %rax ret
long f(long x, long y) { long z = x - y; if (z == 0) { return z; } return y; }
f(long, long): cmpq $2, %rdi setle %dl cmpq %rsi, %rdi sete %al testb %al, %dl je .L3 movl $1, %eax ret .L3: movl $2, %eax ret
long f(long x, long y) { if (x < 3 && x == y) { return 1; } else { return 2; } }
f(long *p): testq %rdi, %rdi je .L4 movq (%rdi), %rax leaq -10(%rax), %rdx testq %rdx, %rdx jle .L3 addq %rax, %rax ret .L3: addq $1, %rax ret .L4: movl $0, %eax ret
#include <stdlib.h> long f(long *p) { if (p == NULL) { return 0; } if (*p - 10 > 0) { return *p + *p; } else { return *p + 1; } }
3 Loops
3.1 do-while loops
do <body-statement> while (<test-expr>);
becomes
loop: <body-statement> t = <test-expr> if (t) goto loop;
3.2 while loops
while (<test-expr>)
<body-statement>
becomes
goto test; loop: <body-statement> test: t = <test-expr> if (t) goto loop;
- note the jump-to-the-middle approach to loop implementation
- On higher optimization settings, while loops get translated into a guarded-do form
- a conditional branch followed by a do-while loop
- can allow the initial check to be optimized away if the compiler can determine the condition will always hold
long fact_while(long x){ long result = 1; while (x > 1) { result = result * x; x = x - 1; } return result; }
fact_while: movl $1, %eax jmp .L2 .L3: imulq %rdi, %rax subq $1, %rdi .L2: cmpq $1, %rdi jg .L3 rep ret
3.3 for loops
- C language standard states that in the absence of
continue
for (<init-expr>; <test-expr>; <update-expr>)
<body-statement>
is equivalent to
<init-expr>;
while (<test-expr>) {
<body-statement>
<update-expr>;
}
- hence, a for loop is then translated using jump-to-the-middle or guarded-do depending on the optimization level
4 Switch
- can make code more readable
- efficient implementation via a jump table
- array where entry \(i\) is the address of the code to be executed when the switch value is \(i\)
- time to perform switch is constant regardless of the number of cases (as opposed to series of if-else)
- used when there are more than a few cases where the values are not too far apart
- see figures 3.22 and 3.23 (p. 234-5) for example implementation
long switch_ex(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_ex(long, long, long): cmpq $6, %rdi ja .L8 jmp *.L4(,%rdi,8) .L4: .quad .L8 .quad .L3 .quad .L5 .quad .L9 .quad .L8 .quad .L7 .quad .L7 .L3: movq %rsi, %rax imulq %rdx, %rax ret .L5: leaq (%rsi,%rdx), %rax jmp .L6 .L9: movl $1, %eax .L6: addq %rdx, %rax ret .L7: movl $1, %eax subq %rdx, %rax ret .L8: movl $2, %eax ret
5 gdb