Laboratory 4 – Introduction to ARM

 

1 Introduction

In this lab we introduce the ARM software development toolkit (ARM SDT), the ARM processor simulator and the ARM debugger. You will also get some familiarity of ARM assembly language programming.

The goals of the laboratory exercise are

2 ARM Overview

Here we outline some details which are needed in order to solve the lab problems.

2.1 Registers

The ARM processor architecture uses 16 registers:

Registers 0-12 are general purpose registers and can be used for any purpose.

Register 13 is typically used as the stack pointer (more about this later).

Register 14 is used to store the return address at function calls.

Register 15 is the program counter. It holds the address of the next instruction to be fetched

for execution.

There is also a status register: CPSR. It contains, among other things, the following important status bits:

N – Negative, set when the result of an arithmetic operation is negative (according to the

two’s complement encoding of the natural numbers).

Z – Zero, set when the result of an operation is zero.

C – Carry, set when an operation results in a carry bit from the most significant position.

V – oVerflow, set when an operation results in arithmetic error.

I – IRQ, interrupt enable/disable.

F – FIQ, fast interrupt enable/disable.

T – Thumb, enables Thumb mode instruction set2.

The CPSR also shows in what mode the processor is currently executing. Some of the available modes are:

USR32 – User mode.

FIQ – Fast interrupt mode.

IRQ – Interrupt mode.

SVC – Supervisor mode.

ABT – Abort mode.

UND – Undefined mode.

For a more thorough discussion about processor modes and their meaning we refer to one of the ARM manuals available through the link section on the course web site. In the course we will deal only with the User, Interrupt and Supervisor modes.

 

2.2 Some important instructions and directives

The example program used in the homework uses a few instructions and directives explained here.

 

AREA lab1_text, CODE

SWI_Exit EQU 0x11

ENTRY

The line, which starts with AREA defines a new section in the program with a name lab1_text and with an attribute CODE specifying that this section contains instructions (and not data).  EQU defines SWI_Exit as 0x11 the number for the terminating interrupt. The third line with only the word ENTRY specifies that the next instruction is the entry point of the program, i.e., the start address.

 

MSR CPSR_f,#0

This line is an instruction to move (actually copy) a register contents or, as in this case, an immediate constant to the Current Processor Status Register (CPSR). The _f specifies that it should only apply to the flags bit field. Effectively, this instruction clears the flags bit field.

 

Close to the end in the program we find:

stop

SWI SWI_Exit

 

This instruction performs the functionality of notifying the operating system that the

program has reached its end and that execution should halt.

 

At the very end we find:

AREA my_data_area, DATA

my_data DCD 1,2,0

Again, the AREA directive specifies a new section. This time a data section with the name

my_data_area. The DCD directive reserves space in memory for the data 1, 2 and 0. One word each is reserved. The label my_data can be used to access the data value 1.  Data values 2 and 0 are on addressesmy_data+4 and my_data+8 respectively.

It is strictly speaking not necessary to have a separate section for the data. They could have been declared in the code section. However, the code section is read-only by default and a data section is read/write by default so if the program were to be executed on a version of ARM with memory management, then it might not work if read/write data resides in a code section.

 

3. Lab tasks

3.1 task 1

Make sure that you understand what the following program should do and how it works. Make sure you understand which lines are instructions and which are directives. Perform a mental execution of the program and try to understand how registers are modified by this code.

 

      AREA lab2_text, CODE

SWI_Exit EQU 0x11

      ENTRY

 

start

 

init  MOV R0, #0

      MOV R1, #0

      MOV R2, #0

      MOV R3, #0

      MSR CPSR_f,#0

     

ex1   MOV R0,#3

      MOV R1,#2

      ADDS R2,R0,R1

           

      MOV R0, #0

      MOV R1, #0

      MOV R2, #0

      MSR CPSR_f,#0

           

ex2   MOV R0,#4

      MOV R1,#3              

      SUBS R2,R0,R1

      SUBS R3,R1,R0

                 

      MOV R0,#0

      MOV R1,#0

      MOV R2,#0

      MOV R3,#0

      MSR CPSR_f, #0

 

