You are on page 1of 15

ARM Assembly - 2

Computer Organization, Tutorial 6


Stack Pointer and Link Register
We need to store the processor state when making nested
calls. The multiple data transfer instructions provide a
mechanism for storing state on the stack. Register R13 is
used as a pointer to the active stack.
Register R14 is used to store the return address from a
subroutine. When a BL or BLX instruction performs a
subroutine call, LR is set to the subroutine return address. To
perform a subroutine return, copy LR back to the program
counter.
Instructions
Load and store
Load data from a memory location to a register
Store data from a register to a memory location
Transfer of a single register
ldr and str
Multiple load and store
Same as above, except allows between one and
16 registers to be moved between the processor
and memory.
Load and Store
LDR{<cond>} Rd, <address>
STR{<cond>} Rd, <address>
e.g.
LDR R0, [R1]
STR R0, [R1]
Load and Store
LDR{<cond>} Rd, <address>
STR{<cond>} Rd, <address>
e.g.
LDR R0, [R1]
STR R0, [R1]

Memory
Pre-Indexing
[Rn, #imm] Immediate offset: Address accessed is imm more/less than the
address found in Rn. Rn does not change.
ldr r2, [r1, #12] @ r2 *(r1 + 12)

[Rn, Rm] Register offset: Address accessed is the value in Rn the value in Rm. Rn
and Rm do not change values.
ldr r2, [r0, r1] @ r2 *(r0 + r1)

[Rn, Rm, shift] Scaled register offset: Address accessed is the value in Rn the
value in Rm shifted as specified. Rn and Rm do not change values.
ldr r0, [r1, r2, lsl #2] @ r0 *(r1 + r2*4)
Pre-Indexing with Update
[Rn, #imm]! Immediate pre-indexed w\update: Address accessed is as with
immediate offset mode, but Rn's value updates to become the address accessed.
ldr r2, [r1, #12]! @ r1 r1 + 12 then r2 *r1

[Rn, Rm]! Register pre-indexed w\update: Address accessed is as with register


offset mode, but Rn's value updates to become the address accessed.
ldr r2, [r0, r1]! @ r0 r0 + r1 then r2 *r0

[Rn, Rm, shift]! Scaled register pre-indexed: Address accessed is as with scaled
register offset mode, but Rn's value updates to become the address accessed.
ldr r2, [r0, r1, lsl #2]! @ r0 r0 + r1*4 then r2 *r0
Post-Indexing
[Rn], #imm Immediate post-indexed: Address accessed is value found in Rn, and
then Rn's value is increased/decreased by imm.
str r2, [r1], +4 @ *r1 r2 then r1 r1 + 4

[Rn], Rm Register post-indexed: Address accessed is value found in Rn, and then
Rn's value is increased/decreased by Rm.
str r0, [r1], r2 @ *r1 r0 then r1 r1 + r2

[Rn], Rm, shift Scaled register post-indexed Address accessed is value found in Rn,
and then Rn's value is increased/decreased by Rm shifted according to shift.
ldr r0, [r1], r2, lsl #3 @ r0 *r1 then r1 r1 + r2*8
Variables on stack
We only have a few registers to store the data. What if we run out of
them but still need variables to keep?
These variables could be stored onto the stack and accessed from
there.
sub sp, #8 @ grow stack by 8 bytes
str r4, [sp,#0]
str r5, [sp,#4]
To delete /free variables add sp, #8
Subroutines - Defining functions
Processor architectures need some way to store the address of the
caller. On ARM processors, this return address is stored in LR (the
link register).
Branch instructions with an l suffix -- like bl and blx -- work just
like a standard b or bx branch, but also store a return address in
LR.
If a function does not modify lr, then the return sequence can (and
should) be a simple "bx lr". Otherwise, the LR can be pushed
onto the stack at function entry. From here, the best return
sequence is usually to pop directly into PC.
Subroutines - Calling with BL
fib2:
cmp r2, #0 main:
bne gr8 mov r0, #1
mov r1, r3 loop:
mov pc, lr add r7, r7, #1
gr8: mov r2, r7
sub sp, sp, #12 mov r3, #0
str lr, [sp, #0] mov r4, #1
str r3, [sp, #4] bl fib2
str r4, [sp, #8] mov r0, #1
sub r2, r2, #1 swi 0x6b
add r4, r4, r3 mov r0, #' '
sub r3, r4, r3 swi 0x00
bl fib2 cmp r7, #30
add r2, r2, #1 bne loop
ldr lr, [sp, #0] swi 0x11
ldr r3, [sp, #4]
ldr r4, [sp, #8]
add sp, sp, #12
Saving Registers onto Stack
We can use load multiple and store multiple instructions to save the
registers on stack for later use.
HW: Check the documentation and try to save 4 registers onto the
stack with just a simple statement.
ARMSim: Debugging
Breakpoints: A breakpoint is a userdefined stopping point in a
program (i.e. a point other than an SWI 0x11 instruction, at which
execution of a program should terminate).
When a program is being debugged, breakpoints are used to halt
execution of the program at predefined points so that the contents of
storage locations, such as registers and main memory, can be
examined to ensure that the program is working correctly.
When a breakpoint is set and the program is run using either the
Debug > Run option or the Continue button, execution of the program
stops just before execution of the instruction at which the breakpoint is
set.
ARMSim: Debugging
To set a breakpoint, doubleclick the line of code, at which the
breakpoint should be set.
Alternatively, step through the code to the line, at which the breakpoint
should be set, and then select Debug > Toggle Breakpoint
When the breakpoint is set, a large red dot appears in the Code View
next to the address of the instruction at which the breakpoint was set.
Clear the breakpoint by doubleclicking the line of code, at which the
breakpoint is set.
ARMSim: Debugging

Reference: http://armsim.cs.uvic.ca/AttachedFiles/ARMSim_UserGuide4Plus.pdf

You might also like