���
			���� ��
		       ��
		       ��
		     � ����  ������    ����������������
		       ��	   �� ��    �  ��  �  �
		       ��    ��������  ������  ��  �  �
		       ��   �	   �� �     �� ��  �  �
		     ������  ����� ��  ������	�  �  �

			flat assembler	version 1.32

	 Copyright (c) 1999-2002, Tomasz Grysztar. All rights reserved.


Table of Contents

 1  Introduction
    1.1  What is fasm?
    1.2  Hardware requirements
    1.3  Software and OS requirements
    1.4  Output formats
    1.5  Output file ordering
    1.6  Output code optimization

 2  Using flat assembler
    2.1  Assembler syntax
	 2.1.1	Instruction syntax
		2.1.1.1  Data access
		2.1.1.2  Jumps and calls
		2.1.1.3  Labels and constants
		2.1.1.4  Addresses
		2.1.1.5  Special cases
		2.1.1.6  FPU and MMX instructions
	 2.1.2	Number syntax
	 2.1.3	Logical expressions syntax
	 2.1.4	Defining constants
	 2.1.5	Defining data
    2.2  Directives
	 2.2.1	Preprocessor directives
	 2.2.2	Code and format settings
	 2.2.3	Label and constant definitions
	 2.2.4	Other directives

���������������������������������������������������������������������������

1  Introduction

1.1  What is fasm?

     The flat assembler is a fast, efficient 80x86 assembler that runs
in 'flat real mode'.  So, it must be run on at least an 80386 PC, but
it can certainly assemble programs for any 80x86 PC.  Unlike many other
80x86 assemblers, fasm only requires the source code to include the
information it really needs.  See the 'asm' files in the 'examples'
subdirectory to see how simple it can be!  The files in the 'source' and
'examples' subdirectories are good references for more complex examples.
You may notice that fasm is case sensitive for all symbols (even instructions
and directives).

1.2  Hardware requirements

     Aside from the above-mentioned need for at least an 80386 CPU, the
hardware needs are small; at least one megabyte of extended memory is
reccommended for best performance.

1.3  Software and OS requirements

     Other than an OS compatible with MSDOS 2.0+, fasm needs no other
software.  Note that fasm will not run if the CPU is in protected or
V86 modes, since flat real mode cannot be entered in that case.  But
it will still run under Win32, because version for that system is attached
to fasm executable.

1.4  Output formats

     There are three possible output formats; by default, the output of
fasm is a non-relocatable binary image such as a 'com' or 'sys' program.
Use of the directive 'format MZ' produces a relocatable and possibly
multi-segment 'exe' program.  No extra 'linking' step is needed! Use of
the directive 'format PE' produces portable executable.

1.5  Output file ordering

     All output code is in the order in which it was entered into the
source file.  So, program code or at least an instruction such as 'jmp
start' must be at the beginning of the source code unless the program
is in format other than binary.  In that case, see the 'entry' directive
(below).

1.6  Output code optimization

     The flat assembler will do multiple (but fast) assembly passes to
generate optimal output code. When size of jump or address in instruction
is not specified, fasm will generate as small instruction code as possible.
That's the only code optimization fasm will do.

2  Using flat assembler

2.1  Assembler syntax

2.1.1  Instruction syntax

2.1.1.1  Data access

    Moving data to or from a register involves two simple rules;
'mov eax,myvar' will place the offset (address) of 'myvar' in the eax
register, while 'mov eax,[myvar]' will place the 32-bit value of the
variable 'myvar' in eax.  Note that fasm will exit with an error if 'myvar'
has not been defined as a 32-bit value. When 'myvar' has not been defined
as 32-bit value, but you need to assemble instruction 'mov eax,[myvar]',
use size override: 'mov eax,dword [myvar]'. This is dangerous if 'myvar' has
been defined as an 8-bit or a 16-bit variable; eax will contain whatever is
in the four bytes beginning at the address of 'myvar'! Allowed size overrides
are: byte (8-bit), word (16-bit), dword (32-bit), pword (48-bit),
qword (64-bit), tword (80-bit), dqword (128-bit).

2.1.1.2  Jumps and calls

    Unconditional:

	jmp  alpha		      ; simple jump
	jmp  near byte beta	      ; short jump
	jmp  near dword beta	      ; force dword size
	jmp  10h:50h		      ; far jump
	jmp  pword 10h:50000h	      ; 32-bit far jump
	call far pword [1000h]	      ; 32-bit far call
	call far dword [delta]	      ; 16-bit far call
	call near dword [delta]       ; 32-bit near call

    Conditional:

	je   alpha		      ; will be optimized
	jge  byte alpha 	      ; force byte (error if out of range)
	jb   dword alpha	      ; force dword (no optimization)

