ÜÜÜ Ūßßß ßŪ ŪŪ ŪŪ Ü ŪŪÜÜ ÜßßßŪÜ ÜßßßßÜŽßÜŽßßÜßŪŻ ŪŪ ŪŻ ŽŪ ß ŽŪ Ū Ż ŪŪ ÜßßßßßŪŪ ßßßŪÜÜ ŽŪ Ū Ż ŪŪ Ū ŪŪ Ü ŽŪ ŽŪ Ū Ż ßßßßßß ßßßßß ßß ßßßßßß ß ß ß 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
' 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