ex3   MOV R0,#1

      MOV R1,#2

      CMP R0,R1

      BLE smaller

greater     MOV R2,#2

      B init4

smaller     MOV R2,#1

 

init4 MOV R0, #0

      MOV R1, #0

      MOV R2, #0

      MSR CPSR_f,#0

                 

ex4   MOV R0,#3

      MOV R1,#1

loop  SUBS R0,R0,R1

      BGE loop

                 

      MOV R0, #0

      MOV R1, #0

      MSR CPSR_f,#0

                 

ex5   ADR R3,my_data

      LDR R0,[R3]

      LDR R1,[R3,#4]!

      ADD R2,R1,R0

      STR R2,[R3,#4]

           

stop 

      SWI SWI_Exit

 

      AREA my_data_area, DATA

           

my_data     DCD   1,2,0

 
        END

 

4 The ARM Project Manager-Review

The ARM Project Manager (APM) is a graphical development tool that automates some of the routine operations of managing source files and building your software development project. APM uses the concept of a project to maintain information of the system you are building. You specify what to build and how to build it. When you have described your system as a project, you can build all of it or just the parts that are needed. If the project output is an executable file, you can execute it or debug it using the ARM debugger.

4.1 Starting APM

This description assumes that you are working on a Windows PC. If the program has been properly installed, you should be able to start the program from the Start button.

Click “Start -> Programs-> Instructional -> ARM Project Manager” and the program should start.

4.2 Creating a new project

To create a new project in the APM you select “Project -> New” .Make sure that the project is of type

ARM Image Format. Also select a name and a directory to put your project and click on OK when you are done. Remember to put your project in a directory which is on a network drive so that you can access it later on a different computer and use simple Path names without spaces.When the project has been created, you can add files to it. In this lab we will only add source code files, but a number of other files can also be associated with a project. The extension .s indicates that the file contains assembler code and the extension .c indicates that it is a file with C-code. Add a file from menu “Project -> Edit”.

When you have added your file(s) and edited them, the project is ready to be built. The default project

template sets up different targets: Debug target has debugging information which is essential for running the program through the debugger.

 

5 The ARM Debugger (for Windows) ADW

The ARM Debugger enables you to debug your ARM-targeted program. This is the way we will use it for most of the labs.

5.1 Starting the debugger

If you developed your program using APM, you should be able to start the debugger simply by

pressing the key F5. This will start the debugger and automatically transfer the executable image to

the debugger.

5.2 Breakpoints

Breakpoints are used to halt the execution at a certain instruction line in the code. When you set a breakpoint it is marked in red in the left pane of the breakpoints window. There are two methods you can use to set a breakpoint. You can double click on the line where you want to set the breakpoint and then press OK. Or you can select the desired breakpoint line and then press F9 or use the Execute menu.

5.3 Views

In the ARM debugger you can choose between several views (windows) to display what is happening during the execution. The available windows are all listed in the View menu in the ARM debugger.

Here we will describe the ones that might be useful for the lab.

5.3.1 Execution window

The execution window displays the source code of the program that is currently executing. It is used to execute the entire program at once or to step through it, line by line. The execution window is also used to set, edit, or remove breakpoints.

5.3.2 Console window

The console window allows you to interact with the executing program. Anything printed by the program, for example a prompt for user input, is displayed on this window and any input required by the program must be entered here.

5.3.3 Disassembly window

The disassembly window displays disassembled code interpreted from a specified area of the memory. Memory addresses are listed in the left-hand pane and disassembled code is displayed in the righthand pane. The disassembly window can, for example, be used to set, edit, or remove breakpoints.

5.3.4 Low Level Symbols windows

The low level symbols window displays a list of all low-level symbols in your program. This window

can be used to display the memory or the source/disassembled code pointed to by the selected symbol. The low level symbols window can also be used to set, edit or remove breakpoints.

5.3.5 Memory window

The memory window displays the contents of the memory in a specified address area. Addresses are listed in the left-hand pane and the memory content is displayed on the right-hand pane. The memory window can be used to change the contents of memory (just double click on a line).

5.3.6 Registers window

The registers window displays the registers and their contents. You can double click on an item to modify the value in the register. The register window can be used to display the memory pointed to by the selected register. It can also be used to edit the contents of a register. Note uppercase indicates set (1) lowercase (0)

 

6 Lab exercise

Work your way through these exercises and contact the lab assistant when you have any question or when you have finished discuss the result.

6.0 Comment the code!

Since this is nonsense code you will not be commenting as an algorithim but more simply as what each line does.

6.1 Executing simple ARM assembler code

Create a new project in APM and add a file that contains lab 1. Build the Debug target and press F5 to load the executable image in the debugger. Configure the debugger in the following way:

Select “Options -> Configure Debugger…”.

Make sure Target Environment is Armulator.

 Select tab Debugger and make sure Endian is set to Little.

This configuration needs to be done only the first time and when you want to modify it. If you move to a different computer, you might need to check the configuration again.

When the program has been loaded and you have selected your views (the default is probably good enough), you can execute the program. Although it is possible to execute the entire program all-at once, this is not meaningful as the exercise is about looking at single instruction execution. Therefore, we will use stepwise execution, which can be done by pressing F10. If you want to execute a certain exercise again without stepping through the previous ones, you can use breakpoints and execute to the breakpoint by pressing F5.

You start up in some initializing code but you can F8 until you see the beginning of your code

You are also encouraged to experiment with the debugger while you are performing the exercises.

For exercises ex1 to ex5 the enclosed tables should be filled in. After executing a line of code, fill in the values in the various registers and the values of the CPSR status bits. A CPSR status bit is set

(1) when the corresponding letter is capitalized, otherwise it is zero (0). The register fields should be filled in with the decimal value and not the hexadecimal value, unless it is an address. For each exercise there are also a couple of questions that need to be answered.

Please note, that after each exercise reset operations are executed. I.e. all used registers are cleared and the status bits are reset. These operations no not need to be monitored. But there is no harm in doing it.

 

6.1.1 Ex1

Exercise 1 is an addition. Before the addition operation is performed, the two terms are loaded into registers.

 Questions:

In which register is the result stored?

What is the difference between the instructions ADD and ADDS?

6.1.2 Ex2

Exercise 2 is a subtraction. The two terms are loaded into registers, then two different subtract operations are performed.

 Questions:

In what order are the registers subtracted?

How is a subtraction executed?

Why is the carry flag set after the first subtraction?

Which flag is set to indicate that the result of an operation is negative?

 

 6.1.3 Ex3

In exercise 3, two operands are compared and based on the comparison, one of two possible branches is executed.

 Questions:

Which branch is executed and why?

How do you think a compare action is conducted?

Which flag does the branch operation, BLE, use?

What values should the flags have in order for the BLE instruction to cause a branch jump? Verify that with an experiment.

 

 6.1.4 Ex4

Exercise 4 illustrates how a loop can be implemented and executed in ARM.

 

Questions:

Which register serves as the loop counter?

How many times is the loop entered?

Which flags does the branch operation, BGE, use?

What values should the flags have in order for the BGE instruction to cause a branch jump?

11

 6.1.5 Ex5

In this exercise we will try to load and store values to and from memory. Memory space for our data is allocated at the label my_data. Three variables are defined and initialized.

Use the Low Level Symbols window to find out at what address, space for my_data is allocated.

In the Memory window changes in the memory during execution can be monitored.

In this assignment, you should fill in the register fields with their hexadecimal values since they are addresses.

 

Questions:

At what memory address is my_data?

What is register R3 used as?

What is the address difference between two sequentially stored values? Why?

At what memory address is the result of the operation stored?

What does the ! symbol do? (Tip, look at register R3 before and after the LDR with ! operation, compare with the STR without ! operation).