Control Flow
Decisions
if/then, switch
We want to jump unconditionally in order to:
- Continue a loop
- Complete a decision construct
This is the jmp construct.
- This is unconditional, which is not directly useful for implementing decisions and loops, but is still useful and necessary for if-else logic.
Condition Codes are status bits updated by most ALU instructions to indicate the outcome of the instruction. Important condition code bits include:
CF: carry flag (unsigned operation overflowed)ZF: zero flag (result was 0)SF: sign flag (result was negative)OF: overflow flag (signed operation overflowed)
These code bits reflect information about the outcome of the ALU operation. Stored in a special place maintained by the CPU.
These code bits can be used to make decisions in if-else logic or loops.
Comparing Values
cmp instruction is essentailly the same as sub, except that it doesn't modify the "result" operand.
- Used to compare integer values
- AT&T syntax puts the operands in the opposite of the order you might expect
- Intended to set condition codes.
cmpl %eax %ebx
- This computes
%ebx - %eaxand sets conditions appropriately.
Testing Bits
test instruction is essentially the same as and, but doesn't modify the "result" operand.
- Good for testing if a certain bit is zero.
testl $0x80, %eax
- sets ZF (zero flag) IFF bit 7 of
%eaxis0.
Set Instructions
setX instructions set a single byte to 0 or 1 depending on whether a condition code bit is set.
- Useful to get the result of a comparison as a data value
- Allows you to produce a boolean value depending on whether or not a particular condition code is set or not set.
setz %al
- Sets
%al(low byte of%rax) to1IFFZF(zero flag) is set.
Conditional Jump
We want to use the result of a comparison in order to influence a conditional jump instruction (used for implementing if/else logic and eventually-terminating loops).
Example instructions:
Signed comparisons:
je,jzwhenZFmeaning jump if equaljlwhenSF ^ OFmeaning jump if lessjlewhen(SF ^ OF) | ZFmeaning jump if less than or equaljgwhen~(SF ^ OF) & ZFmeaning jump if greaterjgewhen~(SF ^ OF)meaning jump if greater than or equal
Unsigned comparisons
jawhen~CF & ~ZFmeaning jump if above (unsigned)jaewhen~CFmeaning jump if above or equal (unsigned)jbwhenCFmeaning jump if below (unsigned)jbewhenCF | ZFmeaning jump if below or equal (unsigned)
If
Basic approach for implementing an if statement In C:
if (compare op1 and op2) {
//conditionally-executed code
}
// rest of code...
In assembly
cmp op2, op1
jX .Lout
/* conditionally-executed code */
.Lout:
/* rest of code */
- The idea is that
jXjumps to.Loutif the condition evaluates as false.
If Else
Basic approach for implementing an if/else statement In C:
if (compare op1 and op2) {
// code if true
} else {
//code if false
}
// rest of code
In assembly:
cmp op2, op1
jX .LelsePart
/* code of true */
jmp.Lout
.LelsePart:
/* code of false */
.Lout:
/* rest of code */
jXjumps to.LelsePartif the condition evaluates to false.
You should always write comments for every function in assembly.
Example:
cmpl $18, age
jl .LtooYoungToVote
movq $sCanVoteMsg, %rdi
jmp .LprintMsg
.LtooYoungToVote
movq $sCannotVoteMsg, %rdi
.LprintMsg
cmpl $18, agecompares the user input (age) with the value18. It's the same asage >= 18?jlmeans jump if less than, so if the age is less than 18, that's when we jump to the section that says that they are too young to vote.
Switch
switch statements: multiway branch based on an integer value.
- One approach is to use an
if/elseorif/...if the range of tested integers is not dense. - Otherwise, if the range of tested integers is dense, you can use jump table.
A Jump Table is an array of code addresses. You look up an entry, and jump to that location. This is a always a constant time O(1) lookup.
- This is a technique for the compiler to optimize
ifstatements.
Example of a jump table:
cmpl $1, %esi
jl .LDefaultCase
cmpl $12, %esi
jg .LDefaultCase
dec %esi
jmp *.LJumpTable(,%esi,8)
.L31DaysCase:
code to handle months 1, 3, 5, etc.
jmp .LSwitchDone
.L30DaysCase:
code to handle months 4, 6, 9, etc.
jmp .LSwitchDone
.LFebCase:
code to handle month 2
jmp .LSwitchDone
.LDefaultCase:
code to handle invalid month values
.LSwitchDone:
jmp *.LJumpTable(,%esi,8)jump table look up
And the actual jump table is an array of pointers, where the element values are code addresses specified using labels:
.LJumpTable:
.quad .L31DaysCase
.quad .LFebCase
.quad .L31DaysCase
.quad .L30DaysCase
.quad .L31DaysCase
.quad .L30DaysCase
.quad .L31DaysCase
.quad .L31DaysCase
.quad .L30DaysCase
.quad .L31DaysCase
.quad .L30DaysCase
.quad .L31DaysCase
Loops
for, while
While
To implement a loop (while) in assembly:
.Ltop:
cmp value, reg
jX .Ldone
/* loop body */
jmp .Ltop
.Ldone:
code following loop...
- Assumes that
regis a loop counter andjXis a conditional jump which, when taken, terminates the loop. - Professor's recommended way
Do While
A slightly more clever approach for this while loop is by by eliminating an unconditional jump from the loop body. Essentially a do while loop:
jmp .LcheckCond
.Ltop:
/* loop body */
.LcheckCond:
cmp value, reg
jX .Ltop
/* code following loop... */
- Assume that
regis a loop counter andjXis a conditional jump which, when taken, continues the loop
Linked from Computer System Fundamentals