Data processing and flow control

In this first exercise, you will write a simple assembler function, which will then be called from C. A framework project is provided, so you only need to implement the function body. To complete the exercise, you will need to use data processing instructions, conditional operations, and a knowledge of the Procedure Call Standard (PCS).

Like all the exercises, there is more than one valid solution. This means that your answer may not match the suggested solution that is shown in Appendix A.

Get started

First, load the provided framework project into Arm Development Studio, following these steps:

  1. Launch the Arm data side.

  2. Click the Import Project icon or go to File -> Import.

  3. Select General then Existing Projects into Workspace.

  4. Click Browse and navigate to where you downloaded the files that accompany the exercise. Select 1_gcd.

  5. Click Finish to import the project into Arm data side.

The imported project then appears in the Project Explorer pane, as illustrated in this screenshot:


Note: You might need to expand the project to see the files.

Within the GCD project, you should see the following files:

This is a simple reset handler. You will not need to modify this file for this exercise.
This contains the C main() function, and implements a simple test harness for the function that you will develop.
This is an A64 assembler file. This file contains an empty function definition that you will complete.

This exercise does not go into detail about the structure of the project or how it is built. If you are interested in how to construct an embedded image with Arm Compiler 6, see Building your first embedded image

Implement an assembler function

In this exercise, you implement Euclid’s algorithm for finding the greatest common denominator (GCD) of two integers. The algorithm is illustrated in the following flow chart:


To complete this exercise, follow these steps:

  1. Open the file gcd.s
  2. This file contains the outline for the GCD function, as you can see in the following code:

    .global gcd
        // uint32_t gcd(uint32_t a, uint32_t b)
        .type gcd, @function
        //  ADD YOUR CODE HERE

    The function takes two 32-bit unsigned integers as arguments, a and b. The function returns a single 32-bit unsigned integer, which is the GCD of the two arguments.

  3. Attempt to implement the function body using A64 assembler. You might want to read the sections Arithmetic and logic operations and Program flow in the Armv8-A Instruction Set Architecture (ISA)
  4. Here are a few things for you to consider before getting started:

    • Which registers will the arguments a and b be passed in?
    • Given that 32-bit types are being used, what kind of general-purpose register should be used?
    • Which register should the return value be in?
    • How do you return from the function?
    Run the completed image

    After you have completed the function, you can test it using the Fixed Virtual Platform (FVP) models that are provided with Arm Development Studio. Follow these steps:

  5. Right-click on the project and select Build Project. Or, select Build Project from the Project menu.
  6. You will see the Console tab, which is near the bottom of the screen in a fresh installation. The Console tab shows the build messages. If the project builds successfully, the output will look like what you can see in the following screenshot:

  7. Check for any errors. If there are any, correct them and try to rebuild the project.
  8. Once you have successfully built your image, you can test it using the FVP models. This exercise uses an FVP with a single-core Cortex-A53 processor.

  9. Double-click on the A64 – GCD.launcher file in the project, as shown in the following screenshot:
  10. Pointing to A64-GCD.launch in Project Explorer

    The Edit Configuration window opens.

  11. Click Debug to launch the simulation.
  12. The debugger will launch the model, load the image, and run to the start of main(). You should see something that looks like the following screenshot:

    The icons in the Debug Control tab let you run, stop, or step the model, as shown here in this detail from the larger screenshot:

  13. Click the green arrow icon to run the model.
  14. The output from the simulator will be shown in the Target Console tab. The output for a successful run looks like what you can see in the following output log:

    terminal_0: Listening for serial connection on port 5000
    terminal_1: Listening for serial connection on port 5001
    terminal_2: Listening for serial connection on port 5002
    terminal_3: Listening for serial connection on port 5003
    CADI server started listening to port 7000
    Info: FVP_Base_Cortex_A53x1: CADI Debug Server started for ARM Models...
    CADI server is reported on port 7000
    GCD Workbook: The GCD of 50 and 75 is 25
Debug your image

Note: This section introduces the Arm Developer Studio controls for debugging. If you are new to the Arm Developer Studio, you can work through this section. If have used Arm Developer Studio side before, or the DS-5 Debugger, you can skip this section.

To begin, we want a fresh simulation. Follow these steps:

  1. Disconnect from the model using the Disconnect from Target in Debug Control pane.
  2. Double-click on the entry for the model connection, to reconnect to the model. 

The connection is pre-configured to run the simulation to the start of main().

At the start of the program, the Debug Control tab provides controls for running and stepping:

  • Run - The simulation executes until it hits a breakpoint, or until it reaches the end of the program.
  • Step Source Line - moves the simulation on either one C statement or one A64 instruction. The icon in Debug Control controls whether a C statement or A64 instruction is stepped.
  • Step over or Step out are useful for functions. Step-over a function call will move execution to the next instruction after the function has returned. Step-out will move execution on until the current function as returned.

The current value of registers, or for C variables, can found in the Registers and Variables pane, as you can see in this screenshot:

Previous Next