1990-01-16 13:27:47 +00:00
|
|
|
.\" $Header$
|
|
|
|
.TH I386_AS 6ACK
|
|
|
|
.ad
|
|
|
|
.SH NAME
|
|
|
|
i386_as \- assembler for Intel 80386
|
|
|
|
.SH SYNOPSIS
|
|
|
|
~em/lib/i386/as [options] argument ...
|
|
|
|
.SH DESCRIPTION
|
|
|
|
This assembler is made with the general framework
|
|
|
|
described in \fIuni_ass\fP(6). It is an assembler generating relocatable
|
|
|
|
object code in \fIack.out\fP(5) format.
|
|
|
|
.SH SYNTAX
|
|
|
|
.IP segments
|
|
|
|
An address on the Intel 80386 consists of two pieces:
|
|
|
|
a segment number and an offset.
|
|
|
|
Usually, the segment number resides in a segment register, and
|
|
|
|
assembly language addresses only give the offset, with the exception of
|
|
|
|
the address of an inter-segment jump or call (see \fIaddressing modes\fP
|
|
|
|
below).
|
|
|
|
.IP registers
|
|
|
|
The Intel 80386 has the following 32-bit registers:
|
|
|
|
.br
|
|
|
|
Four general registers: eax (accumulator), ebx (base), ecx (count), and edx (data).
|
|
|
|
The low- and high order bytes of the low order words of these registers
|
|
|
|
are separately addressable as ah, bh, ch, dh, and al, bl, cl, dl respectively.
|
|
|
|
.br
|
|
|
|
Two pointer registers: esp (stack pointer) and ebp (base pointer).
|
|
|
|
.br
|
|
|
|
Two index registers: esi (source index) and edi (destination index).
|
|
|
|
.br
|
|
|
|
Six segment registers: cs (code), ds (data), ss (stack), es (extra),
|
|
|
|
fs (extra), and gs (extra).
|
|
|
|
.IP "addressing modes"
|
|
|
|
.nf
|
|
|
|
.ta 8n 16n 24n 32n 40n 48n
|
|
|
|
syntax meaning
|
|
|
|
|
|
|
|
expr the value of \fIexpr\fP is immediate data or
|
|
|
|
an address offset. There is no special
|
|
|
|
notation for immediate data.
|
|
|
|
|
|
|
|
register one of the aforementioned general registers
|
|
|
|
or their upper or lower halves, or one of the
|
|
|
|
four segment registers.
|
|
|
|
|
|
|
|
(expr) the value of expr is the address of the operand.
|
|
|
|
|
|
|
|
(reg)
|
|
|
|
expr (reg) the value of \fIexpr\fP (if present) + the contents of
|
|
|
|
\fIreg\fP (which must be a pointer or an index register)
|
|
|
|
is the address of the operand.
|
|
|
|
|
|
|
|
(reg1) (reg2)
|
|
|
|
expr (reg1) (reg2)
|
|
|
|
the value of \fIexpr\fP (if present) + the contents of
|
|
|
|
\fIreg1\fP + the
|
|
|
|
contents of \fIreg2\fP is the address of the operand.
|
|
|
|
|
|
|
|
(reg1) (reg2 * scale)
|
|
|
|
expr (reg1) (reg2 * scale)
|
|
|
|
the value of \fIexpr\fP (if present) + the contents of
|
|
|
|
\fIreg1\fP + the
|
|
|
|
contents of \fIreg2\fP multiplied by \fIscale\fP,
|
|
|
|
is the address of the operand.
|
|
|
|
\fIscale\fP can be either 1, 2, 4, or 8.
|
1990-03-09 12:37:19 +00:00
|
|
|
This mode is only allowed for 32-bit addressing.
|
1990-01-16 13:27:47 +00:00
|
|
|
|
|
|
|
The next addressing mode is only allowed with the instructions
|
|
|
|
"callf" or "jmpf".
|
|
|
|
|
|
|
|
expr : expr the value of the first \fIexpr\fP is a segment number,
|
|
|
|
the value of the second \fIexpr\fP is an address offset.
|
|
|
|
|
|
|
|
The following two addressing modes are only allowed with Intel 80[23]87 floating
|
|
|
|
point processor instructions:
|
|
|
|
|
|
|
|
st
|
|
|
|
st(num) addresses the floating point processor stack. \fInum\fP
|
|
|
|
must be between 0 and 7. st is the same as st(0).
|
|
|
|
|
|
|
|
.fi
|
|
|
|
|
|
|
|
.IP prefixes
|
|
|
|
Each time an address is computed the processor decides which segment register
|
|
|
|
to use. You can override the processor's choice by prefixing the instruction
|
|
|
|
with one of eseg, cseg, sseg, dseg, fseg, or gseg; these prefixes indicate that the
|
|
|
|
processor should choose es, cs, ss, ds, fs, or gs instead.
|
|
|
|
.br
|
|
|
|
Example:
|
|
|
|
.ti +8
|
|
|
|
dseg movs
|
|
|
|
.IP ""
|
|
|
|
There is also an address size toggle, which switches between 32-bit and
|
|
|
|
16-bit address generation: a16 or a32. Normally, the assembler generates
|
|
|
|
32-bit addresses; both of these toggles make it generate 16-bit addresses
|
|
|
|
for the next instruction, and also generate code to set the processor
|
|
|
|
temporarily in 16-bit address mode.
|
|
|
|
.IP ""
|
|
|
|
There is also an operand size toggle, which switches between 32-bit and
|
|
|
|
16-bit operands: o16 or o32. Normally, the assembler generates
|
|
|
|
32-bit operands; both of these toggles make it generate 16-bit operands
|
|
|
|
for the next instruction, and also generate code to set the processor
|
|
|
|
temporarily in 16-bit operand mode.
|
|
|
|
.IP ""
|
|
|
|
Prefixes only affect the next instruction.
|
1990-03-09 12:37:19 +00:00
|
|
|
.IP ""
|
|
|
|
There are also the .use32 and .use16 assembler directives, which do not
|
1990-07-30 12:46:12 +00:00
|
|
|
generate code, but change the assemblers default for operand and address sizes.
|
1990-03-09 12:37:19 +00:00
|
|
|
Obviously, .use16 gives 16-bit modes, .use32 gives 32-bit modes.
|
|
|
|
This is useful for assembling real mode 80386 code, or pure 16-bit
|
|
|
|
modules (that do not have the D-bit set in the segment descriptor).
|
1990-07-30 12:46:12 +00:00
|
|
|
These assembler directives stay in effect until there is another one.
|
1990-01-16 13:27:47 +00:00
|
|
|
.SH "SEE ALSO"
|
|
|
|
uni_ass(6),
|
|
|
|
ack(1),
|
|
|
|
ack.out(5),
|
|
|
|
.br
|
|
|
|
80386 Programmer's Reference Manual, 1986, Intel Corporation
|