Mail Archives: djgpp/1998/08/27/21:05:20
On 27 Aug 98 at 0:25, Siddiqui wrote:
> If I wrote several assembly routines in a single file using somthng like
> MASM,TASM or NASM :) how would I access these routines? Also how would I
> pass variables to these routines (ie: change the values of the registers)
There are two main ways to put assembly language routines into your
C or C++ programs. You can either write them inline in the C or C++
source code or you can write separate pure assembly language files
and link these in as if they were separate C or C++ files.
The inline approach requires you to use AT&T syntax for your
assembler. If you use external assembler modules you can use AT&T
syntax (with the built in assembler, GAS) or Intel syntax (with
NASM).
For more information on inline assembly and the AT&T syntax please
see Brennan's guide to inline assembler with djgpp:
http://brennan.home.ml.org/djgpp/djgpp_asm.html
and the relevant section of GCC's documentation:
info gcc "c ext" "extended asm"
For more information on external assembler routines using AT&T syntax
please see the document I wrote about this:
http://users.ox.ac.uk/~mert0407/asmfuncs.txt
This does not describe the AT&T format in any detail; Brennan's guide
(link above) is a good introduction to the AT&T format, and there is
much more information in the documentation for GAS:
info as machine i386
I can't give any links about NASM itself because I don't use it.
To answer your question, referring to external assembler routines,
you call them just like normal C functions. Write a prototype for
the routine in a header file and include that header in any source
that needs to call the function. Make sure the prototype is `extern
"C"' if you're using C++. Also note that normally the C compiler
adds an underline (`_') to the start of the function name to form its
symbol name, so you must put this at the start of the label in the
assembly language routine.
Re: passing and returning values, there are calling conventions you
must adhere to. These apply to external assembler routines; there
are different rules for inline assembly (see Brennan's guide for
information on that). Briefly, your external routines may clobber
(change the value of) EAX, ECX, EDX, FS and GS; it must preserve all
others. If it returns a non-floating point value it should leave it
in EAX, or EAX:EDX if it's a 64-bit value. Floating point values
are returned on the top of the FPU stack. Parameters to your
function are pushed onto the CPU stack in reverse order, so the first
parameter given is the last to be pushed. Note that the return
address is pushed next, so your parameters will start at ESP+4 on
entry (unless you're returning a struct, in which case the address
of the struct is passed as an implicit 0th parameter -- so your
regular parameters start at ESP+8). See the asmfuncs document above
for much more information on this, and some examples.
You shouldn't use registers to pass values between C functions and
your assembly language functions. In theory you could but the C
compiler might choose to destroy the value in the register before
calling your function. If you're calling your assembler routines
from other assembler routines then anything goes -- you can do pretty
much whatever you want, so long as you put it all back before calling
(or returning to) somebody else's code (i.e. gcc-compiled code or
anything in libc).
--
george DOT foot AT merton DOT oxford DOT ac DOT uk
- Raw text -