www.riscos.com Technical Support:
Acorn Assembler


Interworking assembler with C

Interworking assembly language and C - writing programs with both assembly language and C parts - requires using both ObjAsm and C/C++.

Interworking assembly language and C allows you to construct top quality RISC OS applications. Using this technique you can take advantage of many of the strong points of both languages. Writing most of the bulk of your application in C allows you to take advantage of the portability of C, the maintainability of a high level language, and the power of the C libraries and language. Writing critical portions of code in assembler allows you to take advantage of all the speed of the Archimedes and all the features of the machine (eg the complete floating point instruction set).

The key to interworking C and assembler is writing assembly language procedures that obey the ARM Procedure Call Standard (APCS). This is a contract between two procedures, one calling the other. The called procedure needs to know which ARM and floating point registers it can freely change without restoring them before returning, and the caller needs to know which registers it can rely on not being corrupted over a procedure call. Additionally both procedures need to know which registers contain input arguments and return arguments, and the arrangement of the stack has to follow a pattern that debuggers, etc. can understand. For the specification of the APCS, see the chapter entitled ARM procedure call standard of the accompanying Desktop Tools guide.


The following examples are provided to demonstrate how to write programs combining assembly language and C.


The directory AcornC_C++.Examples.PrintLib.s contains three source files from which you can build a library: PrintStr, PrintHex and PrintDble. These are the assembly language sources for three screen printing routines: print_string, print_hex and print_double. These respectively print null terminated strings, integers in hexadecimal, and double precision floating point numbers in scientific format.

Each routine is written to obey the APCS, so it can be called from assembler, C, or any other high level language obeying the APCS. The sources for PrintLib illustrate several aspects of the APCS, such as the distinction between leaf and non-leaf procedures, and how floating point arguments are passed into a procedure.

Compiling the CTestPrLib example

To show you that you can call the routines in PrintLib from C, we've supplied a small C program in AcornC_C++.Examples.PrintLib.c.CTestPrLib. To build this example, you must:

  1. Build the PrintLib library; you'll find instructions for this in the Assembler example of the Desktop Tools guide.
  2. Start CC if you've not already got it loaded.
  3. Drag the CTestPrLib file to the CC icon, which will display its Setup dialogue box with CTestPrLib already entered as the source to compile.
  4. Add the full pathname of the PrintLib library to the list of Libraries on the Setup menu.
  5. Click on Run to compile and link the program.
  6. Save the program to disc.

To run the program, double click on its icon in the directory display to which you saved it. A standard RISC OS command line output window appears containing text printed by the assembly language library routines as a result of arguments passed from C:

Compiling and linking CTestPrLib in separate stages

If you prefer, you can instead use the Compile only option of CC to compile CTestPrLib to an object file.

You can then use Link to link this object file with the libraries it uses. As well as the PrintLib library, it also uses the C library, so you must link three files: the object code for CTestPrLib, the library built from the PrintLib source, and the C library stubs held in AcornC_C++.Libraries.clib.o.stubs.

(In the above Compiling the CTestPrLib example, the C library stubs were linked in because they were already in the Setup menu's default list of Libraries.)


The directory AcornC_C++.Examples.CStatics gives an example of accessing C static variables from both assembler and C source code. The example builds to form a relocatable module providing a single * Command: *CStatics.

The files in the directory are as follows:

  • c.CInit is the C source code. It declares two variables: extern int var1, which is provided by and initialised to 0 in s.AsmInit (see below), and int var2, which it initialises as 0. It prints the values of the two variables. It then calls the routine Asm_Change_Vars provided by s.AsmInit (see below), which changes the values of the two variables. Finally it prints the new values.
  • cmhg.Header is the CMHG description file for the module. hdr.CVars is an assembler source file that contains a series of macros used by s.AsmInit. You will find these useful if you too ever need to share static data between assembler and C.
  • MakeFile is the make file for the CStatics module.
  • o is an empty directory used to hold the object files created when making the CStatics module.
  • s.AsmInit is the assembler source code. It initialises the variable var1 to 0 and exports it; it also imports the variable var2. It also provides an APCS conformant routine Asm_Change_Vars which adds 10 to var1 and subtracts 10 from var2. All this code makes heavy use of the macros in hdr.CVars.

To build the CStatics module, simply double click on the MakeFile.

When Make has completed, you can see the example in use. Load the resultant CStatics module by double clicking on it, then type CStatics at the command line. You will get this output:

var1 = 0
var2 = 0
var1 = 10
var1 = -10

If you repeat the *CStatics command you will see the variables change again:

var1 = 10
var2 = -10
var1 = 20
var1 = -20

and so on, every time you repeat the command.

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015