Mail Archives: djgpp/1998/08/10/03:55:45
On 9 Aug 98 at 20:45, GAMMELJL AT SLU DOT EDU wrote:
> When one compiles codename.cc with the -S -O2 switches, one gets
> codename.cc in assembly language (codename.s). codename.s is easily
> readable and can be edited with the DOS editor, a very nice feature.
> When codename.cc contains a subroutine named sub (which may be used in
> many programs) one sees that even though the optimizing switch -O2 has been
> used there are small changes one can make in the assembly language for
> sub (whose location in codename.s is clearly marked) which make the
> executable a.exe produced by gxx codename.s run a little faster.
> Now, one would like to use the modified assembly language for sub
> in all future programs. That can be done in this way: Compile any
> program.cc with gxx program.cc -S -O2, find sub in program.s, and
> replace it with the modified assembly language for sub (one uses the
> DOS editor to do that). Then gxx program.s. a.exe is a little faster.
Be careful here. If your optimisations require looking at the code
for the function and the code for calls to the function, and (for
example) preserving extra registers inside the function, or failing
to preserve some registers that the calling code doesn't need
preserved, then your optimisations aren't really safe, and the
problems they cause will be hard to debug.
> But, it would be preferable to put the modified assembly language
> for sub back in program.cc to start with (sub is contained in an include
> file include file file.h so the programs requiring sub have #include
> "file.h". One wants to put the assembly language in sub in file.h.
> Here is the problem: the assembly language in sub.s is not exactly
> like the AT&T assembly language conventions. There are no " ;" \
> on each line; there are only % symbols rather than %%; one has to
> be cautious about the line numbers. It is extremely tedious to take
> the .s assembly language and translate it back to AT&T conventions and
> it is easy to make a mistake.
You're wrong here; the code in a .S file is real AT&T-style
assembler. It's just not in quite the same style as gcc's inline
assembler.
When you write the statement `asm (".....");', gcc inserts the given
string into the assembly language output verbatim. This is the
`basic' style of inline assembler; registers only have one % prefix
(just like in .S files), and there are no inputs and outputs. If you
want to write more than one instruction you must separate them with
semicolons (`;') or line breaks. Since "....." obeys the rules of C
strings you can use `\n' to break lines. The `\t' people sometimes
put in results in more readable code in the .S file; it just indents
the inlined code.
The double % signs used in `extended' inline assembly are really just
single % signs that have been escaped by another % sign. GCC needs
to read through the code in extended inline assembly in order to
replace certain pseudoregisters with real values, e.g. `%0', `%1',
etc. This is how automatically assigned input and output registers
work; it replaces these pseudo regsiters with its chosen x86
registers as it copies the code into the .S file.
> What one would really like is to hand the .s code for sub back
> to file.h with a compiler directive #replace subs assembly language
> with the assembly language found in the file modifiedsub, say
> #replace subasm modifiedsubasm
> Maybe such a thing already exists and I just don't know about it.
> I know it can be done: if I can do it with the DOS editor and compiler
> can do it! ("and" in the line above ="the"). If the compiler can't
> already do it, it would be a very small step forward if it were made
> to. It is really only a matter of editing codename.s after it is
> produced: I could almost do it myself if I knew what the hidden
> end of line symbol in codename.s is, but the writers of the compiler
> would know all of the tricks necessary to do it (how to read the
> text file codename.s and replace subasm with modifiedsubasm.
I don't think that would be a good idea; what if the code generated
by the compiler changed?
In any case, you can just write the routine in assembly language (and
comment out the C version), like this:
/* Prototype */
#ifdef __cplusplus
extern "C"
#endif
int add (int, int);
#ifndef USE_ASM
/* C version */
int add (int a, int b)
{
return a+b;
}
#else
/* assembly language version */
asm ("\n"
".global _add\n" /* This symbol should be exported */
" .p2align 2\n" /* Alignment speeds up calls */
"_add:\n" /* Use a label to mark the entry point */
" movl 4(%esp), %eax\n" /* Get first parameter in EAX */
" addl 8(%esp), %eax\n" /* Add on second parameter */
" ret\n" /* Return (integer result is in EAX) */
);
#endif
Or you could just move it into a .S file of its own, of course.
Note that since you're writing C++ code you'll need to prototype
with `extern "C"', because the name of the function in the assembly
language code is not mangled. I didn't include any debugging
information in this function, and I also didn't use a frame pointer,
but it's just an example.
If you want more information about writing entire functions in
assembly language (specifically in separate .S files, but it also
works as above) please see:
http://users.ox.ac.uk/~mert0407/asmfuncs.txt
(which I've just updated with more complete and accurate information
on parameters and return values).
--
george DOT foot AT merton DOT oxford DOT ac DOT uk
- Raw text -