0% found this document useful (0 votes)
18 views

Lab01 CPU Solutions

Hello

Uploaded by

Inavilli Prudhvi
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views

Lab01 CPU Solutions

Hello

Uploaded by

Inavilli Prudhvi
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

Efficient Embedded Course

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:

 KEIL µVision5 MDK IDE


o Please check the Getting Started with KEIL guide on how to download and install it.
 STM32 Nucleo-F401RE
o For more information, click here.

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);
}

4.3 Register Use Conventions


There are certain register use conventions which we need to follow if we would like our assembly
code to coexist with C code. We will examine these in more detail later in the module “C as
implemented in Assembly Language”.

4.3.1 Calling Functions and Passing Arguments


When a function calls a subroutine, it places the return address in the link register lr. The arguments
(if any) are passed in registers r0 through r3, starting with r0. If there are more than four arguments,
or they are too large to fit in 32-bit registers, they are passed on the stack.

4.3.2 Temporary Storage

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.

4.3.3 Preserved Registers


Registers r4 through r11 must be preserved by a subroutine. If any must be used, they must be
saved first and restored before returning. This is typically done by pushing them to and popping
them from the stack.

4.3.4 Returning from functions


Because the return address has been stored in the link register, the BX lr instruction will reload the
pc with the return address value from the lr. If the function returns a value, it will be passed through
register r0.

4.4 String Copy


The function my_strcpy has two arguments (src, dst). Each is a 32-bit long pointer to a character. In
this case, a pointer fits into a register, so argument src is passed through register r0 and dst is passed
through r1.

Our function will load a character from memory, save it into the destination pointer and increment
both pointers until the end of the string.

__asm void my_strcpy(const char *src, char *dst)


{
loop
LDRB r2, [r0] // Load byte into r2 from memory pointed to by r0 (src
pointer)
ADDS r0, #1 // Increment src pointer
STRB r2, [r1] // Store byte in r2 into memory pointed to by (dst
pointer)
ADDS r1, #1 // Increment dst pointer
CMP r2, #0 // Was the byte 0?
BNE loop // If not, repeat the loop
BX lr // Else return from subroutine
}

4.5 String Capitalization


Let’s look at a function to capitalize all the lower-case letters in the string. We need to load each
character, check to see if it is a letter, and if so, capitalize it.

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.

__asm void my_capitalize(char *str)


{
cap_loop

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

CMP r1, #'z' // Compare it with the 'z' character


BHI cap_skip // If it is higher, then skip this byte

SUBS r1,#32 // Else subtract out difference to capitalize it


STRB r1, [r0] // Store the capitalized byte back in memory

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)?

a. sp = 0x2000_1000, lr = 0x0000_025B, pc = 0x0000_0AF8.

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?

a. Yes: BL.W my_strcpy and BL.W my_capitalize.

7. Continue execution (using F10) until reaching the BL.W my_strcpy instruction. What are the
values of the sp, pc and lr?

a. sp = 0x2000_0FD8, lr = 0x0000_025B, pc = 0x0000_0B08.

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?

a. sp = 0x2000_0FD8, lr = 0x0000_0B0D, pc = 0x0000_01B8. lr has changed because the bl.w


instruction saved the return address (old value of PC + length of bl.w instruction +1). pc has
changed because the pc is loaded with the address of the subroutine to execute. Yes, the PC
matches the disassembly window contents – the yellow arrow points to the instruction at
0x0000_01B8.

9. What registers hold the arguments to my_strcpy, and what are their contents?

a. src: register r0, value 0x2000_0FF0

b. dst: register r1, value 0x2000_0FDC

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!

12. What are the memory contents addressed by dst?

a. Null characters, displayed as ……………. in ASCII mode.

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)?

a. r2 = 0x0000_0000, src = r0 = 0x2000_0FFD, dst = r1 = 0x2000_0FE9, lr = 0x0000_0B0D, pc =


0x0000_01C4

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

You might also like