2.1.1.3  Labels and constants

    Examples of defining labels:

	alpha:			      ; simple label
	     label     beta	      ; as above
	     label     gamma byte     ; low byte of delta dword
	delta	       dd 0	      ; data label
	epsilon = alpha + 1	      ; constant definition

    Local labels:

	sigma:
	.alpha: 		      ; local label (1)
	     jmp  .alpha	      ; jump to (1)
	omega:
	.alpha: 		      ; local label (2)
	     jmp  .alpha	      ; jump to (2)
	     jmp  sigma.alpha	      ; jump to (1)

2.1.1.4  Addresses

    The fasm is able to do some simple arithmetics on registers, so forms
like '[ebx*5]' are allowed (it will be assembled as '[ebx+ebx*4]').
    Defining size of address value is possible; '[word 4]' and '[dword 4]'
will generate different output code: [0004] and [00000004], '[word bx]'
will be [bx+0000], '[byte bx]' will be [bx+00], '[dword ebx+1]' will
be [ebx+00000001], etc.

2.1.1.5  Special cases

    'xlat' instruction accepts one argument: '[bx]'/'byte [bx]' to create
16-bit version, or '[ebx]'/'byte [ebx]' to create 32-bit version of opcode;
in the similar way advanced settings of string instructions can be done, like
'movs byte [es:edi],[fs:esi]', to adjust address registers size and segment
override ('movs' needs two arguments). 'xlatb', 'movsb', etc. accept no
arguments.

2.1.1.6  FPU and MMX instructions

    Examples of FPU instructions:

	fld	tword [si]	      ; load fp
	fadd	st0,st3 	      ; add fp
	fimul	dword [ebx]	      ; multiply integer
	fstp	qword [edx]	      ; store fp and pop stack

    Examples of MMX instructions:

	paddb	mm0,mm1 	      ; packed add bytes
	pand	mm7,qword [esi]       ; logical and
	addps	xmm0,xmm1	      ; packed single fp add
	cmpeqps xmm7,dqword [esi]     ; packed single fp compare
	shufps	xmm4,xmm5,1	      ; shuffle single fp

2.1.2  Number syntax

    Decimal numbers: 15, 15d
    Binary: 1011b
    Hexadecimal: 0ABh, 0xAB
    Octal: 231o, 0231
    Floating point: 3.14, 1.0E3
    Special: $ - current address value, % - current repeat number (see 2.2.3)
    Operators: +,-,*,/,mod,not,and,or,xor,shl,shr
    Address conversion operator: rva (only in PE format)

2.1.3  Logical expressions syntax

    See 'macros' examples in Section 2.2.1 for usage examples.
The logical operators are: ~ (not), | (or), & (and). Logical values
can be defined using comparing operators: = (equal), < (less), > (greater),
<= (less or equal), >= (greater or equal), <> (not equal) for numbers;
'eq' or 'in' for all other symbols.

2.1.4  Defining constants

    As opposed to 'equ', '=' works with values only, and they are
calculated at define time; for example 'xyz = $' defines xyz symbol
as an address of point where it was defined, 'xyz equ $' will just
define equivalent to '$', which will be always address of point
where it's used.

2.1.5  Defining data

    Data can be defined in two ways; if the data is to be initialised
to a specific value, the forms are:

	gdtr	  db	16,0,0,0,0,0,0	      ; sequence of bytes
	attrib	  db	0x1E		      ; single byte (hexadecimal)
	command:  times 127 db 0	      ; byte string
	str001	  db	'test.bin',0	      ; character string
	argv:	  times 10 dd 0 	      ; ten 32-bit double words
	picture   file	'star.gif'	      ; whole file contents

    When loading data with 'file' instruction, after file name can follow
position in file preceded by colon, then comma and count of bytes to load.

    Other forms available are:

	dw   ; 16-bit word
	dp   ; 48-bit pointer
	dq   ; 64-bit quad word
	dt   ; 80-bit floating point
	du   ; 16-bit word strings

    If it is only desired to reserve space for data, the forms are:

	_proname  rd   1		      ; reserve one dword
	_inch	  rb   1		      ; reserve one byte
	newstack  rd   255		      ; reserve 255 dwords

    Other forms available are:

	rw   ; 16-bit word
	rp   ; 48-bit pointer
	rq   ; 64-bit quad word
	rt   ; 80-bit floating point

    Note that if the 'times' directive is to be used to define multiple data
