17.1 Mixing Assembly Language and C Variables and Functions
The following guidelines indicate how to interface separate assembly language modules with C modules.
- Follow the register conventions described in 13.1 Register Variables. In particular, registers W0-W7 and F0-F7, if available, are used for parameter passing. An assembly language function will receive parameters and pass arguments to called functions in these registers.
- Functions not called during interrupt handling must preserve registers W8-W15 and F8-F31, if available. That is, the values in these registers must be saved before they are modified and restored before returning to the calling function. Registers W0-W7 and F0-F7, if available, may be used without restoring their values.
- Interrupt functions must ensure that all registers are preserved. Unlike a normal function call, an interrupt may occur at any point during the execution of a program. When returning to the normal program, all registers must be as they were before the interrupt occurred.
- Variables or functions declared within a separate assembly file that
will be referenced by any C source file should be declared as global using the assembler
directive
.global
. External symbols should be preceded by at least one underscore. The C functionmain
is named_main
in assembly and conversely an assembly symbol_do_something
will be referenced in C asdo_something
. Undeclared symbols used in assembly files will be treated as externally defined.
The following example shows how to use variables and functions in both assembly language and C regardless of where they were originally defined.
The file ex1.c
defines foo
and
cVariable
to be used in the assembly language file. The C file also
shows how to call an assembly function, asmFunction
, and how to access the
assembly defined variable, asmVariable
.
Mixing C and Assembly
/*
** file: ex1.c
*/
extern unsigned int asmVariable;
extern void asmFunction(void);
unsigned int cVariable;
void foo(void)
{
asmFunction();
asmVariable = 0x1234;
}
The file ex2.s
defines asmFunction
and asmVariable
as required for use in a linked application. The
assembly file also shows how to call a C function, foo
, and how to
access a C defined variable, cVariable
.
;
; file: ex2.s
;
.text
.global _asmFunction
_asmFunction:
mov #0,w0
mov w0,_cVariable
return
.global _main
_main:
call _foo
return
.bss
.global _asmVariable
.align 2
_asmVariable: .space 2
.end
In the C file, ex1.c
, external references to symbols
declared in an assembly file are declared using the standard extern
keyword; note that asmFunction
, or _asmFunction
in the
assembly source, is a void
function and is declared accordingly.
In the assembly file, ex1.s
, the symbols
_asmFunction
, _main
and
_asmVariable
are made globally visible through the use of the
.global
assembler directive and can be accessed by any other source
file. The symbol _main
is only referenced and not declared; therefore,
the assembler takes this to be an external reference.
Calling an Assembly Function in C
The following compiler example shows how to call an assembly function
with two parameters. The C function main
in call1.c
calls the asmFunction
in call2.s
with two
parameters.
/*
** file: call1.c
*/
extern int asmFunction(int, int);
int x;
void main(void)
{
x = asmFunction(0x100, 0x200);
}
The assembly-language function sums its two parameters and returns the result.
;
; file: call2.s
;
.global _asmFunction
_asmFunction:
add w0,w1,w0
return
.end
Parameter passing in C is detailed in 14.7.2 Return Value. The two integer arguments are passed in the W0 and W1 registers. The integer return result is transferred via register W0. More complicated parameter lists may require different registers and care should be taken in the hand-written assembly to follow the guidelines.