20.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 Register Conventions. In particular, registers $4-$7 are used for parameter passing. An assembly -language function will receive parameters, and should pass arguments to called functions, in these registers.
- Table 14-1 describes which registers must be saved across non-interrupt function calls.
- Interrupt functions must preserve all registers. 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. 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.S
*/
#include <xc.h>
/* define which section (for example "text")
* does this portion of code resides in. Typically,
* all your code will reside in .text section as
* shown below.
*/
.text
/* This is important for an assembly programmer. This
* directive tells the assembler that don't optimize
* the order of the instructions as well as don't insert
* 'nop' instructions after jumps and branches.
*/
.set noreorder
/*********************************************************************
* asmFunction(int bits)
* This function clears the specified bites in IOPORT A.
********************************************************************/
.global asmFunction
.ent asmFunction
asmFunction:
/* function prologue - save registers used in this function
* on stack and adjust stack-pointer
*/
addiu sp, sp, -4
sw s0, 0(sp)
la s0, LATACLR
sw a0, 0(s0) /* clear specified bits */
la s0, PORTA
lw s1, 0(s0)
la s0, cVariable
sw s1, 0(s0) /* keep a copy */
/* function epilogue - restore registers used in this function
* from stack and adjust stack-pointer
*/
lw s0, 0(sp)
addiu sp, sp,
addu s1, ra, zero
jal foo
nop
addu ra, s1, zero
nop
/* return to caller */
jr ra
nop
.end asmFunction
.bss
.global asmVariable
.align 2
asmVariable: .space 4
The file ex1.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.c
*/
#include <xc.h>
extern void asmFunction(int bits);
extern unsigned int asmVariable;
volatile unsigned int cVariable = 0;
volatile unsigned int jak = 0;
int
main(void) {
TRISA = 0;
LATA = 0xC6FFul;
asmFunction(0xA55Au);
while (1) {
asmVariable++;
}
}
void
foo(void) {
jak++;
}
In the C file, ex2.c, external references to symbols
declared in an assembly file are declared using the standard extern
keyword; note that asmFunction is a void function
and is declared accordingly.
In the assembly file, ex1.S, the symbols
asmFunction and asmVariable are made globally
visible through the use of the .global assembler directive and can
be accessed by any other source file.