items, any label used must end with a colon. The other way is to use 'label'
directive before data definition, for example:

	label argv dword
	times 10 dd 0

    To create union of some variables, you can use label directive with
'at <address>' phrase, or virtual directive, for example:

	GDT_limit dw 15
	GDT_address dd ?

	; now define virtual variable for lgdt and sgdt instructions

	label GDTR pword at GDT_limit

	; and now the other method

	LDTR dp ?

	virtual at LDTR
	  LDT_limit dw ?
	  LDT_address dd ?
	end virtual

2.2  Directives

2.2.1  Preprocessor directives

    The all preprocessor directives in the source code are processed before
the main assembly process, and so they are not affected by the 'if' or
'repeat' directives, which are processed at assembly time (see 2.2.4).

include - includes source file in source code before assembly

macro - defines macroinstructions, arguments are macro name and names
	of macro arguments separated with commas, then '{' (start of macro)
	character, macro instructions, and '}' (end of macro) character.
	Here's an example of macroinstruction for data alignment:

	macro align value { rb (value-1) - ($ + value-1) mod value }

	Note that in PE format you should replace '$' with 'rva $' to allow
	this calculations.

	Macroinstructions may have empty arguments; to check if argument
	is empty use something like 'if <argument> eq <>'.
	If a macro is defined that uses an instruction with the same name
	inside the macro definition, the previous meaning of this name is
	used; useful redefinition of macros can be done in that way, for
	example:

	macro mov arg1,arg2
	 {
	  if arg1 in <ds,es,fs,gs,ss> & arg2 in <cs,ds,es,fs,gs,ss>
	     push  arg2
	     pop   arg1
	  else
	     mov   arg1,arg2  ; here original mov instruction will be used
	  end if
	 }
	macro mov arg1,arg2,arg3
	 {
	  if <arg3> eq <>
	     mov   arg1,arg2  ; here previous macro will be used
	  else
	     mov   arg1,arg2
	     mov   arg2,arg3
	  end if
	 }
	mov   ax,bx	      ; just 'mov ax,bx'
	mov   ds,es	      ; 'push es' and 'pop ds'
	mov   es,ds,dx	      ; 'push ds', 'pop es' and 'mov ds,dx'

	But note that using these macros in big programs will dramatically
	slow down assembly (up to 3 times!) and increase memory requirements.

	If you type arguments in brackets, macroinstruction will allow
	multiple groups of arguments, and will repeat all instructions for
	each arguments group separately. For example:

	macro stoschar [char]
	 {
	     mov   al,char
	     stosb
	 }

	stoschar 1,2,3,4      ; store four bytes at es:di

	There are some special directives available only inside macro
	definitions. The 'local' directive defines local symbols, which
	will have unique names in every macro call; arguments are local
	symbol names, separated with commas. The 'forward', 'reverse' and
	'common' directives divide macroinstruction into parts, each one
	processed after the previous one processing is finished. The part
	defined using 'forward' directive will be processed for each
	group of multiple arguments, from first to last; the same as
	default macroinstruction behaviour. Local symbol defined in one of
	the parts will be available in all next parts, when processing the
	same group of arguments.

	For example, to create table of addresses to strings, and then
	strings data, use this macro:

	macro strtbl [string]
	 { forward
	     local label
	     dd label
	   forward
	     label db string,0 }

	The 'reverse' directive will cause groups of arguments to be
	processed from last to first; and the 'common' directive will define
	part, which will be processed only once.

	Here's example how to define macro for calling procedures with
	arguments on stack in using the above directives:

	macro stdcall proc,[arg]
	 { reverse push arg
	   common call proc }

	Note that instructions can follow the directive defining part of
	macroinstruction.

	Also, in 'common' part name of the macro argument will be replaced
	with all the argument values, from first to last, separated with
	commas. So we can define next macro for indirectly invoking
	procedures this way:

	macro invoke proc,[arg]
	 { common stdcall [proc],arg }

struc - this is the variant of macro directive used to create data
	structures. When struc macro is used in program, it must be preceded
	by a label. Preprocessor will insert this label at the beginning of
	every symbol starting with a single dot. For example:

	struc pixel x,y,color
	 {
	  .x dw x
	  .y dw y
	  .color db color
	 }

	mypix pixel 10,10,4

	; so we have defined mypix.x, mypix.y and mypix.color variables

	virtual at 0
	  pixel pixel ?,?,?
	end virtual

	; and now also pixel.x, pixel.y, pixel.color offsets

	To handle cases, when one or more of macro params are empty (for
	example just: 'mypix pixel'), you can write something like
	'.x dw x+0', or use 'if <x> eq <>'.

