Title: Control Structures in Assembly Language
1Control Structures in Assembly Language
- Assembly Language Programming
- University of Akron
- Dr. Tim Margush
2Structured Programming
- A disciplined approach to designing algorithms
using a limited number of standard control
structures - These are typically
- sequence
- selection
- repetition
3Structured Building Blocks
- The primary building block in a program is a
statement - The simplest statement is an atomic executable
unit from the perspective of the language, such
as an assignment or function call - The only other statements are the allowed control
structures which include statements as subparts
4Assembly Language Control Structures
- Sequence
- Provided by default since the program counter is
incremented to determine the address of the next
instruction - Goto
- Technically not a control "structure," but the
branching capabilities of the processor are used
to implement every other control option
5What is a Branch
- Jump and branch can be used interchangeably
- Jump usually means unconditional
- Branch sometimes means conditional
- Jump instructions place an address into the
program counter - This replaces the incremented value which would
have resulted in sequence
6AVR Jump
- The AVR provides three jump instructions
- The only difference is how the destination
address is represented - rjmp address (pc-relative addressing)
- The address must be within 2048 words of the
current instruction - jmp address (direct addressing)
- ijmp (indirect addressing)
- The address must be in Z
7Assembler Support
- Addresses are generally specified as symbols or
expressions - The most common expression is just a label
- here rjmp here
- The second most common expression involves the PC
value - rjmp PC-2 back up 2 instructions
- The previous instructions must both be a single
word
8Indirect Addressing
- The indirect jump can only use register Z for the
target address - Use the low and high functions to separate the
bytes of the address - ldi ZH, high(somewhere)
- ldi ZL, low(somewhere)
- ijmp
9Conditional Branches
- Conditional branch instructions either
- sequence
- do not change the already incremented program
counter - or branch
- replace the program counter with a new address)
- The AVR branch instructions all use PC-relative
addressing - The range is PC1-64 to PC163
- PC1 because the program counter will already be
incremented when the instruction is executed
10Conditions
- The AVR branch instructions all depend on a
single bit in the status register - brbc s, k
- branch if bit in status register is clear
- brbs s, k
- branch if bit in status register is set
- PC PC1 if the condition is not met
- PC PC 1 k if the condition is met
11Address/Displacement
- In the instruction documentation, the k in
- brbc s, k
- is a signed displacement (-64 .. 63)
- In assembly language, you specify an address and
let the assembler determine the displacement - brbc 0, somewhere
- The displacement k is calculated as (somewhere
(PC1)) - If -64 lt k lt 63 is not true, an error occurs
- To specify your own explicit displacement, you
must write (PC1)k, not just k - brbc 0, PC1-2 (k will be -2)
12Branch Aliases
- Each bit of the status register has a name or
common purpose - The assembly language provides simple aliases for
the branches made possible by the fundamental
brbc and brbs instructions - The aliases imply the bit just put the
destination as the operand - Example brcc somewhere branch if carry clear
- Same as brbc 0, somewhere (bit 0 is carry flaf)
13SREG(0) Carry
- brcc branch if carry clear
- brcs branch if carry set
- After a comparison of unsigned data it is more
readable to use these equivalent forms - brsh branch if same or higher (brcc)
- brlo branch if lower (brcs)
14Examples
- add r16, r17
- brcs unsignedOverflow
- cp r20, r21
- brlo r20isSmaller
- brsh r20isNOTsmaller
- one of the above branches must occur!
15SREG(1) Zero Flag
- brne branch if not equal (Z0)
- breq branch if equal (Z1)
- These make more sense after a comparison
- After an arithmetic or logical instruction, read
these as - branch if result is not equal to zero
- branch if result is equal to zero
16Examples
- cpi r20, 16
- breq sweet
- brlo child
- inc R16
- brne somewhere
17SREG(2) Negative Flag
- brpl branch if plus (N0)
- brmi branch if minus (N1)
- add R2,R3
- brpl notMinus
18SREG(3) oVerflow
- brvc branch if V clear (no signed overflow)
- brvs branch if V set (signed overflow)
- add R20, R21
- brvs overflow_oh_my
19SREG(4) Sign
- These are usually used after a signed comparison
- brge branch if greater or equal
- brlt branch if less
- You must choose between the signed or unsigned
version after a compare different flags are
used to determine the outcome
20SREG(5) Half Carry
- brhc branch if half carry clear
- brhs branch if half carry set
- These can be used to implement BCD arithmetic
21SREG(6) T Flag
- brtc branch if T clear
- brts branch if T set
- After loading a bit into T, this can choose two
paths of execution based on its value
22SREG(7) Global Interrupt Flag
- brid branch if interrupts disabled (I0)
- brie branch if interrupts enabled (I1)
- This allows different paths of execution
depending on whether interrupts are enabled or
not
23Skip Instructions
- The AVR processor has a few special purpose
instructions that conditionally skip the next
instruction (PCPC1, 2, or 3) - cpse Rd, Rr
- Compare and skip if equal
- sbic A, b sbis A, b
- Skip if bit in I/O register A is clear/set
(Alt31) - sbrc Rr, b sbrs Rr, b
- Skip if bit in Rr is clear/set
24Structure
- The ability to jump to any address allows the
creation of arbitrarily complex control
structures - The structured programming model seeks to limit
complexity by reducing entry and exit points from
blocks of code and providing for a
well-understood flow through a block
25Enter/Exit
- Imitating high level languages, control
structures - should be entered at the top
- and exited at the bottom
- This takes advantage of the natural sequencing
action as we read down the page
26IF
- If statements are entered at the top
- Entry is at the top
- The condition must be evaluated before the
statement in the then-part is reached - Whether the then-part is executed or not, control
continues with the statement after the if
statement - Exit at the bottom
27Assembly IF
- assume a and b are
- registers and
- contain signed data
- cp a,b
- brge end_if
- inc a
- end_if
- inc b
28Negated Condition
- We negate the if condition to achieve a more
natural flow - The code at right uses the original condition
- if (altb)
- Extra jumps are needed to get everything right
- cp a,b
- brlt then_part
- rjmp end_if
- then_part
- inc a
- end_if
- inc b
29IF Flow
- if (condition)
- action
-
- becomes
- if (!condition) branch around action
- action
- common exit point
30If/Else
- if (condition)
- then_action
- else
- else_action
-
- becomes
- if (!condition) branch to else_part
- then_action
- jump to end_if
- else_part
- else_action
- end_if
- Note the need for the jrmp to avoid falling into
the code of the else-part - If the condition is not negated, the else part
can be coded first - This results in an unfamiliar ordering of the two
alternatives - No jump is needed at the end of the else-part
it sequences to the next statement (common exit)
31One Entry
- It is assumed that no statements from elsewhere
in the program jump to any of the statements
inside the group of statements comprising the if
or if/else structure - Allowing such transfers will violate the one
entry restriction and create a control structure
that is more complex
32Compound Condition AND
- if (condition1 condition2)
- action
-
- becomes
- if (!condition1) branch to end_if
- if (!condition2) branch to end_if
- action
- end_if
33Short Circuit Evaluation
- The expression
- condition1 condition2
- is false if either condition is false
- Short circuit evaluation considers the conditions
in left to right order, and only evaluates the
next if the previous ones are true - if (!condition1) branch to end_if
- if (!condition2) branch to end_if
34DeMorgan's Law
- Assembly language programmers need to negate
conditions to implement most decision structures - DeMorgan's Law is needed for compound conditions
- (p q) p q
- (p q) p q
35Compound Condition OR
- if (condition1 condition2)
- action
-
- is awkward if negated
- if (!condition1) branch to next_condition
- branch to action
- next_condition if (!condition2) branch to end_if
- action
- end_if
36Compound Condition OR
- if (condition1 condition2)
- action
-
- Is better implemented as follows
- if (condition1) branch to then_part
- if (!condition2) branch to end_if
- then_part
- action
- end_if
Only the last condition is negated
37Example
- if (x lt -2 x gt 2)
- y x
- The second condition is negated to make the test
to skip the then_part - x lt 2
- This is an awkward condition for the AVR (there
is no brle), so it is transformed to - x lt 3
- cpi x, -2
- brlt then_part
- cpi x, 3
- brlt end_if
- then_part
- mov y, x
- end_if
38Switch
- The multiway selection structure commonly known
as switch is generally considered equivalent to
nested if/else statements - However, if the customary break statements are
not used, a more complex structure can result - Assembly is good at making complex structures!
39Switch
- switch (a)
- case 1
- x
- break
- case 3
- case 4
- y--
- break
- case 2
- x y
- default
- y x
- cpi a, 1
- breq case_1
- cpi a, 3
- breq case_3
- cpi a, 4
- breq case_4
- cpi a, 2
- breq case_2
- rjmp case_default
- cases follow
- case_1
- inc x
- rjmp case_end
case_3 case_4 dec y rjmp case_end case_2
add x, y case_default mov y, x case_end
40Computed GoTo
- The indirect jump instruction provides another
way of implementing a switch statement by
calculating the address of the code for the
specific case, and jumping directly to it - There must be an easy transformation from the
switch variable to the address
41A Jump Address Table
- This is an table of destination addresses
- jat .dw case_1, case_2, case_3, case_4,
case_default - The desired access is accessed by adding some
number to the address of the table (0, 1, 2, etc) - ldi zh, high(jat)
- ldi zl, low(jat)
- add zl, r16
- adc zh, zero
- An ijmp instruction transfers to that section of
code - ijmp
42Switch
- cpi a, 5
- brge case_default
- subi a, 1
- brmi case_default
- ldi zh, high(jat)
- ldi zl, low(jat)
- add zl, a
- brcc goto
- inc zh
- goto
- lpm xl, Z
- adwi z, 1
- lpm xh, Z
- movw zhzl, xhxl
- ijmp
- jat .dw case_1, case_2,
- case_1
- inc x
- rjmp case_end
- switch (a)
- case 1
- x
- break
- case 3
- case 4
- y--
- break
- case 2
- x y
- default
- y x
Data embedded in program cannot be executed!
43Looping
- Loops in assembly language occur when a jump
transfers to an already executed instruction - Conditional loops are naturally implemented by
using a conditional branch at the bottom of the
loop - Creates a post-test loop (do until or do while)
44Example Do Until
- loop entered here
- lp
- inc x
- brne lp
- loop exit here
Notice how this creates a natural one entry (at
the top) and one exit (at the bottom) control
structure
45Pre-Test Loops
- Placing the loop condition at the top of the loop
creates an awkward structure - while (x!0)
- x
- loop entered here
- lp
- tst x
- breq end_while
- inc x
- rjmp lp
- end_while
- loop exit here
46Pre-Test Loops
- This illustrates an alternate implementation of a
pre-test loop - An initial test precedes the loop
- The other tests are done at the end of the loop
- while (x!0)
- x
- loop entered here
- tst x
- breq end_while
- lp
- inc x
- brne lp
- end_while
- loop exit here
47Pre-Test Loops
- It is also possible to enter the loop at the
bottom (at the test) - while (x!0)
- x
- loop entered here
- cpi x, 0
- rjmp lp_test
- lp
- inc x
- lp_test
- brne lp
- loop exit here
A setup for the loop test is required in this
case because the increment action and testing are
coupled in the loop body
48For Loops
- For loops are just special cases of the standard
while loop - Precede the loop with the necessary
initializations - Decide how to code the test (at the top or
bottom) - Add the required updates for the loop counter
49Example For Loop
- ldi x, 0
- rjmp for_test
- for_loop
- inc a
- inc x
- dec y
- for_test
- cp x, y
- brlt for_loop
- breq for_loop
- exit here
An alternative might be cp y, x brge for_loop