The 386 assembler included in Gforth was written by Bernd Paysan, it's available under GPL, and originally part of bigFORTH.
The 386 disassembler included in Gforth was written by Andrew McKewan and is in the public domain.
The disassembler displays code in an Intel-like prefix syntax.
The assembler uses a postfix syntax with reversed parameters.
The assembler includes all instruction of the Athlon, i.e. 486 core instructions, Pentium and PPro extensions, floating point, MMX, 3Dnow!, but not ISSE. It's an integrated 16- and 32-bit assembler. Default is 32 bit, you can switch to 16 bit with .86 and back to 32 bit with .386.
There are several prefixes to switch between different operation sizes,
.b for byte accesses,
.w for word accesses,
double-word accesses. Addressing modes can be switched with
for 16 bit addresses, and
.da for 32 bit addresses. You don't
need a prefix for byte register names (
AL et al).
For floating point operations, the prefixes are
.fl (IEEE double),
.fd (double-word), and
The MMX opcodes don't have size prefixes, they are spelled out like in the Intel assembler. Instead of move from and to memory, there are PLDQ/PLDD and PSTQ/PSTD.
The registers lack the 'e' prefix; even in 32 bit mode, eax is called
ax. Immediate values are indicated by postfixing them with
3 #. Here are some examples of addressing modes in various
Gforth Intel (NASM) AT&T (gas) Name .w ax ax %ax register (16 bit) ax eax %eax register (32 bit) 3 # offset 3 $3 immediate 1000 #) byte ptr 1000 1000 displacement bx ) [ebx] (%ebx) base 100 di d) 100[edi] 100(%edi) base+displacement 20 ax *4 i#) 20[eax*4] 20(,%eax,4) (index*scale)+displacement di ax *4 i) [edi][eax*4] (%edi,%eax,4) base+(index*scale) 4 bx cx di) 4[ebx][ecx] 4(%ebx,%ecx) base+index+displacement 12 sp ax *2 di) 12[esp][eax*2] 12(%esp,%eax,2) base+(index*scale)+displacement
You can use
LI) instead of
DI) to enforce 32-bit displacement fields (useful for
Some example of instructions are:
ax bx mov \ move ebx,eax 3 # ax mov \ mov eax,3 100 di d) ax mov \ mov eax,100[edi] 4 bx cx di) ax mov \ mov eax,4[ebx][ecx] .w ax bx mov \ mov bx,ax
The following forms are supported for binary instructions:
<reg> <reg> <inst> <n> # <reg> <inst> <mem> <reg> <inst> <reg> <mem> <inst> <n> # <mem> <inst>
The shift/rotate syntax is:
<reg/mem> 1 # shl \ shortens to shift without immediate <reg/mem> 4 # shl <reg/mem> cl shl
Precede string instructions (
movs etc.) with
.b to get
the byte version.
The control structure words
UNTIL etc. must be preceded
by one of these conditions:
vs vc u< u>= 0= 0<> u<= u> 0< 0>= ps
pc < >= <= >. (Note that most of these words shadow some Forth words
assembler is in front of
forth in the search path,
code words). Currently the control structure words use
one stack item, so you have to use
roll instead of
to shuffle them (you can also use
Here is an example of a
code word (assumes that the stack pointer
is in esi and the TOS is in ebx):
code my+ ( n1 n2 -- n ) 4 si D) bx add 4 # si add Next end-code