COHERENT manpages

This page displays the COHERENT manpage for as [i80386 assembler].

List of available manpages
Index


as -- Command

i80386 assembler
as [-o outfile] [-bfglnpwxX] infile

The 80386 version of as, the COHERENT assembler, assembles programs written
in  any of  several  different dialects  of assembly  language into  object
modules in  COFF format, which  can be linked  with objects written  by the
COHERENT C  compiler.  This  version of  as contains numerous  features not
available with the COHERENT 286 assembler:

-> It  serves as  a  flexible base  for  writing programs  in native  80386
   assembly language.

-> It  assembles programs  written in  older  flavors of  COHERENT assembly
   language.

-> It assembles programs written in UNIX assembly language.

-> Unlike the old COHERENT assembler and the UNIX assembler, 80386 as comes
   with full macro faculities.

-> It  is  also designed  to  detect  many of  the  common  errors made  by
   assembly-language programmers.

The COHERENT  system also includes  the command asfix,  which updates files
written in  the COHERENT 286 assembler.  asfix  changes local and character
symbols to the new format.

Invoking the Assembler

as permits file names and options to be interspersed upon the command line.
It recognizes the following command-line options:

-Dname=string
     Initialize string variable name to string.  For example, the option

         -Dname=some_string

     is equivalent to:

         name    .define some_string

-Ename=value
     Initialize variable name to value.  For example, the option

         -Ename=17

     is equivalent to:

         name    .equ    17

-a   Set alignment for data objects.  For example, when this option is used
     the express

         .long 5

     is  automatically  aligned  to  a  four-byte  boundary,  but  is  left
     unaligned without it.

-b   Reverse  bracket sense;  that is,  use () for  expressions and  [] for
     code.  For example:

          movl $[2 * 5], (%eax)/ without -b
          movl $(2 * 5), [%eax]/ with -b

-f   Reverse the order of the operands, from UNIX-assembler form to that of
     the Intel documentation or the 80286 version of as.

-g   Make undefined symbols .globl.

-l   Generate an output listing.

-n   This option turns off the as  mechanism for handling bugs in the 80386
     chip.  as  tries to  cope with  known 80386 bugs  by changing  code at
     appropriate points  in its output.   If these changes  create problems
     with your code, you can turn off the as bug-handler mechanism by using
     the -n option to as.

-o outfile.o
     Write the output into outfile.o.   Note that the suffix .o must appear
     in the  output file's name, or  the assembler will exit  with an error
     message.  The default output file is infile.o.

-p   Don't use `%' on register names; e.g., use ax, not %ax.

-Q   Quiet: Suppress all error messages,  no matter how awful an error they
     indicate.

-w   Disable warning messages.

-x   Remove all non-global symbols from the common symbol output.

-X   Remove all non-global symbols  starting with .L from the common symbol
     output.

as reads the environmental variables ASHEAD and ASTAIL and appends them to,
respectively, the  beginning and the  end of its command  line.  By setting
these variables,  you can ensure that as always  executes with the switches
that you want.  For example, to  ensure that as always executes with the -g
switch set, insert the following into your .profile:

    export ASHEAD=-g

Lexography

A symbol consists  of from one to 256 characters.   The assembler defines a
character as being  an alphabetic character, question mark, period, percent
sign, or underscore.  Xyz, .20, and hi_there are legal symbols; whereas 85i
is not.

Like C, the as assembly language is case sensitive.

Local  symbols begin  with  a question  mark.  These  are recognizable  (or
visible) only between nonlocal symbols.  For example:

/    ?loop invisible here
abc  mov  $10, %cx
?loop     add            $1, %bx/ ?loop visible here
     jcxz xyz
     jmp  ?loop
xyz:
/    ?loop invisible here

An octal  number is defined  just as in  the C language: it  consists of an
initial 0 plus  two other numerals between 0 and  7.  For example, 077 is a
legal octal number.

A  hexadecimal number  consists  of an  initial  0x or  0X  plus two  other
numerals: 0 through 9, a through  f, or A through F.  For example, 0x0F and
0Xa3 are legal hexadecimal numbers.

A binary  number consists of an  intial 0b or 0B  followed by an indefinite
number 0's and 1's.  For example, 0b01001010 is a legal binary number.

A  decimal number  begins  with a  numeral  other than  0,  followed by  an
indefinite number of numerals between 0 and 9.  For example, 109 is a legal
decimal number.

A floating-point number begins is a string of numerals, 0 through 9, with a
period or  e within or  at the end  of it.  It  is like a  C floating-point
number, except  that it  cannot begin  with a period  because a  symbol may
begin with  a period.  For  example, 123.456, 123456., and  17e26 are legal
floating-point numbers, but .123456 is not.

A  character  constant  is  enclosed  between  apostrophes, as  in  C.   as
recognizes  the same  escape sequences  as  C.  See  the Lexicon  article C
language for a table of these constants.

String  constants  are  enclosed  between  quotation  marks, as  in  the  C
language, and use the same escape  sequences as C.  See the Lexicon article
C language for a table of these sequences.

Pseudo-Opcodes

as recognizes  a rich set of pseudo-opcodes.  These  are not true assembly-
language opcodes,  but are interpreted by the  assembler; they are designed
to  help  make your  life  easier.  The  following  briefly summarizes  the
pseudo-opcodes.

.16............16-bit mode
.2byte.........Make unaligned short variables
.32............32-bit mode
.4byte.........Make unaligned long variables
.align.........Increment location counter to two- or four-byte aligned spot
.alignoff......Turn alignment off
.alignon.......Turn alignment on
.blkb..........Set tag in .data
.bracketnorm...Normal bracket sense -- see -b option
.brcketrev.....Reverse bracket sense -- see -b option
.bss...........Set tag in .bss
.bssd..........Set tag in .bss
.byte..........Make byte variables
.comm..........Set label as common
.data..........Change segment to .data
.def...........Reserved to set auxiliary symbol entries in a later release
.define........Define string constant
.dim...........Reserved to set auxiliary symbol entries in a later release
.double........Make double variables
.eject.........Force a page break
.else..........Connected to .if
.endef.........Reserved to set auxiliary symbol entries in a later release
.endi..........End .if
.endm..........End .macro definition
.endw..........End .while
.equ...........Define numeric constant
.errataoff.....Turn off chip errata fixes
.errataon......Turn on chip errata fixes
.even..........Increment location counter to byte-aligned spot
.fail..........Print error message
.file..........Reserved to set auxiliary symbol entries in a later release
.float.........Make float variables
.globl.........Declare names as visible to linker
.ident..........ident string
.if............Compile-time conditional
.include.......Include a file
.intelorder....Intel operand order -- see -f option
.lcomm.........Set name up as common
.line..........Reserved to set auxiliary symbol entries in a later release
.list..........Turn on listing (assumes -l option)
.llen..........Set print line length
.ln............Reserved to set auxiliary symbol entries in a later release
.long..........Make long variables
.macro.........Define a macro name
.mexit.........Exit current macro expansion
.mlist.........Toggle listing of macro expansion
.nolist........Turn off listing (assumes -l option)
.nopage........Turn off page breaks and titles
.number........Convert a string to a number.
.org...........Change location counter
.page..........Turn on page breaks and titles
.plen..........Set page length
.prvd..........Change segment to .data
.prvi..........Change segment to .text
.scl...........Reserved to set auxiliary symbol entries in a later release
.set...........Makes name equal to expr
.shift.........Shift macro parameters
.shrd..........Change segment to .data
.shri..........Change segment to .text
.size..........Reserved to set auxiliary symbol entries in a later release
.string........Convert a floating-point expression to a string
.strn..........Change segment to .data
.tag...........Reserved to set auxiliary symbol entries in a later release
.text..........Change segment to .text
.ttl...........Set page titles
.type..........Reserved to set auxiliary symbol entries in a later release
.undef.........Free string, numeric constant, or opcode
.unixorder.....Return normal order of operands; undoes .intelorder
.val...........Reserved to set auxiliary symbol entries in a later release
.value.........Make short variables
.version.......Comment string
.warn..........Print a warning message
.warnoff.......Turn off warning messages
.warnon........Turn on warning messages
.while.........Compile-time loop control
.word..........Make short variables
.zero..........Create zero-filled memory

Each pseudo-opcode is described in the following sections.

Input Format

An  assembly-language  program  consists of  a  series  of  lines with  the
following format:

[#][label]  [opcode]    [operands]  [/ comment]

The optional `#'  at the beginning of the line  tells as not to replace any
.define symbols  within the line.   (These are described  below.) Normally,
the assembler replaces all .define symbols  in a line before it parses that
line.   Without this  option, a  series of .defines  could lead  to awkward
results.

For example, the code

#%ecx   .define xx
#xx .define (%ecx)
    mov $3, %ecx

results in:

    mov $3, (%ecx)

Like the  C compiler, as will  not go into an infinite  loop if two .define
statements mirror each other.

A comment begins  with a slash `/' and may  include the entire line.  Blank
lines are also legal.

Extra operands are not assumed to be comments.  This is to tighten up error
checking  for  the  convenience  of  new  and  part-time  assembly-language
programmers.

Expression Format

The as macro assembler has mostly  the same operators and precedence as the
C preprocessor.   The exceptions are ?:, &&, ||,  :, and `,' (which
are missing), `/' (which is spelled .div), and `%' (which is spelled .rem).

In  addition,  the  macro  assembler  includes  the  following  directives:
.defined,  .sizeof,  .segment, .parmct,  .location,  .string, .number,  and
.float.

Expression bracketing  is normally done  by [], because  () is used  by the
operand format.  This may be reversed by the -b option, described above.

The unary operators have the following priority:

.float .number .stringConversion
.defined .sizeof
.location .segmentInquiry
-                 Negation
!                 Logical negation

The binary operators have the following priority:

[]
* .div .rem       Multiply, divide, remainder
+ -               Add, subtract.
>> << Left shift , right shift
< > <= >= == !=Comparison
&amp;             AND
^                 Exclusive OR
|                 OR
#                 Repeat

Most binary operators should be familiar to C programmers; the exception is
the #, which repeats an instruction N times.  For example, the expression

    .byte   5 # 3

produces five copies of byte 3, whereas the expression

    .long   7 # 4

produces seven  copies of the  long `4'.  Note  that this operator  has the
lowest precedence of all binary operators.

You can  use an expression  wherever you can  use a number.   This includes
address displacements, constants,  and .if and .while statements.  Integers
are internally 32 bits, floats are internally C doubles.

Like C, comparison operators return one for true and zero for false.

In addition, as provides string operators.   Like C, the first element of a
string is indexed as zero.  Unlike  C, however, attempts to access past the
end of a string gives all zeroes.  The following summarizes the as suite of
string operators:

string + string
     Concatenate two strings.  For example, "12" + "34" yields "1234".

string [ expr1, expr2 ]
     Address a substring  from expr1 to expr2.  For example, "1234567"[1,3]
     yields "234"; and "123"[1,10] yields "23".

string [ expr ]
     Address a substring  from expr to the end of  the string.  For example
     "1234567"[5] yields "67".

.string expr
     Convert a  numeric expression to  a string.  For  example, .string 123
     gives "123".

.string float
     Convert a floating-point expression to a string.  For example, .string
     0.5 * 3 gives "1.5"

.float string
     Convert a string to a floating-point number.

.float expr
     Convert a numeric expression to a floating-point number.

.number string
     Convert a string to a number.

.number float
     Convert a floating-point number to a number.

.string ( expr )
     Return character at position  expr as a number.  For example, "123"(1)
     gives two.

string1 @ string2
     Return  the position  at  which string2  begins  within string1.   For
     example,  "12345"  @ "23"  returns  one;  and "123"  @  "jj" gives  -1
     (because ``jj'' does not appear within ``123'').

The unary operator : creates a  label equal to the current location.  It is
generally not needed.  For example, the expression

    connected   .long 5

builds an  aligned long,  initializes it  to five, and  gives it  the label
connected. However, the expression

    unconnected:    .long 5

builds  the  label unconnected  at  the current  location,  then builds  an
aligned long with  a value of five.  Note that  the label connected will be
on the five,  whereas the label unconnected may be  somewhere else if there
was alignment.  For example, the expression

        .align  4
    lab1: lab2: lab3: .long 5

puts lab1, lab2, and lab3 on the long because it is already aligned.

Macros and Conditional Compilation

The as directive .macro lets you declare a macro that you can use through a
program.  The directive .endm marks the end of a macro declaration.

A macro has the following form:

name    .macro  params
    body of macro
    .endm

The following example creates and uses the macro store:

store     .macro         xy,xz/ declare "store" with two parms: xy and xz
     movl xy,%ecx
     movl %ecx,(%eax)
     movl xz,%ecx
     movl %ecx,4(%eax)
     .endm               / end of macro

     store               5,10/ moves 5 and 10 to where %eax points.

Macros can  contain .if statements, and can even  define other macros.  For
example:

def  .macro              .name, to/ macro for defining other macros
name .macro
     movl from, to
     .endm
     .endm

     def  frog, %eax, %ebx/ define the macro frog
     frog                / movel%eax, %ebx

as increments a count every time  you expand any macro, and associates that
number with the macro.  When the  keyword .macno is used within a macro, as
translates it  into that  number.  Thus, .macno  is a unique  number within
each macro expansion.  This allows the generation of unique labels internal
to macros.  For example:

stradd    .macro         str
     .data
L\.macno  .byte str, 0   / create a data item
     .text
     movl L\.macno, %eax / put its address into %eax
     .endm

L\.macno becomes  something like L51.   Note that a `\'  before any defined
symbol or macro name vanishes in the expansion pass.

To permit macros with indefinite parameter counts, the assembler offers the
reserved word .parmct and the  command .shift.  The former holds the number
of parameters passed  to a macro, and the latter  shifts the parameters one
position to the left.  For example:

kall .macro              fun, parm
     .while .parmct > 1/ while more than one parm remains
     push parm
     .shift              / parm 3 becomes parm 2, parm 4 parm 3 etc
     call fun
     .endm

The operators  .if, .else, and .endi allow a  program to implement compile-
time decisions.   These may be inside  or outside of macros.   When a macro
exits, the assembler automatically  closes  all .if statments that had been
started within it.  For example:

defy .macro
     .if .defined y      / if y has been defined true
     .mexit              / exits closing any if statements
     .else
y    .equ 1              / define y as 1
/ For UNIX compatibility
/    .set y, 1
/ produces the same result
     .endm

When used  with a label,  the operator .defined  is true if  that label had
been defined  in this pass.   If the label  is defined later,  .defined can
still  be  used with  it,  but causes  a  phase error,  as  occurs in  some
assemblers.

The operator .fail permits the flagging of errors.  For example:

    .if ! .defined y
    .fail   y is not defined
    .endi

The operator .include permits the inclusion of files.  For example:

    .include    somefile.h

Undefining Symbols or Opcodes

as  Some software  (e.g.,  the GNU  C  compiler) requires  that opcodes  be
recognized on  column one  and that opcodes  be replacable by  macros.  The
command .undef un-defines all macros and opcodes.  Once you have un-defined
an identifier, you  can re-use it to name a  macro or other data item.  For
example,  to use  mov  (which names  an  opcode) to  name a  macro, do  the
following:

    .undef  mov
mov .macro  foo, bar
    movl    foo, bar
    .endm

Data-Definition Operators

The following describes the data-definition operators that as supports.

.byte expr
     Define expr as an array of  single bytes.  expr can take any number of
     forms, as shown by the following examples:

          .byte               5, 2/ defines 2 bytes 0x05 and 0x02
          .byte               "Hello World", 0/ a zero-terminated Hello World
          .byte               10 # 1/ 10 repetitions of 0x01

.word expr
     Define expr as a word, that is, as a two-byte integer.  For example:

          .word               .sizeof xx/ a short the size of xx
          .word               50 * 50/ a short of 100
     / For UNIX compatability
     /    .value              50 * 10
     / produces the same result.

.long   expr
     Define expr as a long (four-byte) integer.  For example:

          .long               10/ a long of 10

.comm name, length
     Define a common variable named  name, that is length bytes long.  (See
     the  entry for  .lcomm, below,  for a discussion  of what  segment the
     variable is  stored.) If name is linked with  another module that also
     declares name  but sets it  to another length, the  linker creates one
     such variable and gives it the greater length of the two.

     The linker deduces the alignment of a common variable from its length:
     if the  length of a  common is divisible  by four, it is  aligned on a
     four-byte boundary; if it is divisible by two, it is aligned on a two-
     byte boundary.  Otherwise, it  is assumed to be unaligned.  The linker
     supports  only three  classes of  alignment: four-byte,  two-byte, and
     unaligned.

     A common  variable is aligned  according to its  most strongly aligned
     contributor.  For example, if one module contributes a common variable
     named xyz  whose length is four bytes, and  another contributes an xyz
     whose length  is five bytes,  the resulting xyz  is given a  length of
     eight bytes to satisfy the  length requirement (at least five) and the
     alignment requirement (four-byte boundary).

     After the  first linker pass,  all common variables are  placed at the
     end of  the .bss segment: first  the four-byte-aligned variables, then
     the two-byte-aligned, then the unaligned.

     By  default, as  does not  align its  data objects.   The command-line
     option -a instructs as to align all data objects automatically.

.lcomm label, length
     Same as comm, described above.

     Please note  that on a  COFF-based system, it  is not possible  to put
     common data  into the  .data section,  even though the  UNIX assembler
     documentation  claims that  .comm does  this.   Both .comm  and .lcomm
     place data into the .bss.

     The problem  is that COFF format for common  variables leaves no place
     for  information  about   alignment  or  segment.   This  creates  two
     problems.  First, the  lack of information about alignment forces COFF
     to  adopt the  complex  strategy of  deducing  alignment from  length.
     Second, the  lack of information  about segment compels  COFF to store
     all common variables in one segment, .bss being chosen.

.float expr
     Define expr as a single-precision floating-point number.  For example:

          .float              1.5/ a float of 1.5

.double expr
     Define expr as a double-precision floating-point number.  For example:

          .double 3.0 * 0.5   / a double of 1.5

Resetting the Location Counter

The instructions .org and .align reset the location counter.  For example:

     .org .+5            / Location counter to here plus 5
     .org                / Location counter to top of current section
     .align              2/ Up to nearest two-byte boundary

The pseudo-opcodes .alignon and .alignoff respectively turn aligning on and
off.

As noted above,  the command-line option -a instructs as  to align all data
objects automatically.

The instructions  .text, .data, and .bss reset the  location counter to the
corresponding  sections.  Instructions  are  placed in  the .text  section,
initialized  data  in the  .data  section,  and the  .bss  is reserved  for
unitialized data.  Placing information into the .bss results in an error.

Dynamic Linking

The Intel  Binary Compatibility Standard dictates the  way that as computes
addresses, to permit dynamic linking of objects.

In object  files, all .data addresses must follow  all .text addresses, and
all  .bss address  must follow  all .data  addresses.  This  allows dynamic
linking of  object files, in which  the object file is  mapped, not read in
pieces.

In the as  assembly language, .data and .text addresses  are started from 0
for each module.  At the end of assembly, during the output phase, as fixes
these addresses to make .data follow .text, and so on.

For example, if you have a conditional like

    .if some_data_address > 0x300

as calculates the  address for the .if statement from  the beginning of its
segment;  and the  address is  only  corrected in  the final  output.  Such
statements may appear to be working incorrectly.

Listing Commands

as  prints a  listing if  you use  its -l  option.  The  following commands
modify the form of this listing.

.ttl string
     Print string as the title to the command page.  For example:

         .ttl    This is a page title

     If you do  not use this command, the assembler  uses the file name for
     the title.  The first .ttl encountered  in the assembly pass 0 is used
     to  set the  first title.   Subsequent .ttl  commands reset  the title
     before printing.

.nopage
     Turn off page breaks and titles.

.page
     Turn on page breaks and titles.

.eject
     Force a page break.

.nolist
     Turn off the listing.

.list
     Turn the listing back on.

.mlist off
     Turn off the listing of macro expansions.

.mlist on
     Turn on the listing of macro expansions.

Addressing Modes

as recognizes two modes of addressing:  16-bit mode and 32-bit mode. In 16-
bit mode, the  address type and operand mode default  to 16 bits; in 32-bit
mode they default to 32 bits.  For example:

     .16
     movw %ax, (%si)# Is generated without escapes.
     movl %eax, (%esi)# Has two escapes, address and operand
     .32
     movw %ax, (%si)# Has two escapes, address and operand
     movl %eax, (%esi)# Is generated without escapes.

In 16-bit mode, the 16-bit addressing  forms in table 17-2 of the Intel 386
Programmer's  Manual are  generated where they  fit; otherwise,  an address
escape is built and the 32-bit  forms in tables 17-3 and 17-4 are used.  In
32 bit mode, this is reversed.

as uses the following grammar in its addressing modes:

Eight-bit registers

         r8  : %al | %cl | %dl | %bl | %ah | %ch | %dh | %bh;

16-bit registers

         r16 : %ax | %cx | %dx | %bx | %sp | %bp | %si | %di;

32-bit registers

         r32 : %eax | %ecx | %edx | %ebx | %esp | %ebp | %esi | %edi;

Segment registers

         sreg : %es | %cs | %ss | %ds | %fs | %gs;

Control registers

         ctlreg : %cr0 | %cr2 | %cr3;

Debug registers

         dbreg : %dr0 | %dr1 | %dr2 | %dr3 | %dr6 | %dr7;

Test registers

         testreg : %tr6 | %tr7;

m16  These addresses can have a segment prefix:

         m16 : m16b | sreg ':' m16b;

m32  These addresses can have a segment prefix:

         m32 : m32b | sreg ':' m32b;

rm16 These addresses can have a segment prefix or may be r16:

         rm16 : rm16b | sreg ':' rm16b;

rm32 These addresses can have a segment prefix or may be r32:

         rm32 : r32 | rm32b | sreg ':' rm32b;

rm8  These addresses can be rm32, rm16, or r8:

         rm8  : r8 | rm16b | sreg ':' rm16b | rm32b | sreg ':' rm32b;

rm16b

         displacement | (vx, vy) | displacement(vx, vy) |
             displacement(vw) | (vz);
         vx : %bx | %si;
         vy : %si | %di;
         vz : %si | %di | %bx;

rm32b

         (va) | displacement(vb) | (, vb, scale) | (vb, scale)
              | displacement(vb, scale) | (vb, vb, scale)
              | displacement(vb, vb, scale);
         va : %eax | %ecx | %edx | %ebx | %esi | %edi;
         vb : %eax | %ecx | %edx | %ebx | %ebp | %esi | %edi;
         vb : %eax | %ecx | %edx | %ebx | %ebp | %esp | %esi | %edi;
         scale : 0 | 1 | 2 | 4 | 8;

mem32
     A 32-bit memory address.

mem16
     A 16-bit memory address.

reli Expand to eight-, 16-, or 32-bit relative addresses.

rel8 Eight-bit relative addresses.

rel16
     Sixteen- or 32-bit relative addresses.

Using as To Create Debug Information

Some UNIX languages, such as gcc and gc++, produce assembly language rather
than  object  code.   The following  documents  how  to  use  as with  such
compilers.   Note  that  error checking  is  minimal,  and  that bad  debug
information can  corrupt the generated  COFF output.  This  section must be
read with  a listing of  the header file  coff.h for reference;  or see the
Lexicon article coff.h.

The compiler  starts with type and  line information in a  format much like
that of the desired COFF output  files.  It must break this down into lines
to  ship through  the assembler,  and the assembler  then must  rebuild the
information into COFF format for output.

.file filename
     This connects  the object file to the original  source file.  If used,
     this should be the first statement  in the file.  It produces a SYMENT
     of n_sclass = C_FILE and an AUXENT with ae_fname = filename.

.def symbolName
     This  instruction initializes  SYMENT  with n_name  = symbolName.   If
     there  is a  symbol by  that name on  the assembler's  internal symbol
     table, it is marked to prevent  output to the symbol table.  Any RELOC
     references point to this table  entry, so its n_value must be correct.
     Because we assume  that code of this kind is  result of a compiler, we
     assume  it is  correct.  The  following commands  up to  and including
     .endef refer to this SYMENT.

.type number
     This sets this SYMENT's n_type number. If number indicates a function,
     DT_FCN, a LINENO record is built pointing at this SYMENT.

.val [symbol] [number]
     This sets this SYMENT's n_value. If it is a symbol, it sets n_scnum to
     the symbol's section number.

.scl number
     This sets this SYMENT's n_sclass to number.

.dim number [, number [, number [, number]]]
     This sets  up to  four entries in  an AUXENT's ae_dimen.  It describes
     multidimensioned  arrays to  COFF.   This command  supports only  four
     dimensions because  the COFF  specifications are reliable  only though
     four dimensions.

.size n
     This sets this AUXENT ae_size to n.

.tag name
     This scans  backwards on the SYMENTs for a  matching n_name. It points
     this ae_tagndx to that name's  symbol number and that ae_endndx to the
     next symbol number.

     A  good example  is a  struct: It  would start with  a SYMENT  of type
     T_STRUCT, then  then have SYMENTs for its members.   At the end, there
     would be  a C_EOS (end of  structure) with a tag that  gets us back to
     the symbol's name.  .tag connects the forward and backward pointers.

.line n
     This sets the AUXENT's ae_lnno to n.

.endef
     This marks  the end of  a SYMENT started  by .def. If  the n_sclass ==
     C_EFCN  (end  of  function),  it  builds  the functions  ae_fsize  and
     ae_endndx and  does not output this SYMENT. If  any AUXENT fields were
     set, an AUXENT record follows this SYMENT.

.ln number
     This builds a  LINENO record with l_lnno = n  and l_addr.l_paddr = the
     current location.

Instructions

In matching instructions, as first looks up the name of the instruction.  A
number  of actual  instructions will  match that  name.  For  example, btsw
matches 0xab and 0x0fab /5, and  bts matches anything that matches btsw and
btsl.

as attempts to match operands to the instruction until a form is found that
will accept  all the  operands.  If  no form matches  all the  operands, as
prints the error message

    Illegal combination of opcode and operands

The assembler  at that point cannot  say which operand is  wrong because of
the nature of the 80386 instruction set.

If you  see a great number  of these messages, as's  command-line option -f
may be  in the wrong sense:  although the opcode is  valid and the operands
are valid,  there is no  form of this  opcode that takes  these operands in
this order.

as  first attempts  to match  opcodes that do  not require  an operand-mode
escape: that is, in 80386  mode it attempts to match long-mode instructions
first, then short-mode instructions.

Register Usage

The  COHERENT C  compiler uses  the following  save/restore sequence  for a
function, to set the frame  pointer when the function contains no automatic
variables:

    push    %ebp
    movl    %ebp, %esp

If n bytes of autos are required, then it uses the following sequence:

    enter   $n, $0

It then executes the code

    push    %esi
    push    %edi
    push    %ebx

to preserve register variables  as required: they are not saved/restored if
the function  does not touch them.   (This is why they  are saved after the
frame adjust, not before).  To restore register variables, it executes

    pop %ebx
    pop %edi
    pop %esi

as required, followed by

    leave
    ret

Routines  written in  assembly language must  preserve registers  ebp, esi,
edi, and ebx; they may overwrite eax, ecx, and edx.

Absolute Symbols

as can create what COFF calls ``absolute symbols.'' For example

    .globl  x
x   .equ    10
x   .equ    x * x   / The last value of x in the module

leaves on the  symbol table an absolute symbol for  x of 100.  For internal
reason, the .globl must preceed any .equ.

Opcodes

The following gives a table of  the opcodes recognized by as. Note that the
opcode is  sometimes followed by  a slash and  a number, or  a letter.  For
example,

    D0 /4   salb    con1, rm8

means opcode  is 0xD0 place  4 in the  register/opcode field of  the modr/m
byte.

    58 +r   popl    r32

means add the register number to 0x58.

Opcode    Instruction         OperandsDescription

37        aaa                 Adjust after addition
D5 0A     aad                 Adjust AX before division
D4 0A     aam                 Adjust AX after multiply
3F        aas                 Adjust AL after subtraction

          adc                 Add with carry
83 /2     adcl      imm8s,rm32
83 /2     adcw      imm8s,rm16
14        adcb      imm8,al
15        adcw      imm16,ax
15        adcl      imm32,eax
15        adcl      imm32
80 /2     adcb      imm8,rm8
81 /2     adcw      imm16,rm16
81 /2     adcl      imm32,rm32
12 /r     adcb      rm8,r8
13 /r     adcw      rm16,r16
13 /r     adcl      rm32,r32
10 /r     adcb      r8,rm8
11 /r     adcw      r16,rm16
11 /r     adcl      r32,rm32

          add                 Add
83 /0     addl      imm8s,rm32
83 /0     addw      imm8s,rm16
04        addb      imm8,al
05        addw      imm16,ax
05        addl      imm32,eax
05        addl      imm32
80 /0     addb      imm8,rm8
81 /0     addw      imm16,rm16
81 /0     addl      imm32,rm32
02 /r     addb      rm8,r8
03 /r     addw      rm16,r16
03 /r     addl      rm32,r32
00 /r     addb      r8,rm8
01 /r     addw      r16,rm16
01 /r     addl      r32,rm32

          and                 Logical AND
83 /4     andl      imm8s,rm32
83 /4     andw      imm8s,rm16
24        andb      imm8,al
25        andw      imm16,ax
25        andl      imm32,eax
25        andl      imm32
80 /4     andb      imm8,rm8
81 /4     andw      imm16,rm16
81 /4     andl      imm32,rm32
22 /r     andb      rm8,r8
23 /r     andw      rm16,r16
23 /r     andl      rm32,r32
20 /r     andb      r8,rm8
21 /r     andw      r16,rm16
21 /r     andl      r32,rm32

63 /r     arpl      r16,rm16  Adjust RPL field of selector

          bound               Check if register is within bounds
62 /r     boundw    m16,r16
62 /r     boundl    m32,r32

          bsf                 Bit scan forward
0F BC     bsfw      rm16,r16
0F BC     bsfl      rm32,r32

          bsr                 Bit scan reverse
0F BD     bsrw      rm16,r16
0F BD     bsrl      rm32,r32

          bt                  Save bit in carry flag
0F A3     btw       r16,rm16
0F A3     btl       r32,rm32
0F BA /4  btw       imm8,rm16
0F BA /4  btl       imm8,rm32

          btc                 Bit test and complement
0F BB     btcw      r16,rm16
0F BB     btcl      r32,rm32
0F BA /7  btcw      imm8,rm16
0F BA /7  btcl      imm8,rm32

          btr                 Bit test and reset
0F B3     btrw      r16,rm16
0F B3     btrl      r32,rm32
0F BA /6  btrw      imm8,rm16
0F BA /6  btrl      imm8,rm32

          bts                 Bit test and set
0F AB     btsw      r16,rm16
0F AB     btsl      r32,rm32
0F BA /5  btsw      imm8,rm16
0F BA /5  btsl      imm8,rm32

E8        call      reli      Call Procedure
98        cbtw                Sign extend AL
98        cbw                 Sign extend AL
99        cdq                 Double word to quad word
F8        clc                 Clear carry
FC        cld                 Clear direction Flag
FA        cli                 Clear interrupt Flag
99        cltd                Double word to quad word
0F 06     clts                Clear task-switched flag in CR0
F5        cmc                 Complement carry flag

          cmp                 Compare
83 /7     cmpl      imm8s,rm32
83 /7     cmpw      imm8s,rm16
3C        cmpb      imm8,al
3D        cmpw      imm16,ax
3D        cmpl      imm32,eax
3D        cmpl      imm32
80 /7     cmpb      imm8,rm8
81 /7     cmpw      imm16,rm16
81 /7     cmpl      imm32,rm32
3A /r     cmpb      rm8,r8
3B /r     cmpw      rm16,r16
3B /r     cmpl      rm32,r32
38 /r     cmpb      r8,rm8
39 /r     cmpw      r16,rm16
39 /r     cmpl      r32,rm32

A6        cmpsb               Compare bytes
A7        cmpsl               Compare long
A7        cmpsw               Compare words
99        cwd                 Word to double word
98        cwde                Sign extend AX
99        cwtd                Word to double word
98        cwtl                Sign extend AX
27        daa                 Decimal adjust after addition
2F        das                 Decimal adjust after subtraction

          dec                 Decrement by 1
48 +r     decw      r16
48 +r     decl      r32
FE /1     decb      rm8
FF /1     decw      rm16
FF /1     decl      rm32

          div                 Unsigned divide
F6 /6     divb      rm8,al
F6 /6     divb      rm8
F7 /6     divw      rm16,ax
F7 /6     divw      rm16
F7 /6     divl      rm32,eax
F7 /6     divl      rm32

C8        enter     imm8,imm16Make stack frame for procedure
D9 F0     f2xm1               ST = 2 ** ST - 1
D9 E1     fabs                ST = abs(ST)

          fadd                Floating add
D8 /0     fadds     m32
DC /0     faddl     m64
D8 C0 +r  fadd      fpreg,st0
D8 C0 +r  fadd      fpreg
DE C1     fadd
DC C0 +r  fadd      st0,fpreg

          faddp               Floating add and pop
DE C0 +r  faddp     st0,fpreg
DE C0 +r  faddp     fpreg
DE C1     faddp

DF /4     fbld      m80       Load Binary Coded Decimal
DF /6     fbstp     m80       Store Binary Coded Decimal and Pop
D9 E0     fchs                Change Floating Sign
9B DB E2  fclex               Clear floating point exception flags

          fcom                Floating Compare
D8 /2     fcoms     m32
DC /2     fcoml     m64
D8 D0 +r  fcom      fpreg,st0
D8 D0 +r  fcom      fpreg
D8 D1     fcom

          fcomp               Floating Compare and Pop
D8 /3     fcomps    m32
DC /3     fcompl    m64
D8 D8 +r  fcomp     fpreg
D8 D9     fcomp

DE D9     fcompp              Floating Compare and pop twice
D9 FF     fcos                Cosine
D9 F6     fdecstp             Decrement Stack Top Pointer

          fdiv                Floating divide
D8 /6     fdivs     m32
DC /6     fdivl     m64
D8 F0 +r  fdiv      fpreg,st0
D8 F0 +r  fdiv      fpreg
DE F1     fdiv
DC F0 +r  fdiv      st0,fpreg

          fdivp               Floating divide and pop
DE F0 +r  fdivp     st0,fpreg
DE F0 +r  fdivp     fpreg
DE F1     fdivp

          fdivr               Reverse floating divide
D8 /7     fdivrs    m32
DC /7     fdivrl    m64
D8 F8 +r  fdivr     fpreg,st0
D8 F8 +r  fdivr     fpreg
DE F9     fdivr
DC F8 +r  fdivr     st0,fpreg

          fdivrp              Reverse floating divide and pop
DE F8 +r  fdivrp    st0,fpreg
DE F8 +r  fdivrp    fpreg
DE F9     fdivrp

DD C0 +r  ffree     fpreg     Free Floating Point Register

          fiadd               Add integer to float
DA /0     fiaddl    m32
DE /0     fiadds    m16

          ficom               Compare float to integer
DA /2     ficoml    m32
DE /2     ficoms    m16

          ficomp              Compare float to integer and pop
DA /3     ficompl   m32
DE /3     ficomps   m16

          fidiv               Divide float by integer
DA /6     fidivl    m32
DE /6     fidivs    m16

          fidivr              Reverse divide integer by float
DA /7     fidivrl   m32
DE /7     fidivrs   m16

          fild                Load integer
DB /0     fildl     m32
DF /0     filds     m16
DF /5     fildll    m64

          fimul               Multiply integer to float
DA /1     fimull    m32
DE /1     fimuls    m16

D9 F7     fincstp             Increment Stack Top Pointer
9B DB E3  finit               Initialize Floating Point Unit

          fist                Store integer
DB /2     fistl     m32
DF /2     fists     m16

          fistp               Store integer and pop
DB /3     fistpl    m32
DF /3     fistps    m16
DF /7     fistpll   m32

          fisub               Subtract integer from float
DA /4     fisubl    m32
DE /4     fisubs    m16

          fisubr              Reverse subtract integer from float
DA /5     fisubrl   m32
DE /5     fisubrs   m16

          fld                 Load Real
D9 C0 +r  fld       fpreg
D9 /0     flds      m32
DD /0     fldl      m32
DB /5     fldt      m64

D9 E8     fld1                Load Constant 1
D9 /5     fldcw     m32       Load Floating Point Control Word
D9 /4     fldenv    m32       Load FPU Environment
D9 EA     fldl2e              Load Constant log(e) base 2
D9 E9     fldl2t              Load Constant log(10) base 2
D9 EC     fldlg2              Load Constant log(2) base 10
D9 ED     fldln2              Load Constant log(2) base e
D9 EB     fldpi               Load Constant pi
D9 EE     fldz                Load Constant 0.0

          fmul                Floating multiply
D8 /1     fmuls     m32
DC /1     fmull     m64
D8 C8 +r  fmul      fpreg,st0
D8 C8 +r  fmul      fpreg
DE C9     fmul
DC C8 +r  fmul      st0,fpreg

          fmulp               Floating multiply and pop
DE C8 +r  fmulp     st0,fpreg
DE C8 +r  fmulp     fpreg
DE C9     fmulp

DB E2     fnclex              Clear floating point exception flags no wait
DB E3     fninit              Initialize Floating Point Unit no wait
D9 D0     fnop                No Operation
DD /6     fnsave    m32       Store FPU State no wait
D9 /7     fnstcw    m32       Store Control Word no wait
D9 /6     fnstenv   m32       Store FPU Environment no wait

          fnstsw              Store Status Word no wait
DD /7     fnstsw    m16
DF E0     fnstsw    ax

D9 F3     fpatan              Partial Arctangent
D9 F8     fprem               Partial Remainder toward 0
D9 F5     fprem1              Partial Remainder < 1/2 modulus
D9 F2     fptan               Partial Tangent
D9 FC     frndint             Round To Integer
DD /4     frstor    m32       Resore FPU State
DB F4     frstpm              set 287XL real mode (nop for 387/486)
9B DD /6  fsave     m32       Store FPU State
D9 FD     fscale              Scale
DB E4     fsetpm              set 287 protected mode (nop for 387/486)
D9 FE     fsin                Sine
D9 FB     fsincos             Sine and Cosine
D9 FA     fsqrt               Square Root

          fst                 Store Real
DD D0 +r  fst       fpreg
D9 /2     fsts      m32
DD /2     fstl      m64

9B D9 /7  fstcw     m32       Store Control Word
9B D9 /6  fstenv    m32       Store FPU Environment

          fstp                Store Real and pop
DD D8 +r  fstp      fpreg
D9 /3     fstps     m32
DD /3     fstpl     m64
DB /7     fstpt     m80

          fstsw               Store Status Word
9B DD /7  fstsw     m16
9B DF E0  fstsw     ax

          fsub                Floating subtract
D8 /4     fsubs     m32
DC /4     fsubl     m64
D8 E0 +r  fsub      fpreg,st0
D8 E0 +r  fsub      fpreg
DE E1     fsub
DC E0 +r  fsub      st0,fpreg

          fsubp               Floating subtract and pop
DE E0 +r  fsubp     st0,fpreg
DE E0 +r  fsubp     fpreg
DE E1     fsubp

          fsubr               Reverse floating subtract
D8 /5     fsubrs    m32
DC /5     fsubrl    m64
D8 E8 +r  fsubr     fpreg,st0
D8 E8 +r  fsubr     fpreg
DE E9     fsubr
DC E8 +r  fsubr     st0,fpreg

          fsubrp              Reverse floating subtract and pop
DE E8 +r  fsubrp    st0,fpreg
DE E8 +r  fsubrp    fpreg
DE E9     fsubrp

D9 E4     ftst                Test

          fucom               Unordered compare real
DD E0 +r  fucom     st0,fpreg
DD E0 +r  fucom     fpreg
DD E1     fucom

          fucomp              Unordered compare real and pop
DD E8 +r  fucomp    st0,fpreg
DD E8 +r  fucomp    fpreg
DD E9     fucomp

DA E9     fucompp             Unordered compare %st %st1 and pop twice
9B        fwait               Wait for coprocessor
D9 E5     fxam                Examine

          fxch                Floating exchange
D9 C8 +r  fxch      st0,fpreg
D9 C8 +r  fxch      fpreg,st0
D9 C8 +r  fxch      fpreg
D9 C9     fxch

D9 F4     fxtract             Extract Exponent and Significand
D9 F1     fyl2x               %st1 * log(%st) base 2
D9 F9     fyl2xp1             %st1 * log(%st + 1.0) base 2
F4        hlt                 Halt
FF /2     icall     rm32      Call indirect

          idiv                Signed divide
F6 /7     idivb     rm8,al
F6 /7     idivb     rm8
F7 /7     idivw     rm16,ax
F7 /7     idivw     rm16
F7 /7     idivl     rm32,eax
F7 /7     idivl     rm32

FF /4     ijmp      rm32      Jump indirect
FF /3     ilcall    m32       Long call indirect
FF /5     iljmp     m32       Long jump indirect

          imul                Signed multiply
F6 /5     imulb     rm8,al
F6 /5     imulb     rm8
F7 /5     imulw     rm16,ax
F7 /5     imulw     rm16
F7 /5     imull     rm32,eax
F7 /5     imull     rm32
0F AF /r  imulw     rm16,r16
0F AF /r  imull     rm32,r32
6B        imulw     imm8s,rm16,r16
6B        imull     imm8s,rm32,r32
6B /r     imulw     imm8s,r16
6B /r     imull     imm8s,r32
69        imulw     imm16,rm16,r16
69        imull     imm32,rm32,r32
69 /r     imulw     imm16,r16
69 /r     imull     imm32,r32

          in                  Input from port
E4        inb       imm8
E5        inw       imm8
E5        inl       imm8
EC        inb       (dx)
ED        inw       (dx)
ED        inl       (dx)

          inc                 Increment by one
40 +r     incw      r16
40 +r     incl      r32
FE /0     incb      rm8
FF /0     incw      rm16
FF /0     incl      rm32

6C        insb                Input byte from port into ES:(E)DI
6C        insb      (dx)      Input byte from port into ES:(E)DI
6D        insl                Input long from port into ES:(E)DI
6D        insl      (dx)      Input long from port into ES:(E)DI
6D        insw                Input word from port into ES:(E)DI
6D        insw      (dx)      Input word from port into ES:(E)DI
CC        int       con3      Interrupt 3
CD        int       imm8      Interrupt
CE        into                Int 4 if overflow is 1
CF        iret                Interrupt return
CF        iretd               Different mode different opcode ?
07        ja        reli      Jump if above
03        jae       reli      Jump if above or equal
02        jb        reli      Jump if below
06        jbe       reli      Jump if below or equal
02        jc        reli      Jump if carry
E3        jcxz      rel8      Jump if CX is zero
04        je        reli      Jump if equal
E3        jecxz     rel8      Jump if CX is zero
0F        jg        reli      Jump if greater
0D        jge       reli      Jump if greater or equal
0C        jl        reli      Jump if less
0E        jle       reli      Jump if less or equal
E9        jmp       reli      Jump absolute
06        jna       reli      Jump if not above
02        jnae      reli      Jump if not above or equal
03        jnb       reli      Jump if not below
07        jnbe      reli      Jump if not below or equal
03        jnc       reli      Jump if no carry
05        jne       reli      Jump if not equal
0E        jng       reli      Jump if not greater
0C        jnge      reli      Jump if not greater or equal
0D        jnl       reli      Jump if not less
0F        jnle      reli      Jump if not less or equal
01        jno       reli      Jump if not overflow
0B        jnp       reli      Jump if not parity
09        jns       reli      Jump if not sign
05        jnz       reli      Jump if not zero
00        jo        reli      Jump if overflow
0A        jp        reli      Jump if parity
0A        jpe       reli      Jump if parity even
0B        jpo       reli      Jump if parity odd
08        js        reli      Jump if sign
04        jz        reli      Jump if zero
04        jz        reli      Jump if zero
9F        lahf                Load flags into AH register

          lar                 Load access rights byte
0F 02 /r  larw      rm16,r16
0F 02 /r  larl      rm32,r32

9A        lcall     imm16x,imm32Long call

          lds                 load full pointer DS:r16
C5 /r     ldsw      m16,r16
C5 /r     ldsl      m32,r32

          lea                 Load effective address
8D /r     leaw      m16,r16
8D /r     leal      m32,r32

C9        leave               High level procedure exit

          les                 Load full pointer ES:r16
C4 /r     lesw      m16,r16
C4 /r     lesl      m32,r32

          lfs                 Load full pointer FS:r16
0F B4 /r  lfsw      m16,r16
0F B4 /r  lfsl      m32,r32

          lgdt                Load m into DGTR
0F 01 /2  lgdtw     m16
0F 01 /2  lgdtl     m32

          lgs                 Load full pointer GS:r16
0F B5 /r  lgsw      m16,r16
0F B5 /r  lgsl      m32,r32

          lidt                Load m into IDTR
0F 01 /3  lidtw     m16
0F 01 /3  lidtl     m32

EA        ljmp      imm16x,imm32Long jump
0F 00 /2  lldt      rm16      Load local descriptor table register
0F 01 /6  lmsw      rm16      Load machine status word
F0        lock                Assert lock signal for next instruction
AC        lodsb               Load string operand byte
AD        lodsl               Load string operand long
AD        lodsw               Load string operand word
E2        loop      rel8      Dec count jmp if count <> 0
E1        loope     rel8      Dec count jmp if count <> 0 and ZF = 1
E0        loopne    rel8      Dec count jmp if count <> 0 and ZF = 0
E0        loopnz    rel8      Dec count jmp if count <> 0 and ZF = 0
E1        loopz     rel8      Dec count jmp if count <> 0 and ZF = 1
CB        lret                Far return
CA        lret      imm16     Far return pop imm16 bytes of parms

          lsl                 Load segment limit
0F 03 /r  lslw      rm16,r16
0F 03 /r  lsll      rm32,r32

          lss                 Load full pointer SS:r16
0F B2 /r  lssw      m16,r16
0F B2 /r  lssl      m32,r32

0F 00 /3  ltr       rm16      Load task register

          mov                 Move data
A0        movb      moffs,al
A1        movw      moffs,ax
A1        movl      moffs,eax
A2        movb      al,moffs
A3        movw      ax,moffs
A3        movl      eax,moffs
8A /r     movb      rm8,r8
8B /r     movw      rm16,r16
8B /r     movl      rm32,r32
88 /r     movb      r8,rm8
89 /r     movw      r16,rm16
89 /r     movl      r32,rm32
8C /r     movw      sreg,rm16
8E /r     movw      rm16,sreg
B0 +r     movb      imm8,r8
B8 +r     movw      imm16,r16
B8 +r     movl      imm32,r32
C6        movb      imm8,rm8
C7        movw      imm16,rm16
C7        movl      imm32,rm32
0F 20 /r  movl      ctlreg,r32
0F 22 /r  movl      r32,ctlreg
0F 21 /r  movl      dbreg,r32
0F 23 /r  movl      r32,dbreg
0F 24 /r  movl      treg,r32
0F 26 /r  movl      r32,treg

A4        movsb               Move bytes
A5        movsl               Move longs
A5        movsw               Move words

          movsx               Move with sign extend
0F BE /r  movsxb    rm8,r16
0F BE /r  movsxb    rm8,r32
0F BF /r  movsxw    rm16,r32
0F BE /r  movsbw    rm8,r16
0F BE /r  movsbl    rm8,r32
0F BF /r  movswl    rm16,r32

          movzx               Move with zero extend
0F B6 /r  movzxb    rm8,r16
0F B6 /r  movzxb    rm8,r32
0F B7 /r  movzxw    rm16,r32
0F B6 /r  movzbw    rm8,r16
0F B6 /r  movzbl    rm8,r32
0F B7 /r  movzwl    rm16,r32

          mul                 Unsigned multiply
F6 /4     mulb      rm8,al
F6 /4     mulb      rm8
F7 /4     mulw      rm16,ax
F7 /4     mulw      rm16
F7 /4     mull      rm32,eax
F7 /4     mull      rm32

          neg                 Negate
F6 /3     negb      rm8
F7 /3     negw      rm16
F7 /3     negl      rm32

90        nop                 No operation

          not                 Invert bits
F6 /2     notb      rm8
F7 /2     notw      rm16
F7 /2     notl      rm32

          or                  Logical inclusive OR
83 /1     orl       imm8s,rm32
83 /1     orw       imm8s,rm16
0C        orb       imm8,al
0D        orw       imm16,ax
0D        orl       imm32,eax
0D        orl       imm32
80 /1     orb       imm8,rm8
81 /1     orw       imm16,rm16
81 /1     orl       imm32,rm32
0A /r     orb       rm8,r8
0B /r     orw       rm16,r16
0B /r     orl       rm32,r32
08 /r     orb       r8,rm8
09 /r     orw       r16,rm16
09 /r     orl       r32,rm32

          out                 Output from port
E6        outb      imm8
E7        outw      imm8
E7        outl      imm8
EE        outb      (dx)
EF        outw      (dx)
EF        outl      (dx)

6E        outsb               Output byte to port into ES:(E)DI
6F        outsl               Output long to port into ES:(E)DI
6F        outsw               Output word to port into ES:(E)DI

          pop                 Pop a word from the stack
58 +r     popw      r16
58 +r     popl      r32
1F        popw      ds
07        popw      es
17        popw      ss
0F A1     popw      fs
0F A9     popw      gs
8F /0     popw      m16
8F /0     popl      m32

          popa                Pop all
61        popaw
61        popal

          popf                Pop stack into flags
9D        popfw
9D        popfl

          push                Push a word on the stack
50 +r     pushw     r16
50 +r     pushl     r32
6A        pushb     imm8s
68        pushw     imm16
68        pushl     imm32
0E        pushw     cs
1E        pushw     ds
06        pushw     es
16        pushw     ss
0F A0     pushw     fs
0F A8     pushw     gs
FF /6     pushw     m16
FF /6     pushl     m32

          pusha               Push all
60        pushaw
60        pushal

          pushf               Push flags
9C        pushfw
9C        pushfl

          rcl                 Rotate carry left
D0 /2     rclb      con1,rm8
D0 /2     rclb      rm8
D2 /2     rclb      cl,rm8
C0 /2     rclb      imm8,rm8
D1 /2     rclw      con1,rm16
D1 /2     rclw      rm16
D3 /2     rclw      cl,rm16
C1 /2     rclw      imm8,rm16
D1 /2     rcll      con1,rm32
D1 /2     rcll      rm32
D3 /2     rcll      cl,rm32
C1 /2     rcll      imm8,rm32

          rcr                 Rotate carry right
D0 /3     rcrb      con1,rm8
D0 /3     rcrb      rm8
D2 /3     rcrb      cl,rm8
C0 /3     rcrb      imm8,rm8
D1 /3     rcrw      con1,rm16
D1 /3     rcrw      rm16
D3 /3     rcrw      cl,rm16
C1 /3     rcrw      imm8,rm16
D1 /3     rcrl      con1,rm32
D1 /3     rcrl      rm32
D3 /3     rcrl      cl,rm32
C1 /3     rcrl      imm8,rm32

F3        rep                 rep following instruction CX times
F3        repe                repe following instruction CX times or eq
F2        repne               repne following instruction CX times or ne
F2        repnz               alternate name for repnz
F3        repz                alternate name for repe
C3        ret                 Return
C2        ret       imm16     Return pop imm16 bytes of parms

          rol                 Rotate left
D0 /0     rolb      con1,rm8
D0 /0     rolb      rm8
D2 /0     rolb      cl,rm8
C0 /0     rolb      imm8,rm8
D1 /0     rolw      con1,rm16
D1 /0     rolw      rm16
D3 /0     rolw      cl,rm16
C1 /0     rolw      imm8,rm16
D1 /0     roll      con1,rm32
D1 /0     roll      rm32
D3 /0     roll      cl,rm32
C1 /0     roll      imm8,rm32

          ror                 Rotate right
D0 /1     rorb      con1,rm8
D0 /1     rorb      rm8
D2 /1     rorb      cl,rm8
C0 /1     rorb      imm8,rm8
D1 /1     rorw      con1,rm16
D1 /1     rorw      rm16
D3 /1     rorw      cl,rm16
C1 /1     rorw      imm8,rm16
D1 /1     rorl      con1,rm32
D1 /1     rorl      rm32
D3 /1     rorl      cl,rm32
C1 /1     rorl      imm8,rm32

9E        sahf                Store AH into flags

          sal                 Shift arithmetic left
D0 /4     salb      con1,rm8
D0 /4     salb      rm8
D2 /4     salb      cl,rm8
C0 /4     salb      imm8,rm8
D1 /4     salw      con1,rm16
D1 /4     salw      rm16
D3 /4     salw      cl,rm16
C1 /4     salw      imm8,rm16
D1 /4     sall      con1,rm32
D1 /4     sall      rm32
D3 /4     sall      cl,rm32
C1 /4     sall      imm8,rm32

          sar                 Shift arithmetic right
D0 /7     sarb      con1,rm8
D0 /7     sarb      rm8
D2 /7     sarb      cl,rm8
C0 /7     sarb      imm8,rm8
D1 /7     sarw      con1,rm16
D1 /7     sarw      rm16
D3 /7     sarw      cl,rm16
C1 /7     sarw      imm8,rm16
D1 /7     sarl      con1,rm32
D1 /7     sarl      rm32
D3 /7     sarl      cl,rm32
C1 /7     sarl      imm8,rm32

          sbb                 Subtract with borrow
83 /3     sbbl      imm8s,rm32
83 /3     sbbw      imm8s,rm16
1C        sbbb      imm8,al
1D        sbbw      imm16,ax
1D        sbbl      imm32,eax
1D        sbbl      imm32
80 /3     sbbb      imm8,rm8
81 /3     sbbw      imm16,rm16
81 /3     sbbl      imm32,rm32
1A /r     sbbb      rm8,r8
1B /r     sbbw      rm16,r16
1B /r     sbbl      rm32,r32
18 /r     sbbb      r8,rm8
19 /r     sbbw      r16,rm16
19 /r     sbbl      r32,rm32

AE        scasb               Compare string bytes
AF        scasl               Compare string longs
AF        scasw               Compare string words
0F 97     seta      rm8       Set byte if above
0F 93     setae     rm8       Set byte if above or equal
0F 92     setb      rm8       Set byte if below
0F 96     setbe     rm8       Set byte if below or equal
0F 92     setc      rm8       Set byte if carry
0F 94     sete      rm8       Set byte if equal
0F 9F     setg      rm8       Set byte if greater
0F 9D     setge     rm8       Set byte if greater or equal
0F 9C     setl      rm8       Set byte if less
0F 9E     setle     rm8       Set byte if less or equal
0F 96     setna     rm8       Set byte if not above
0F 92     setnae    rm8       Set byte if not above or equal
0F 93     setnb     rm8       Set byte if not below
0F 97     setnbe    rm8       Set byte if not below or equal
0F 93     setnc     rm8       Set byte if no carry
0F 95     setne     rm8       Set byte if not equal
0F 9E     setng     rm8       Set byte if not greater
0F 9C     setnge    rm8       Set byte if not greater or equal
0F 9D     setnl     rm8       Set byte if not less
0F 9F     setnle    rm8       Set byte if not less or equal
0F 91     setno     rm8       Set byte if not overflow
0F 9B     setnp     rm8       Set byte if not parity
0F 99     setns     rm8       Set byte if not sign
0F 95     setnz     rm8       Set byte if not zero
0F 90     seto      rm8       Set byte if overflow
0F 9A     setp      rm8       Set byte if parity
0F 9A     setpe     rm8       Set byte if parity even
0F 9B     setpo     rm8       Set byte if parity odd
0F 98     sets      rm8       Set byte if sign
0F 94     setz      rm8       Set byte if zero
0F 94     setz      rm8       Set byte if zero
0F 01 /0  sgdt      mem32     Store gdtr

          shl                 Shift arithmetic left
D0 /4     shlb      con1,rm8
D0 /4     shlb      rm8
D2 /4     shlb      cl,rm8
C0 /4     shlb      imm8,rm8
D1 /4     shlw      con1,rm16
D1 /4     shlw      rm16
D3 /4     shlw      cl,rm16
C1 /4     shlw      imm8,rm16
D1 /4     shll      con1,rm32
D1 /4     shll      rm32
D3 /4     shll      cl,rm32
C1 /4     shll      imm8,rm32

          shld                Shift double precision left
0F A4     shldw     imm8,r16,rm16
0F A4     shldl     imm8,r32,rm32
0F A5     shldw     cl,r16,rm16
0F A5     shldl     cl,r32,rm32

          shr                 Shift right
D0 /5     shrb      con1,rm8
D0 /5     shrb      rm8
D2 /5     shrb      cl,rm8
C0 /5     shrb      imm8,rm8
D1 /5     shrw      con1,rm16
D1 /5     shrw      rm16
D3 /5     shrw      cl,rm16
C1 /5     shrw      imm8,rm16
D1 /5     shrl      con1,rm32
D1 /5     shrl      rm32
D3 /5     shrl      cl,rm32
C1 /5     shrl      imm8,rm32

          shrd                Shift double precision right
0F AC     shrdw     imm8,r16,rm16
0F AC     shrdl     imm8,r32,rm32
0F AD     shrdw     cl,r16,rm16
0F AD     shrdl     cl,r32,rm32
0F AD     shrdw     r16,rm16
0F AD     shrdl     r32,rm32

0F 01 /1  sidt      mem32     Store idtr
0F 00 /0  sldt      rm16      Store ldtr to EA word
0F 01 /4  smsw      rm16      Store machine status to EA word
F9        stc                 Set carry flag
FD        std                 Clear direction flag
FB        sti                 Set interrupt flag
AA        stosb               Store string byte
AB        stosl               Store string long
AB        stosw               Store string word
0F 00 /1  str                 Store task register

          sub                 Subtract
83 /5     subl      imm8s,rm32
83 /5     subw      imm8s,rm16
2C        subb      imm8,al
2D        subw      imm16,ax
2D        subl      imm32,eax
2D        subl      imm32
80 /5     subb      imm8,rm8
81 /5     subw      imm16,rm16
81 /5     subl      imm32,rm32
2A /r     subb      rm8,r8
2B /r     subw      rm16,r16
2B /r     subl      rm32,r32
28 /r     subb      r8,rm8
29 /r     subw      r16,rm16
29 /r     subl      r32,rm32

          test                Logical compare
A8        testb     imm8,al
A9        testw     imm16,ax
A9        testl     imm32,eax
A9        testl     imm32
F6 /0     testb     imm8,rm8
F7 /0     testw     imm16,rm16
F7 /0     testl     imm32,rm32
84 /r     testb     r8,rm8
85 /r     testw     r16,rm16
85 /r     testl     r32,rm32

0F 00 /4  verr      rm16      Verify segment for read
0F 00 /5  verw      rm16      Verify segment for write
9B        wait                Wait for coprocessor

          xchg                Exchange register
90 +r     xchgw     r16,ax
90 +r     xchgw     ax,r16
90 +r     xchgl     r32,eax
90 +r     xchgl     r32
90 +r     xchgl     eax,r32
86 /r     xchgb     rm8,r8
87 /r     xchgw     rm16,r16
87 /r     xchgl     rm32,r32
86 /r     xchgb     r8,rm8
87 /r     xchgw     r16,rm16
87 /r     xchgl     r32,rm32

D7        xlat                Table lookup translation
D7        xlatb               Table lookup translation

          xor                 Logical exclusive OR
83 /6     xorl      imm8s,rm32
83 /6     xorw      imm8s,rm16
34        xorb      imm8,al
35        xorw      imm16,ax
35        xorl      imm32,eax
35        xorl      imm32
80 /6     xorb      imm8,rm8
81 /6     xorw      imm16,rm16
81 /6     xorl      imm32,rm32
32 /r     xorb      rm8,r8
33 /r     xorw      rm16,r16
33 /r     xorl      rm32,r32
30 /r     xorb      r8,rm8
31 /r     xorw      r16,rm16
31 /r     xorl      r32,rm32

Using C to Prototype Assembly Language

The COHERENT C compiler includes a  switch, -S, that translates C code into
COHERENT assembly  language.  The assembly  language it produces  cannot be
directly assembled,  but you can examine  it to see just  what the compiler
does under given  circumstances; and you can use it  to prototype a routine
in assembly language.

Suppose, for  example, that  you wish  to write a  function that  takes two
parameters: an  integer, which  gives a  port number to  read from;  and an
address where the  data should go.  Start by writing  a C function with the
correct calling sequence.  For example, the following function is in a file
called proto.c:

readstuff(addr, port)
register char *addr;
int port;
{
    register int dx = port;
    char *foo = addr;
}

Compile it with the following command line:

    cc -S proto.c

This produces file proto.s, which contains the following:

/   module name foo
    .alignoff

    .text
    .globl readstuff
readstuff:
    push    %ebp
    movl    %ebp, %esp
    push    %esi
    push    %edi
    push    %ebx
    movl    %ebx, 8(%ebp)
    movl    %esi, 12(%ebp)
    movl    %edi, %ebx
    pop %ebx
    pop %edi
    pop %esi
    leave
    ret
    .align  4

This is your  prototype.  You can easily modify it  into what you want; for
example:

/   This will only work if you install it as a driver.
/   As the operating system will protect itself if
/   Ordinary users try to access ports. Ask about our
/   Device driver kits.

     .text
     .globl readstuff
readstuff:
     push    %ebp
     movl    %ebp, %esp
     push    %edi             / Save the edi for the caller
     movl    %edx, 8(%ebp)    / Get the port number
     movl    %edi, 12(%ebp)   / Get the user address

     insb                     / Read port (%dx) to %es:%edi

     pop     %edi             / See 386 calling conventions
     leave
     ret

Example

The following example echoes strings onto your screen.

/ sstatic void foo(i) { printf("Parm is %d\n", i); }

     .text
.L2: .byte   "Parm is %d0, 0

foo:
     push    %ebp             / set up stack frame
     movl    %ebp, %esp
     push    8(%ebp)          / push parms from right to left
     push    $.L2
     call    printf
     leave                    / %esp <- %ebp; pop %ebp
     ret

/ main() { foo(5); }

     .globl main
main:
     push    %ebp
     movl    %ebp, %esp
     push    $5
     call    foo
     leave
     ret

See Also

asfix,
calling conventions,
cc,
cdmp,
commands
Intel Corporation:  386 DX Programmer's Reference  Manual. Santa Clara, CA:
Intel Corporation, 1990.  Highly recommended.

Diagnostics

The following gives the error messages  returned by as. The messages are in
alphabetical order.  Each message is marked as to its degree of severity: A
fatal message  usually indicates a  condition that caused  the assembler to
terminate  execution.   Often,  they  indicate  internal  problems  in  the
assembler.  An error message points to  a condition in the source code that
the assembler  cannot resolve.  This almost always  occurs when the program
does  something  illegal.   A  warning  message  points out  code  that  is
compilable, but may produce trouble when the program is executed.

.align must be 1, 2 or 4 (error)
     .align must work after the link.   These are the only values for which
     this can be true.

Ambiguous operand length, n bytes selected (warning)
     The assembler cannot tell the  operand length by looking at the opcode
     and the  operands.  You may  want to do  something like change  mov to
     movl.

Arithmetic between addresses on different segments (error)
     You  may only  add  or subtract  addresses  if they  are  in the  same
     segment.

Bad scale (error)
     Address scale must be 0, 1, 2, 4, or 8.

16 bit addressing mode used in 32 bit code (warning)
     You probably don't want to do  this.  For example, you may want to say
     (%esi), not (%si).

32 bit addressing mode used in 16 bit code (warning)
     You probably don't want to do  this.  For example, you may want to say
     (%si), not (%esi).

Cannot fopen(string, string) (fatal)
Cannot insert \0 in string (error)
     NUL (\0) terminates strings.  Instead of

         .byte   "hello\n\0"
     use:

         .byte   "hello\n", 0

Character constant n long (error)
     Character constants must be one byte long.

.comm must have tag (error)
     The format of .comm is .comm name, size.

Command option 'c' missing its argument (fatal)
Data defined in .bss (error)
     The  .bss segment  is  uninitialized data.   You  cannot place  actual
     values there.

.define must have a label (error)
Duplicate symbol 'string' (error)
     symbol is defined on two different lines.

.else detected logic type n (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

End of line after backslash reading parm (error)
     Macro parmeters may not be broken up with backslash.

End of line after backslash (error)
End of line detected in character constant (error)
End of line detected in string (error)
End of macro building .while (error)
     A .macro ended while reading in a .while loop.

.endi detected logic type n (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Error in binary number (error)
Error in octal number (error)
Found n parms expected n (error)
Illegal combination of opcode and operands (error)
     Although the opcode  is valid and the operands are  valid, there is no
     form of  this opcode which takes this combination  of operands in this
     order.

Illegal use of local symbol (error)
Illegal use of of predefined symbol string. (error)
Improper instruction following lock (warning)
     Only a few instructions are  valid after a lock instruction.  See your
     machine documentation for details.

Improper instruction following rep (warning)
     Only a  few instructions are valid after a  rep instruction.  See your
     machine documentation for details.

Indirect mode on invalid instruction (error)
     Indirection is only allowed on call and jump near instructions.

Internal error relative branch logic (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Invalid .mlist option must be on or off (error)
Invalid character 'c' string at position n (error)
Invalid character 0x0xn string at position n (error)
Invalid data type, must be symbol (error)
Invalid floating point register number (error)
Invalid opcode: 'string' (error)
     The string in the opcode position  is not one of our opcodes or one of
     your macros.

Invalid operand type (error)
string is an improper register in this context (error)
Label ignored (error)
     This statement cannot take a label.

Label on invalid operator (error)
Label required (error)
Length n string range exceeded (error)
     Strings may not exceed 32 kilobytes.

Logic error in macro def 'string' n (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Logic error in umark (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Macro definition must have a label (error)
.mexit not in macro (error)
Missing .endi (error)
     Input ended leaving .if open.

Missing .endm (error)
     Input ended leaving .macro open.

Missing .endw (error)
     Input ended leaving .while open.

Mixed 386/286 addressing modes (error)
     No opcode allows mixed 286 and 386 addressing modes.

Mixed 386/286 data modes (error)
     No 386 opcode allows mixed 286 and 386 data modes.

Mixed length addressing registers (error)
     Addressing registers must both be the same length.

more than one file to process (fatal)
     The assembler will only process one file at a time.

Name required (error)
     The format of set is .set name, value

no work (fatal)
     There were no files listed on the command line.

NULL address in relative branch (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Octal number n truncated to char (error)
     An octal number in a string was too big.

Optype n in lex (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Org to invalid value (error)
     You may not .org to doubles or strings.

Org to wrong segment (error)
     You must .org to the current segment.

Out of space (fatal)
     A call  to malloc()  failed.  The typical  large consumers of  RAM are
     macros  and  .defines;  symbols  consume  less.   Can you  break  your
     assembly into  smaller pieces?  Could  you be in some  sort of endless
     recursion or loop?

Parm n not found (error)
     An attempt to .shift too far has been made.

.parmct not in macro (error)
     .parmct returns the number of parameters in the current macro.

Phase error 'string' (error)
     A symbol is  defined one way in one phase  of the assembly and another
     way in the next phase.

Redefinition of 'string' (error)
     An assembler internal symbol is being redefined.

Seek error on object file (fatal)
Seek error on object file (fatal)
.shift not in macro (error)
     .shift shifts macro parameters.  It has no meaning outside a macro.

String must be on .byte (error)
     For example:

         .byte "This is how we place a string", 0

Symbol may not be double (error)
     You may not convert a symbol to a floating-point value.

Symbol may not be float (error)
     You may not convert a symbol to a floating-point value.

Syntax error (error)
     The syntax of  this statement makes no sense to  the parser.  This can
     be a variety of problems.

Table error kind 0xn detected (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

This code may not work the same way on all chips (warning)
     Some chips may not execute this code as expected.

Too many operands (error)
     No 386 opcode has more than three operands.

Undefined symbol 'string' (error)
     A symbol was used without defining  it or using a -g option.  You must
     define local symbols.

Unexpected .else statement (error)
Unexpected .endi statement (error)
Unexpected .endm ignored (error)
Unexpected .endw (error)
Unexpected return from parser (fatal)
     Logic error in assembler.  Please report this problem to Mark Williams
     technical support.

Unknown command option c (fatal)
Unlikely output file 'string' (fatal)
     Output file-names should  have .o suffixes.  Because this is generally
     a  typographical error,  as aborts to  avoid overwriting  an important
     file.

Unmatched 'c' (error)
     A delimeter, [, (, ), or ] is unmatched in this command.

Unmatched bracket in parmeter (error)
     Line ended leaving an open bracket or parenthesis.

Write error on object file (fatal)
     as could  not write  the object  module.  This error  can have  any of
     several causes;  the most common is that you  lack permission to write
     into the  current directory,  or you  lack permission to  overwrite an
     existing file of the same name.

Notes

We have designed  as to ease porting of programs  written in other dialects
of  UNIX 386  assembly  language, as  well  as to  be a  powerful tool  for
development  of new  programs.  We  think  you will  find the  features and
documentation  of  our   assembler  considerably  more  complete  than  are
available anywhere else.  However, we have chosen not to duplicate behavior
of other assemblers that leads  to inefficient or incorrect output, or that
generates code without warning when given questionable input.  We have also
chosen to  support operator precedence rather  than perpetuating antiquated
left-to-right evaluation schemes seen elsewhere.  Caveat utilitor.

In the course  of writing this assembler, we have  discovered that the UNIX
implementation of fdiv, fdivr,  fsub, and fsubr differs from that described
in  the  Intel documents.   The  COHERENT assembler  conforms  to the  UNIX
standard by default.  You should be very careful with the order of operands
to these instructions.  Once again, caveat utilitor.