Node:ASM and C,
Next:OBJ and LIB,
Previous:ASM GPF,
Up:Converting
Q: Which register can I safely change in my assembly code that is
called from a C program?
Q: How come my program that calls assembly-language functions
crashes with a GPF, but only if I compile it with -O2?
Q: When I try to link my assembly modules with a C++ program,
the linker complains about the functions I wrote in assembly!
A: You can safely clobber EAX, ECX, EDX, FS and GS, as well as EFLAGS and the floating-point registers (including the FPU control and status words), but must save and restore all other registers at the end of your assembly function. Failure to preserve, e.g., ESI, EDI, EBX, ESP or DS in functions written in assembly can cause a C program linked with such functions to crash, since GCC expects those registers to be preserved across function calls. Special-purpose registers such as GDTR, LDTR, CR*, and DR*, although GCC and the DJGPP library don't use them, should probably not be touched at all, but if you do, it's a good idea to save and restore them.
Functions written in assembly or in C that are meant to be linked with
C++ programs should be declared extern "C"
in their
prototype, like this:
#ifdef __cplusplus extern "C" { #endif int my_assembly_func (int); #ifdef __cplusplus } #endif
This example shows how to produce a prototype that would work with both
C and C++ programs; it is usually placed in a .h
header file
that is meant to be #include
d in the C or C++ programs.
This extern "C"
declaration prevents the C++ compiler from
mangling the names of external functions according to the usual C++
rules. (The name-mangling is needed because C++ allows several
different functions to have the same name but different types of
arguments.)