CS 208 f21 — x86-64 Control Flow: Conditionals
Table of Contents
1 Review
What effect do these instructions
:
leaq (%rdx,%rcx,4), %rax
movq (%rdx,%rcx,4), %rbx
leaq (%rdx), %rdi
movq (%rdx), %rsi
have on register values give the initial state below?1
2 208 Reference Sheet
3 Jump Instructions
- class of
jumpinstructions move program execution to specified instruction (figure 3.15, p. 206) - direct jumps encode the jump target in the instruction
- indirect jumps read the jump target from register or memory
- written with a
*preceding the operand
- written with a
- conditional jumps (can only be direct) jump or continue the subsequent instruction based on some combination of condition codes
| Instruction | (op) s, d |
test a, b |
cmp a, b |
||
|---|---|---|---|---|---|
jmp |
Unconditional | ||||
je |
sete |
"Equal" | d (op) s == 0 |
b & a == 0 |
b == a |
jne |
setne |
"Not equal" | d (op) s != 0 |
b & a != 0 |
b != a |
js |
sets |
"Sign" (negative) | d (op) s < 0 |
b & a < 0 |
b - a < 0 |
jns |
setns |
(non-negative) | d (op) s >= 0 |
b & a >= 0 |
b - a >= 0 |
jg |
setg |
"Greater" | d (op) s > 0 |
b & a > 0 |
b > a |
jge |
setge |
"Greater or equal" | d (op) s >= 0 |
b & a >= 0 |
b >= a |
jl |
setl |
"Less" | d (op) s < 0 |
b & a < 0 |
b < a |
jle |
setle |
"Less or equal" | d (op) s <= 0 |
b & a <= 0 |
b <= a |
ja |
seta |
"Above" (unsigned >) | d (op) s > 0U |
b & a > 0U |
b - a > 0U |
jb |
setb |
"Below" (unsigned <) | d (op) s < 0U |
b & a < 0U |
b - a < 0U |
3.1 Implementing Conditional Branches with Conditional Control
if (<text-expr>) <then-statement> else <else-statement>
becomes
t = <test-expr>;
if (!t)
goto false;
<then-statement>
goto done;
false:o
<else-statement>
done:
3.1.1 Example
long absdiff(long x, long y) { long result; if (x > y) result = x - y; else result = y - x; return result; }
| Register | Use |
|---|---|
%rdi |
1st argument (x) |
%rsi |
2nd argument (y) |
%rax |
return value |
absdiff: cmpq %rsi, %rdi // perform x - y jle .L4 // if condition codes indicate x <= y, jump to L4 // x > y: movq %rdi, %rax subq %rsi, %rax ret .L4: // x <= y: movq %rsi, %rax subq %rdi, %rax ret
3.2 (OPTIONAL) Implementing Conditional Branches with Conditional Moves
- Reading: CSPP section 3.6.6
- class of
cmovinstructions copy source operand to destination register when the condition holds- same conditions as
setandjumpinstructions
- same conditions as
- can be more efficient than conditional jumps because the sequence of intructions is predictable
- memory may or may not be moved, but the subsequent instruction is executed regardless
- processors pipeline instructions, meaning they process them in a series of stages (fetching instruction from memory, determining instruction type, reading from memory, performing arithmetic operation, writing to memory, updating program counter)
- significant performance benefits from overlapping different stages of sequential instructions
- pipelining in the presence of conditional jumps requires sophisticated branch prediction (modern processors aim for 90% accuracy)
- turn on optimization for previous exercise (
-O1compiler flag) to see an example
4 Conditional Exercise
Translate this C code to assembly2
long wacky(long x, long y) { long result; if (x + y > 7) { result = x; } else { result = y + 2; } return result; }
4.1 Jump Instruction Encodings
If we compile wacky and disassemble it, we can see how jump instructions are encoded into machine code3:
0000000000400497 <wacky>: 400497: 48 8d 04 37 lea (%rdi,%rsi,1),%rax 40049b: 48 83 f8 07 cmp $0x7,%rax 40049f: 7f 05 jg 4004a6 <wacky+0xf> 4004a1: 48 8d 46 02 lea 0x2(%rsi),%rax 4004a5: c3 retq 4004a6: 48 89 f8 mov %rdi,%rax 4004a9: c3 retq
- jump target encoded compactly with instruction pointer relative representation
- specify offset to the address of the immediately following instruction
7fis the encoding for thejginstruction05is the jump target, meaning it will add0x5to%rip(the instruction pointer) if it jumps- when we execute the
jginstruction,%ripis set to the address of the next instruction,0x4004a1. Adding0x5to this will result in executing themovinstruction at0x4004a6instead. objdump, the disassembler I used to produce the above example, computes this for us and displays0x4004a6as the jump target even though in the machine code the target is encoded as0x5
5 Condition Codes
- condition codes are the basis for control flow within a program (i.e., determining which instruction gets executed next)
- special
%ripregister stores instruction pointer
- special
- most useful codes:
CF: carry flag. Set when an operation generated a carry out of the most significant bit. Used to detect unsigned overflowZF: zero flag. Set when an operation yields 0SF: sign flag. Set when an operation yields a negative valueOF: overflow flag. Set when an operation causes a two's complement overflow, negative or positive
- all the standard arithmetic instructions set these flags except for
leaq cmpandtestinstructions set condition codescmpsubtracts first operand from secondtestands operands (usually the same quantity is both operands, check if its zero, positive, negative)
5.1 Accessing the Condition Codes
- class of
setinstructions to set a single byte to 1 or 0 based on one or more condition codes (figure 3.14, p. 203)- in the case where
cmp b, awas executed - when \(a=b\), then \(a-b=0\), so
ZFwill be set - when \(a < b\), then \(a - b < 0\) (
SFset) or \(a - b\) overflows so the result is positive andOFis set- but both
SFandOFset would indicate \(a\) is positive and \(b\) is negative such that \(a-b\) would overflow to a negative value - hence, less than is detected when
SF ^ OF
- but both
- for unsigned \(a < b\), \(a - b\) would cause a carry out of the most significant bit, setting
CF
- in the case where
5.2 Example
5.2.1 Translate conditional C code to assembly
int gt(long x, long y) { return x > y; }
| Register | Use |
|---|---|
%rdi |
1st argument (x) |
%rsi |
2nd argument (y) |
%rax |
return value |
gt: cmpq %rsi, %rdi // perform x - y, set condition codes setg %al // if the condition codes indicate x > y, write 1 to %al movzbl %al, %eax // copy %al to %eax, using 0s to extend the 1 byte %al to the 4 bytes of %eax ret
5.2.2 movz and movs
- when moving data from a smaller source to a larger destination, can specify zero extension or sign extension
- destination must be a register
movzSD/movsSDSis the size of the source (borw)Dis the size of the destination (w,l, orq)
6 Which condition codes indicate \(a > b\)?
- not less than and not equal
~(SF ^ OF)and~ZF~(SF ^ OF) & ~ZF
7 Practice
CSPP practice problems 3.16 (p. 212) and 3.18 (p. 213)
Footnotes:
2
wacky: leaq (%rdi,%rsi), %rax cmpq $7, %rax jg .L3 leaq 2(%rsi), %rax ret .L3: movq %rdi, %rax ret
3
Perform this disassembly via an option on godbolt.org
or, by putting the code for wacky and an empty main in wacky.c and running these commands:
gcc -Og -no-pie -o wacky wacky.c objdump -d wacky
objdump will print out a bunch of boilerplate assembly that's part of any program, so you'll need to locate the definition of wacky within it.