6.6.1 Using Assembly Language Modules With C/C++ Code
Interfacing C/C++ with assembly language functions is straightforward if you follow the calling conventions defined in Section 6.4, and the register conventions defined in Section 6.3. C/C++ code can access variables and call functions defined in assembly language, and assembly code can access C/C++ variables and call C/C++ functions.
Follow these guidelines to interface assembly language and C:
- You must preserve any dedicated registers modified by a function. Dedicated registers include:
- Save-on-entry registers (R4-R10)
- Stack pointer (SP or R1)
If the SP is used normally, it does not need to be explicitly preserved. In other words, the assembly function is free to use the stack as long as anything that is pushed onto the stack is popped back off before the function returns (thus preserving SP).
Any register that is not dedicated can be used freely without first being saved.
- Interrupt routines must save all the registers they use. For more information, see Section 6.7.
- When you call a C/C++ function from assembly language, load the designated registers with arguments and push the remaining arguments onto the stack as described in Section 6.4.1.
Remember that a function can alter any register not designated as being preserved without having to restore it. If the contents of any of these registers must be preserved across the call, you must explicitly save them.
- Functions must return values correctly according to their C/C++ declarations. Double values are returned in R12 and R13, and structures are returned as described in Step 2 of Section 6.4.1. Any other values are returned in R12.
- No assembly module should use the .cinit section for any purpose other than autoinitialization of global variables. The C/C++ startup routine assumes that the .cinit section consists entirely of initialization tables. Disrupting the tables by putting other information in .cinit can cause unpredictable results.
- The compiler assigns linknames to all external objects. Thus, when you write assembly language code, you must use the same linknames as those assigned by the compiler. See Section 5.15 for details.
- Any object or function declared in assembly language that is accessed or called from C/C++ must be declared with the .def or .global directive in the assembly language modifier. This declares the symbol as external and allows the linker to resolve references to it.
Likewise, to access a C/C++ function or object from assembly language, declare the C/C++ object with the .ref or .global directive in the assembly language module. This creates an undeclared external reference that the linker resolves.
- Any assembly routines that interface with MSP430x C programs are required to conform to the large-code model:
- Use CALLA/RETA instead of CALL/RET
- Use PUSHM.A/POPM.A to save and restore any used save-on-entry registers. The entire 20-bit register must be saved/restored.
- Manipulation of function pointers requires 20-bit operations (OP.A)
- If interfacing with C code compiled for the large-data model, data pointer manipulation must be performed using 20-bit operations (OP.A).