purge - argument is one or more macro names, separated with commas; this
	directive will remove last definition of specified macro; for example
	when you've redefined some macro, you can get previous definition
	back using purge. If the macro has not been defined, you won't get
	any error. When you need to totally undefine some non-preprocessor
	symbol (defined with equ, or labels), use this clever macro:

	macro undefine symbol
	 {
	  local undefined
	  symbol equ undefined
	 }

	For example after 'undefine add', you can't use 'add' instruction,
	but definition and usage of 'add' label is possible. Also, if you
	use '_add equ add', and then 'undefine add', you can define 'add'
	label and have access to 'add' instruction using '_add' symbol.

equ - defines symbolic constant. This directive should be preceded by the
      symbol name, and followed by the symbol value.

2.2.2  Code and format settings

use16 - set code type to 16-bit (this is default code setting).

use32 - set code type to 32-bit (this is default code setting for PE format).

org - argument must be an address value; set from what address this
      code will start in memory.

format - set output file format, can be set binary, MZ or PE; binary
	 is the default format, MZ is an EXE file format, PE is a portable
	 executable file format. When specified format is PE, more format
	 settings can follow; use 'console', 'GUI' or 'native' words to set
	 target subsystem type (subsystem version can follow); 'i386',
	 'i486' or 'i586' to specify target machine type; 'DLL' to create
	 dynamic link library. Use 'on <file>' phrase to specify custom
	 stub program.

segment - define segment at current position (only in MZ format),
	  code will be aligned to paragraph. In segment definition, after
	  segment name, 'use16' or 'use32' is allowed.

section - define section at current position (only in PE format), code will
	  be aligned to page (4096 bytes). First argument is a string
	  containing section name, optional next arguments are section type
	  (code, data, udata, export, import, resource), and section
	  attributes (readable, writeable, executable, shareable,
	  discardable).

entry - define program entry point (only in MZ and PE formats). In MZ format
	argument must be a segment:offset address (like in far jump).

stack - define program stack size (only in MZ and PE formats), when no stack
	is defined, default size of 1000h bytes is used. In MZ format the
	stack location can be defined in segment:offset form. In PE format
	second argument is allowed to define stack commit (first argument
	defines stack reserve).

heap - define 'heap' size in paragraphs (only in MZ and PE formats). In MZ
       format argument is a 16-bit value, defining maximum size of additional
       heap in paragraphs (note that this is heap in addition to stack and
       undefined data; use 'heap 0' to always allocate only memory program
       really needs); default value of 'heap' is FFFFh. In PE format
       argument is a 32-bit value, defining heap reserve; second argument is
       allowed to define heap commit.

data - begin PE format specific data definition. Argument is a number of PE
       data directory, or a predefined data type (export, import, resource).
       Data definition should be ended with 'end data' directive.

2.2.3  Label and constant definitions

label - define label, needed argument is a name of label, optional
	arguments are size of labeled data and 'at <address>' phrase.

load - define constant equal to binary value loaded from file; arguments are
       constant name, optionally constant size (when no size is specified,
       constant will be one byte), then 'from <file>' phrase, after file
       name position in file preceded by a colon can follow.

2.2.4  Other directives

times - repeat instruction n times; arguments are number of repeats and
	instruction to repeat (optionally character ':' can be used to
	separate number and instructions), also % value (current repeat
	number) can be used in instruction, so 'times 5 db %' will create
	01,02,03,04,05 bytes; recurrency is also allowed, so
	'times 3 times % db %' will create 01,01,02,01,02,03 bytes.

repeat - larger version of times directive, repeat has one argument -
	 number of repeats, instructions to repeat are expected in next
	 lines, ended with 'end repeat' directive.

virtual - creates virtual code or data at specified address; this data
	  won't be included in output file, but labels defined there can
	  be useful in other parts of program; argument to virtual is
	  'at <address>' phrase, virtual instructions are expected in
	  next lines, ended with 'end virtual' directive. If directive
	  has no arguments, it uses the current address, the same as
	  'virtual at $'.

if - used to assemble some part of codes, when specified conditions are
     met; argument is a logical expression, in next lines instructions to
     assemble when this expression value is true, then 'end if' directive,
     or 'else', or 'else if' and next logical expression.

end - used to end structures defined with some other directives.

display - display text at the assembly time; arguments are strings or byte
	  values to be displayed.

���������������������������������������������������������������������������

Thanks to:

    Leonid Petroff - for really good work with bugs reporting and many
		     helpful suggestions

    Bartek Uliasz - without him the flat assembler project would never
		    be started

    and all others who helped me (there were many of them)!