Lab01 CPU Solutions
Lab01 CPU Solutions
LAB 1
CPU ASM LAB EXERCISE:
PROCESSING TEXT IN ASSEMBLY LANGUAGE
Issue 1.0
Contents
1 Introduction.............................................................................................1
1.1 Lab overview..........................................................................................................................1
2 Learning Outcomes..................................................................................1
3 Requirements.......................................................................................... 1
4 Software.................................................................................................. 2
4.1 Mixing Assembly Language and C Code.................................................................................2
4.2 Main.......................................................................................................................................2
4.3 Register Use Conventions......................................................................................................2
4.3.1 Calling Functions and Passing Arguments......................................................................2
4.3.2 Temporary Storage........................................................................................................2
4.3.3 Preserved Registers.......................................................................................................3
4.3.4 Returning from functions...............................................................................................3
4.4 String Copy.............................................................................................................................3
4.5 String Capitalization...............................................................................................................3
5 Lab Procedure..........................................................................................4
1 Introduction
1.1 Lab overview
In this exercise, you will execute assembly code on the Nucleo-F401RE board using the debugger to
examine its execution at the processor level.
Please make sure to read and go through the Getting Started with KEIL guide before/during the lab.
2 Learning Outcomes
Write a mixed C program and assembly language subroutines for the microcontroller.
Call the subroutines written in assembly in a C function.
Use Arm register calling conventions when writing subroutines in assembly language.
Use a suitable debugging tool to view and analyse the processor state.
3 Requirements
In this lab, we will be using the following hardware and software:
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 1
4 Software
4.1 Mixing Assembly Language and C Code
We will program the board in C, but add assembly language subroutines to perform the string copy
and capitalization operations. Some embedded systems are coded purely in assembly language, but
most are coded in C and resort to assembly language only for time-critical processing. This is because
the code development process is much faster (and hence much less expensive) when writing in C
when compared to assembly language. Writing an assembly language function which can be called
as a C function results in a modular program which gives us the best of both worlds: the fast,
modular development of C and the fast performance of assembly language. It is also possible to add
inline assembly code to C code, but this requires much greater knowledge of how the compiler
generates code.
4.2 Main
First we will create the main C function. This function contains two variables (a and b) with character
arrays.
int main(void)
{
const char a[] = "Hello world!";
char b[20];
my_strcpy(a, b);
my_capitalize(b);
while (1);
}
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 2
Registers r0 through r3 can be used for temporary storage if they were not used for arguments, or if
the argument value is no longer needed.
Our function will load a character from memory, save it into the destination pointer and increment
both pointers until the end of the string.
Each character in the string is represented with its ASCII code. For example, ‘A’ is represented with a
65 (0x41), ‘B’ with 66 (0x42), and so on up to ‘Z’ which uses 90 (0x5a). The lower case letters start at
‘a’ (97, or 0x61) and end with ‘z’ (122, or 0x7a). We can convert a lower case letter to an upper case
letter by subtracting 32.
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 3
LDRB r1, [r0] // Load byte into r1 from memory pointed to by r0 (str
pointer)
CMP r1, #'a'-1 // compare it with the character before 'a'
BLS cap_skip // If byte is lower or same, then skip this byte
cap_skip
ADDS r0, r0, #1 // Increment str pointer
CMP r1, #0 // Was the byte 0?
BNE cap_loop // If not, repeat the loop
BX lr // Else return from subroutine
}
The code is shown above. It loads the byte into r1. If the byte is less than ‘a’ then the code skips the
rest of the tests and proceeds to finish up the loop iteration.
This code has a quirk – the first compare instruction compares r1 against the character immediately
before ‘a’ in the table. Why? What we would like is to compare r1 against ‘a’ and then branch if it is
lower. However, there is no branch lower instruction, just branch lower or same (BLS). To use that
instruction, we need to reduce by one the value we compare r1 against.
5 Lab Procedure
1. Compile the code.
2. Load it onto your board.
3. Run the program until the opening brace in the main function is highlighted. Open the
Registers window (View->Registers Window) What are the values of the stack pointer (r13),
link register (r14) and the program counter (r15)?
4. Open the Disassembly window (View->Disassembly Window). Which instruction does the
yellow arrow point to, and what is its address? How does this address relate to the value of
pc?
a. SUB sp,sp,#0x28 is at address 0x0000_0AF8,which is the value of pc. This is the next
instruction which will be executed.
5. Step one machine instruction using the F10 key while the Disassembly window is selected.
Which two registers have changed (they should be highlighted in the Registers window), and
how do they relate to the instruction just executed?
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 4
a. The stack pointer r13 has changed to 0x2000_0FD8, resulting from subtracting 0x28 from
0x2000_1000. The program counter r15 has changed to 0x0000_0AFA, resulting from
executing the subtract instruction (which is two bytes long).
6. Look at the instructions in the Disassembly window. Do you see any instructions which are
four bytes long? If so, what are the first two?
7. Continue execution (using F10) until reaching the BL.W my_strcpy instruction. What are the
values of the sp, pc and lr?
8. Execute the BL.W instruction. What are the values of the sp, pc and lr? What has changed
and why? Does the pc value agree with what is shown in the Disassembly window?
9. What registers hold the arguments to my_strcpy, and what are their contents?
10. Open a Memory window (View->Memory Windows->Memory 1) for with the address for src
determined above. Open a Memory window (View->Memory Windows->Memory 2) for with
the address for dst determined above. Right-click on each of these memory windows and
select ASCII to display the contents as ASCII text.
11. What are the memory contents addressed by src?
a. Hello world!
13. Single step through the assembly code watching memory window 2 to see the string being
copied character by character from src to dest. What register holds the character?
a. r2
14. What are the values of the character, the src pointer, the dst pointer, the link register (r14)
and the program counter (r15) when the code reaches the last instruction in the subroutine
(BX lr)?
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 5
15. Execute the BX lr instruction. Now what is the value of PC?
a. pc = 0x0000_0B0C
16. What is the relationship between the PC value and the previous LR value? Explain.
a. pc is lr+1. The processor resumes executing code at address 0x0000_0B0C, but the last bit of
the pc is set to indicate the processor is executing in Thumb mode.
17. Now step through the my_capitalize subroutine and verify it works correctly, converting b
from “Hello world!” to “HELLO WORLD!”.
Copyright © 2024 Arm Limited (or its affiliates). All rights reserved.
Page 6