478 lines
9.8 KiB
HTML
478 lines
9.8 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>GCC Inline Assembly</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Linux Assembly HOWTO"
|
|
HREF="index.html"><LINK
|
|
REL="UP"
|
|
TITLE="Assemblers"
|
|
HREF="assemblers.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Assemblers"
|
|
HREF="assemblers.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="GAS"
|
|
HREF="gas.html"></HEAD
|
|
><BODY
|
|
CLASS="section"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Linux Assembly HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="assemblers.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
>Chapter 3. Assemblers</TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="gas.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="section"
|
|
><H1
|
|
CLASS="section"
|
|
><A
|
|
NAME="AEN263"
|
|
></A
|
|
>3.1. GCC Inline Assembly</H1
|
|
><P
|
|
> The well-known GNU C/C++ Compiler (GCC), an optimizing 32-bit compiler at the
|
|
heart of the GNU project, supports the x86 architecture quite well, and
|
|
includes the ability to insert assembly code in C programs, in such a way that
|
|
register allocation can be either specified or left to GCC. GCC works on most
|
|
available platforms, notably Linux, *BSD, VSTa, OS/2, *DOS, Win*, etc.
|
|
</P
|
|
><DIV
|
|
CLASS="section"
|
|
><H2
|
|
CLASS="section"
|
|
><A
|
|
NAME="AEN266"
|
|
></A
|
|
>3.1.1. Where to find GCC</H2
|
|
><P
|
|
> GCC home page is http://gcc.gnu.org.
|
|
</P
|
|
><P
|
|
> <A
|
|
NAME=""
|
|
></A
|
|
>
|
|
DOS port of GCC is called
|
|
DJGPP.
|
|
</P
|
|
><P
|
|
> There are two Win32 GCC ports:
|
|
cygwin and
|
|
mingw
|
|
</P
|
|
><P
|
|
> There is also an OS/2 port of GCC called EMX;
|
|
it works under DOS too,
|
|
and includes lots of unix-emulation library routines.
|
|
Look around the following site:
|
|
|
|
ftp://ftp.leo.org/pub/comp/os/os2/leo/gnu/emx+gcc/.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="section"
|
|
><H2
|
|
CLASS="section"
|
|
><A
|
|
NAME="AEN278"
|
|
></A
|
|
>3.1.2. Where to find docs for GCC Inline Asm</H2
|
|
><P
|
|
> The documentation of GCC includes documentation files in TeXinfo format.
|
|
You can compile them with TeX and print then result,
|
|
or convert them to <TT
|
|
CLASS="filename"
|
|
>.info</TT
|
|
>, and browse them with emacs,
|
|
or convert them to <TT
|
|
CLASS="filename"
|
|
>.html</TT
|
|
>, or nearly whatever you like;
|
|
convert (with the right tools) to whatever you like,
|
|
or just read as is. The <TT
|
|
CLASS="filename"
|
|
>.info</TT
|
|
> files
|
|
are generally found on any good installation for GCC.
|
|
</P
|
|
><P
|
|
> The right section to look for is <TT
|
|
CLASS="literal"
|
|
>C Extensions::Extended Asm::</TT
|
|
>
|
|
</P
|
|
><P
|
|
> Section <TT
|
|
CLASS="literal"
|
|
>Invoking GCC::Submodel Options::i386 Options::</TT
|
|
> might
|
|
help too. Particularly, it gives the i386 specific constraint names for
|
|
registers:
|
|
<TT
|
|
CLASS="literal"
|
|
>abcdSDB</TT
|
|
> correspond to
|
|
<TT
|
|
CLASS="literal"
|
|
>%eax</TT
|
|
>,
|
|
<TT
|
|
CLASS="literal"
|
|
>%ebx</TT
|
|
>,
|
|
<TT
|
|
CLASS="literal"
|
|
>%ecx</TT
|
|
>,
|
|
<TT
|
|
CLASS="literal"
|
|
>%edx</TT
|
|
>,
|
|
<TT
|
|
CLASS="literal"
|
|
>%esi</TT
|
|
>,
|
|
<TT
|
|
CLASS="literal"
|
|
>%edi</TT
|
|
>
|
|
and
|
|
<TT
|
|
CLASS="literal"
|
|
>%ebp</TT
|
|
>
|
|
respectively (no letter for <TT
|
|
CLASS="literal"
|
|
>%esp</TT
|
|
>).
|
|
</P
|
|
><P
|
|
> The DJGPP Games resource (not only for game hackers) had page specifically
|
|
about assembly, but it's down. Its data have nonetheless been recovered on the
|
|
DJGPP site, that contains a mine of other
|
|
useful information:
|
|
|
|
http://www.delorie.com/djgpp/doc/brennan/.
|
|
</P
|
|
><P
|
|
> GCC depends on GAS for assembling and follows its syntax (see below);
|
|
do mind that inline asm needs percent characters to be quoted,
|
|
they will be passed to GAS.
|
|
See the section about GAS below.
|
|
</P
|
|
><P
|
|
> Find <EM
|
|
>lots</EM
|
|
> of useful examples in the
|
|
<TT
|
|
CLASS="filename"
|
|
>linux/include/asm-i386/</TT
|
|
>
|
|
subdirectory of the sources for the Linux kernel.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="section"
|
|
><H2
|
|
CLASS="section"
|
|
><A
|
|
NAME="AEN304"
|
|
></A
|
|
>3.1.3. Invoking GCC to build proper inline assembly code</H2
|
|
><P
|
|
> Because assembly routines from the kernel headers (and most likely your own
|
|
headers, if you try making your assembly programming as clean as it is in the
|
|
linux kernel) are embedded in <TT
|
|
CLASS="function"
|
|
>extern inline</TT
|
|
> functions,
|
|
GCC must be invoked with the <TT
|
|
CLASS="option"
|
|
>-O</TT
|
|
> flag (or <TT
|
|
CLASS="option"
|
|
>-O2</TT
|
|
>,
|
|
<TT
|
|
CLASS="option"
|
|
>-O3</TT
|
|
>, etc), for these routines to be available. If not, your
|
|
code may compile, but not link properly, since it will be looking for
|
|
non-inlined <TT
|
|
CLASS="function"
|
|
>extern</TT
|
|
> functions in the libraries against
|
|
which your program is being linked! Another way is to link against libraries
|
|
that include fallback versions of the routines.
|
|
</P
|
|
><P
|
|
> Inline assembly can be disabled with <TT
|
|
CLASS="option"
|
|
>-fno-asm</TT
|
|
>, which will have
|
|
the compiler die when using extended inline asm syntax, or else generate calls
|
|
to an external function named <TT
|
|
CLASS="function"
|
|
>asm()</TT
|
|
> that the linker can't
|
|
resolve. To counter such flag, <TT
|
|
CLASS="option"
|
|
>-fasm</TT
|
|
> restores treatment of the
|
|
<TT
|
|
CLASS="literal"
|
|
>asm</TT
|
|
> keyword.
|
|
</P
|
|
><P
|
|
> More generally, good compile flags for GCC on the x86 platform are
|
|
</P
|
|
><P
|
|
> <B
|
|
CLASS="command"
|
|
>gcc -O2 -fomit-frame-pointer -W -Wall</B
|
|
>
|
|
</P
|
|
><P
|
|
> <TT
|
|
CLASS="option"
|
|
>-O2</TT
|
|
> is the good optimization level in most cases. Optimizing
|
|
besides it takes more time, and yields code that is much larger, but only a bit
|
|
faster; such over-optimization might be useful for tight loops only (if any),
|
|
which you may be doing in assembly anyway. In cases when you need really strong
|
|
compiler optimization for a few files, do consider using up to
|
|
<TT
|
|
CLASS="option"
|
|
>-O6</TT
|
|
>.
|
|
</P
|
|
><P
|
|
> <TT
|
|
CLASS="option"
|
|
>-fomit-frame-pointer</TT
|
|
> allows generated code to skip the stupid
|
|
frame pointer maintenance, which makes code smaller and faster, and frees a
|
|
register for further optimizations. It precludes the easy use of debugging tools
|
|
(<B
|
|
CLASS="command"
|
|
>gdb</B
|
|
>), but when you use these, you just don't care about size
|
|
and speed anymore anyway.
|
|
</P
|
|
><P
|
|
> <TT
|
|
CLASS="option"
|
|
>-W -Wall</TT
|
|
> enables all useful warnings and helps you to catch
|
|
obvious stupid errors.
|
|
</P
|
|
><P
|
|
> You can add some CPU-specific <TT
|
|
CLASS="option"
|
|
>-m486</TT
|
|
> or such flag so that GCC
|
|
will produce code that is more adapted to your precise CPU. Note that modern
|
|
GCC has <TT
|
|
CLASS="option"
|
|
>-mpentium</TT
|
|
> and such flags (and
|
|
PGCC has even more), whereas
|
|
GCC 2.7.x and older versions do not. A good choice of CPU-specific flags should
|
|
be in the Linux kernel. Check the TeXinfo documentation of your current GCC
|
|
installation for more.
|
|
</P
|
|
><P
|
|
> <TT
|
|
CLASS="option"
|
|
>-m386</TT
|
|
> will help optimize for size, hence also for speed on
|
|
computers whose memory is tight and/or loaded, since big programs cause swap,
|
|
which more than counters any "optimization" intended by the larger code. In
|
|
such settings, it might be useful to stop using C, and use instead a language
|
|
that favors code factorization, such as a functional language and/or FORTH,
|
|
and use a bytecode- or wordcode- based implementation.
|
|
</P
|
|
><P
|
|
> Note that you can vary code generation flags from file to file, so
|
|
performance-critical files will use maximum optimization, whereas other files
|
|
will be optimized for size.
|
|
</P
|
|
><P
|
|
> To optimize even more, option <TT
|
|
CLASS="option"
|
|
>-mregparm=2</TT
|
|
> and/or corresponding
|
|
function attribute might help, but might pose lots of problems when linking to
|
|
foreign code, <EM
|
|
>including <SPAN
|
|
CLASS="application"
|
|
>libc</SPAN
|
|
></EM
|
|
>.
|
|
There are ways to correctly declare foreign functions so the right call
|
|
sequences be generated, or you might want to recompile the foreign libraries
|
|
to use the same register-based calling convention...
|
|
</P
|
|
><P
|
|
> Note that you can add make these flags the default by editing file
|
|
<TT
|
|
CLASS="filename"
|
|
>/usr/lib/gcc-lib/i486-linux/2.7.2.3/specs</TT
|
|
> or wherever that
|
|
is on your system (better not add <TT
|
|
CLASS="option"
|
|
>-W -Wall</TT
|
|
> there, though). The
|
|
exact location of the GCC specs files on system can be found by
|
|
<B
|
|
CLASS="command"
|
|
>gcc -v</B
|
|
>.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="section"
|
|
><H2
|
|
CLASS="section"
|
|
><A
|
|
NAME="AEN343"
|
|
></A
|
|
>3.1.4. Macro support</H2
|
|
><P
|
|
> GCC allows (and requires) you to specify register constraints in your inline
|
|
assembly code, so the optimizer always know about it; thus, inline assembly
|
|
code is really made of patterns, not forcibly exact code.
|
|
</P
|
|
><P
|
|
> Thus, you can put your assembly into CPP macros, and inline C functions, so
|
|
anyone can use it in as any C function/macro. Inline functions resemble macros
|
|
very much, but are sometimes cleaner to use. Beware that in all those cases,
|
|
code will be duplicated, so only local labels (of <TT
|
|
CLASS="literal"
|
|
>1:</TT
|
|
> style)
|
|
should be defined in that asm code. However, a macro would allow the name for
|
|
a non local defined label to be passed as a parameter (or else, you should use
|
|
additional meta-programming methods). Also, note that propagating inline asm
|
|
code will spread potential bugs in them; so watch out doubly for register
|
|
constraints in such inline asm code.
|
|
</P
|
|
><P
|
|
> Lastly, the C language itself may be considered as a good abstraction to
|
|
assembly programming, which relieves you from most of the trouble of assembling.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="assemblers.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="gas.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Assemblers</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="assemblers.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>GAS</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |