www.riscos.com Technical Support:
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.
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:
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:
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:
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.