Lectures‎ > ‎


ARM and CPU basics


ARMv4/v7 Details

16 general purpose registers with an addition flags register
General purpose: r0..r15
Flags: cpsr (Current Program Status Register)
Memory is byte addressable, but read/write words with ldr and str must be give word aligned addresses
Some registers have special usage or special conventions
r15 is the pc (program counter)
r14 is the lr (link register)
r13 is the sp (stack pointer)
The other registers can be used for computation, but they have restrictions when implementing function calls (more below).

ARM Instructions

data processing: add, sub, mul, ror, etc.
control: b, beq, bl, bx
memory: ldr, str, ldrb, strb

ARM Assembly DDCA Book vs RPi as (gas)

GAS stands for GNU Assembler
Note that the book uses a slight different syntax than what we will be using to write and run assembly code on the Raspberry Pi.
Here are the differences:
    DDCA: uppercase for labels and instructions, GAS: lowercase for labels and instructions
    DDCA: no colon after labels, GAS: you must use a colon after a label
    DDCA: use mov pc, lr to return from a function, GAS: use bx lr to return from a function
    DDCA: no directives, GAS: need some directives like .global to expose labels to other code
    DDCA: comments semicolon ;, GAS: C/C++ style comments /* */ or //

ARM Conditional Execution 

if statements
for/while loops

ARM Memory

Static vs dynamic.
We will use static and stack allocated memory.

The ARM Stack

The Stack is just a region of memory that is used to for temporary memory allocation.
It is used to support function calls.
The stack can be used to preserve register values, pass more than 4 arguments, and for local variable allocation.
The stack pointer (SP) holds the address of the current location on the stack.
Stacks typically grow down (that is the SP starts at a high address).
To allocate stack memory, subtract from SP.
Functions must restore SP before returns (this will deallocated the stack memory).
Provide a picture.
Show some code.

ARM Procedure Calling Conventions

All functions (procedures) must follow well-defined conventions so that they can interact with each other.
There is the caller and the callee.
In ARM, we use the bl instruction to call a function.
    bl <addr> 
The bl instruction will branch to the <addr> and also update the lr (r14) register with the address just after the bl instruction.
This value in lr is called the "return address"
The first for arguments to a function are passed in the first four registers r0, r1, r2, r3
The return value of a function is passed back in r0.
Return from a function with:
    bx lr
On a function call, some registers are expected to be "preserved" and some are not preserved.
Preserved (callee-saved): r4-r11, r14, r13
Nonpreserved (caller-saved): r12, r0-r3, cpsr
Also, the stack memory above SP must be preserved by a function, but the stack memory below SP does not have to be preserved.

To preserve register values, save current values on stack. Restore values from stack before return.
Note: ARM requires that you subtract from SP in multiples of 8 (not 4 or less).

Show how to write a correct version of count_zeros().

If your function is going to call another function, make sure to preserve lr and any of the other callee saved registers you may need after the function call.

Note there are some more complex forms of function calls such as passing structs in by value as an argument or return a struct as a value.
Also, the stack may be used to allocate space for more local variables than will fit into registers.

Recursive Functions

Recursive functions are no different that regular functions.
A recursive function make a function call, this function call happens to be the address of the function itself.
The main rule is to follow the procedure calling conventions.
Preserve callee saved registers, like lr and likely one or more of the argument registers r0, r1, r2, r3.
First write the C version.
Then write the assembly version, but don't think too much about the recursive call, just think of it as a normal function call.
Preserve the correct registers.

Develop recursive factorial.