release 1.40

This commit is contained in:
Tomasz Grysztar 2002-08-04 12:00:00 +00:00
parent 6307fd8c56
commit 17dee461f0
16 changed files with 870 additions and 838 deletions

554
FASM.TXT
View file

@ -1,554 +0,0 @@
ÜÜÜ
Ûßßß ßÛ
ÛÛ
ÛÛ
Ü ÛÛÜÜ ÜßßßÛÜ ÜßßßßÜÞßÜÞßßÜßÛÝ
ÛÛ ÛÝ ÞÛ ß ÞÛ Û Ý
ÛÛ ÜßßßßßÛÛ ßßßÛÜÜ ÞÛ Û Ý
ÛÛ Û ÛÛ Ü ÞÛ ÞÛ Û Ý
ßßßßßß ßßßßß ßß ßßßßßß ß ß ß
flat assembler version 1.39
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 Label and constant definitions
2.2.3 Code and format settings
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. There exists also version for Linux, distributed in
a separate package.
1.4 Output formats
There are four 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 and use of the
diretive 'format COFF' produces object file.
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).
You can also use 'ptr' operator instead of brackets to get the value of
the variable, so 'mov byte ptr myvar,7' is the same as 'mov byte [myvar],7'.
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 = delta - 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)
Symbol concatenation operator: #
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 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.3 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, PE, or COFF; binary
is the default format, MZ is an EXE file format, PE is a portable
executable file format and COFF is a common object file format.
To make Microsoft COFF file, use 'format MS COFF' phrase.
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 and COFF formats).
If output format is PE, code will be aligned to page (4096 bytes).
First argument is a string containing section name (maximum 8
characters), optional next arguments are section type (code, data),
and section attributes (readable, writeable, executable, shareable,
discardable). With PE format you can also specify that section
is one of predefined data types: export, import, resource, fixups.
public - declare the existing symbol as public (only in COFF format), needed
argument is a name of symbol, optional argument is 'as <string>'
(string should be quoted) to make this symbol visible outside
with the different name.
extrn - define the external symbol (only in COFF format), needed argument is
a name of symbol, optional argument is the size of data labeled by
this symbol.
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,
fixups). Data definition should be ended with 'end data' directive.
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)!

View file

@ -1,5 +1,5 @@
flat assembler version 1.39
flat assembler version 1.40
Copyright (c) 1999-2002, Tomasz Grysztar
All rights reserved.
@ -35,4 +35,3 @@ The licence and distribution terms for any publically available
version or derivative of this code cannot be changed. i.e. this code
cannot simply be copied and put under another distribution licence
(including the GNU Public Licence).

View file

@ -10,6 +10,7 @@ assembler:
shr ecx,2
xor eax,eax
rep stos dword [edi]
mov [stub_size],eax
mov [current_pass],0
mov [number_of_sections],0
mov [times_working],0
@ -26,10 +27,12 @@ assembler:
mov [virtual_data],0
mov esi,[source_start]
mov edi,[code_start]
mov [org_origin],edi
mov [org_start],edi
mov [org_sib],0
mov [error_line],0
mov [counter],0
xor eax,eax
mov [org_sib],eax
mov [error_line],eax
mov [counter],eax
mov [number_of_relocations],0
mov [undefined_data_end],0
pass_loop:
@ -61,7 +64,7 @@ assemble_line:
mov eax,[display_buffer]
sub eax,100h
cmp edi,eax
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz source_end
@ -103,7 +106,7 @@ assemble_line:
mov cl,al
shl ecx,16
mov eax,edi
sub eax,[org_start]
sub eax,[org_origin]
cdq
xor ch,ch
cmp [reloc_labels],0
@ -148,13 +151,23 @@ assemble_line:
jmp assemble_line
define_constant:
lods dword [esi]
mov edx,[eax+8]
push edx
cmp [current_pass],0
je get_constant_value
test dl,4
jnz get_constant_value
and dl,not 1
mov [eax+8],dl
get_constant_value:
push eax
lods byte [esi]
push ax
push eax
call get_value
pop bx
pop ebx
mov ch,bl
pop ebx
pop dword [ebx+8]
or ebx,ebx
jz set_org
cmp ebx,10h
@ -331,8 +344,9 @@ org_directive:
org_ok:
mov ecx,edi
sub ecx,eax
mov [org_start],ecx
mov [org_origin],ecx
mov [org_sib],0
mov [org_start],edi
jmp instruction_assembled
label_directive:
lods byte [esi]
@ -357,7 +371,7 @@ label_directive:
mov cl,ah
label_size_ok:
mov eax,edi
sub eax,[org_start]
sub eax,[org_origin]
cdq
mov ebp,[org_sib]
shl ecx,16
@ -367,7 +381,9 @@ label_directive:
lods byte [esi]
cmp al,'('
jne invalid_argument
push dword [ebx+8]
push ebx ecx
and byte [ebx+8],not 1
cmp byte [esi],'.'
je invalid_value
call get_address_value
@ -379,6 +395,7 @@ label_directive:
xchg bl,bh
mov bp,bx
pop ecx ebx
pop dword [ebx+8]
cdq
or ch,[value_type]
jz free_label_reloc_ok
@ -444,12 +461,14 @@ load_directive:
cmp al,8
ja invalid_value
mov [operand_size],al
lods byte [esi]
cmp al,82h
jne invalid_argument
mov dword [value],0
mov dword [value+4],0
lods word [esi]
cmp ax,'('
cmp ax,82h+'(' shl 8
jne invalid_argument
cmp byte [esi],0
jne load_from_code
inc esi
lea edx,[esi+4]
mov eax,[esi]
lea esi,[esi+4+eax+1]
@ -474,18 +493,37 @@ load_directive:
load_position_ok:
xor al,al
call lseek
mov dword [value],0
mov dword [value+4],0
movzx ecx,[operand_size]
mov edx,value
call read
jc error_reading_file
call close
value_loaded:
mov eax,dword [value]
mov edx,dword [value+4]
pop ebx
xor cx,cx
jmp make_constant
load_from_code:
cmp byte [esi],'.'
je invalid_value
call get_relative_offset
neg eax
cmp [value_type],0
jne invalid_use_of_symbol
push esi edi
mov esi,edi
sub esi,eax
jc value_out_of_range
cmp esi,[org_start]
jb value_out_of_range
mov edi,value
movzx ecx,[operand_size]
cmp ecx,eax
ja value_out_of_range
rep movs byte [edi],[esi]
pop edi esi
jmp value_loaded
display_directive:
push esi edi
prepare_display:
@ -505,7 +543,7 @@ display_directive:
stos byte [edi]
display_next:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz do_display
@ -608,7 +646,7 @@ virtual_directive:
virtual_at_current:
dec esi
mov eax,edi
sub eax,[org_start]
sub eax,[org_origin]
xor bx,bx
xor cx,cx
mov [value_type],0
@ -625,14 +663,17 @@ virtual_directive:
mov word [ebx],virtual_directive-assembler
neg eax
add eax,edi
xchg [org_start],eax
xchg [org_origin],eax
mov [ebx+4],eax
mov [ebx+8],edx
mov al,[virtual_data]
mov [ebx+2],al
mov al,[reloc_labels]
mov [ebx+3],al
mov [ebx+0Ch],edi
mov eax,edi
xchg eax,[org_start]
mov [ebx+0Ch],eax
mov [ebx+10h],edi
or [virtual_data],-1
mov [reloc_labels],0
cmp [value_type],1
@ -643,7 +684,7 @@ virtual_directive:
jmp instruction_assembled
allocate_structure_data:
mov ebx,[structures_buffer]
sub ebx,10h
sub ebx,14h
cmp ebx,[additional_memory]
jb out_of_memory
mov [structures_buffer],ebx
@ -668,7 +709,7 @@ virtual_directive:
cmp word [ebx],repeat_directive-assembler
je no_such_structure
repeat_structure_ok:
add ebx,10h
add ebx,14h
jmp scan_structures
no_such_structure:
stc
@ -681,16 +722,18 @@ virtual_directive:
mov al,[ebx+3]
mov [reloc_labels],al
mov eax,[ebx+4]
mov [org_start],eax
mov [org_origin],eax
mov eax,[ebx+8]
mov [org_sib],eax
mov edi,[ebx+0Ch]
mov eax,[ebx+0Ch]
mov [org_start],eax
mov edi,[ebx+10h]
remove_structure_data:
push esi edi
mov esi,[structures_buffer]
mov ecx,ebx
sub ecx,esi
lea edi,[esi+10h]
lea edi,[esi+14h]
mov [structures_buffer],edi
shr ecx,2
rep movs dword [edi],[esi]
@ -916,7 +959,7 @@ data_bytes:
stos byte [edi]
byte_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -932,6 +975,9 @@ data_bytes:
inc esi
lods dword [esi]
mov ecx,eax
lea eax,[edi+ecx]
cmp eax,[display_buffer]
ja out_of_memory
rep movs byte [edi],[esi]
inc esi
jmp byte_ok
@ -973,7 +1019,7 @@ data_words:
stos word [edi]
word_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -987,6 +1033,9 @@ data_words:
lods dword [esi]
mov ecx,eax
jecxz word_string_ok
lea eax,[edi+ecx*2]
cmp eax,[display_buffer]
ja out_of_memory
xor ah,ah
copy_word_string:
lods byte [esi]
@ -1026,20 +1075,20 @@ data_dwords:
cmp al,'('
jne invalid_operand
mov al,[value_type]
push ax
push eax
cmp byte [esi],'.'
je invalid_value
call get_word_value
call mark_relocation
stos word [edi]
pop ax
pop eax
mov [value_type],al
mov ax,dx
call mark_relocation
stos word [edi]
dword_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -1083,20 +1132,20 @@ data_pwords:
cmp al,'('
jne invalid_operand
mov al,[value_type]
push ax
push eax
cmp byte [esi],'.'
je invalid_value
call get_dword_value
call mark_relocation
stos dword [edi]
pop ax
pop eax
mov [value_type],al
mov ax,dx
call mark_relocation
stos word [edi]
pword_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -1126,7 +1175,7 @@ data_qwords:
stos dword [edi]
qword_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -1178,7 +1227,7 @@ data_twords:
add esi,12
tbyte_ok:
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
lods byte [esi]
or al,al
jz data_end
@ -1237,7 +1286,7 @@ data_file:
add edi,ecx
jc out_of_memory
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
call read
jc error_reading_file
call close
@ -1253,7 +1302,7 @@ data_file:
add edi,ecx
jc out_of_memory
cmp edi,[display_buffer]
jae out_of_memory
ja out_of_memory
jmp check_for_next_name
reserve_bytes:
lods byte [esi]
@ -1271,7 +1320,7 @@ reserve_bytes:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_bytes
@ -1317,7 +1366,7 @@ reserve_words:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_words
@ -1351,7 +1400,7 @@ reserve_dwords:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_dwords
@ -1382,7 +1431,7 @@ reserve_pwords:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_words
@ -1410,7 +1459,7 @@ reserve_qwords:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_dwords
@ -1437,7 +1486,7 @@ reserve_twords:
add edx,edi
jc out_of_memory
cmp edx,[display_buffer]
jae out_of_memory
ja out_of_memory
push edi
cmp [next_pass_needed],0
je zero_words
@ -1483,7 +1532,7 @@ int_instruction:
stos word [edi]
jmp instruction_assembled
aa_instruction:
push ax
push eax
mov bl,10
cmp byte [esi],'('
jne .store
@ -1497,7 +1546,7 @@ aa_instruction:
.store:
cmp [operand_size],0
jne invalid_operand
pop ax
pop eax
mov ah,bl
stos word [edi]
jmp instruction_assembled
@ -2482,7 +2531,6 @@ test_instruction:
inc [base_code]
call store_instruction
jmp instruction_assembled
test_mem_imm:
mov al,[operand_size]
cmp al,1
@ -3252,14 +3300,14 @@ lea_instruction:
cmp al,','
jne invalid_operand
mov al,[operand_size]
push ax
push eax
mov [operand_size],0
lods byte [esi]
call get_size_operator
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
cmp al,2
je lea_16bit
cmp al,4
@ -3339,7 +3387,7 @@ enter_instruction:
call get_word_value
cmp [value_type],0
jne invalid_use_of_symbol
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -3355,7 +3403,7 @@ enter_instruction:
jne invalid_operand
call get_byte_value
mov dl,al
pop bx
pop ebx
mov al,0C8h
stos byte [edi]
mov ax,bx
@ -3375,7 +3423,7 @@ sh_instruction:
call get_address
push edx bx cx
mov al,[operand_size]
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -3390,7 +3438,7 @@ sh_instruction:
lods byte [esi]
cmp al,11h
jne invalid_operand
pop ax cx bx edx
pop eax cx bx edx
cmp al,1
je sh_mem_cl_8bit
cmp al,2
@ -3426,7 +3474,7 @@ sh_instruction:
sh_mem_imm_size_ok:
call get_byte_value
mov byte [value],al
pop ax cx bx edx
pop eax cx bx edx
cmp al,1
je sh_mem_imm_8bit
cmp al,2
@ -3486,7 +3534,7 @@ sh_instruction:
or al,11000000b
or [postbyte_register],al
mov al,ah
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -3501,7 +3549,7 @@ sh_instruction:
lods byte [esi]
cmp al,11h
jne invalid_operand
pop ax
pop eax
mov bl,[postbyte_register]
cmp al,1
je sh_reg_cl_8bit
@ -3539,7 +3587,7 @@ sh_instruction:
sh_reg_imm_size_ok:
call get_byte_value
mov byte [value],al
pop ax
pop eax
mov bl,[postbyte_register]
cmp al,1
je sh_reg_imm_8bit
@ -3624,7 +3672,7 @@ shd_instruction:
jne invalid_operand
xor al,al
xchg al,[operand_size]
push ax
push eax
lods byte [esi]
call get_size_operator
cmp al,'('
@ -3634,7 +3682,7 @@ shd_instruction:
lods byte [esi]
cmp al,11h
jne invalid_operand
pop ax cx bx edx
pop eax cx bx edx
cmp al,2
je shd_mem_reg_cl_16bit
cmp al,4
@ -3659,7 +3707,7 @@ shd_instruction:
shd_mem_reg_imm_size_ok:
call get_byte_value
mov byte [value],al
pop ax cx bx edx
pop eax cx bx edx
cmp al,2
je shd_mem_reg_imm_16bit
cmp al,4
@ -3924,7 +3972,7 @@ bt_instruction:
bt_mem_imm:
xor al,al
xchg al,[operand_size]
push ax
push eax
lods byte [esi]
call get_size_operator
cmp al,'('
@ -3938,7 +3986,7 @@ bt_instruction:
mov [extended_code],0BAh
call get_byte_value
mov byte [value],al
pop ax
pop eax
cmp al,2
je bt_mem_imm_16bit
cmp al,4
@ -4013,7 +4061,7 @@ bt_instruction:
bt_reg_imm:
xor al,al
xchg al,[operand_size]
push ax
push eax
lods byte [esi]
call get_size_operator
cmp al,'('
@ -4026,7 +4074,7 @@ bt_instruction:
bt_reg_imm_size_ok:
call get_byte_value
mov byte [value],al
pop ax
pop eax
cmp al,2
je bt_reg_imm_16bit
cmp al,4
@ -4069,6 +4117,7 @@ bs_instruction:
cmp al,','
jne invalid_operand
lods byte [esi]
call get_size_operator
cmp al,10h
je bs_reg_reg
cmp al,'['
@ -4500,7 +4549,7 @@ in_instruction:
cmp al,','
jne invalid_operand
mov al,ah
push ax
push eax
mov [operand_size],0
lods byte [esi]
call get_size_operator
@ -4513,7 +4562,7 @@ in_instruction:
lods byte [esi]
cmp al,22h
jne invalid_operand
pop ax
pop eax
cmp al,1
je in_al_dx
cmp al,2
@ -4544,7 +4593,7 @@ in_instruction:
in_imm_size_ok:
call get_byte_value
mov dl,al
pop ax
pop eax
cmp al,1
je in_al_imm
cmp al,2
@ -5176,13 +5225,13 @@ jmp_instruction:
cmp [jump_type],1
je invalid_operand
call get_word_value
push ax
push eax
inc esi
lods byte [esi]
cmp al,'('
jne invalid_operand
mov al,[value_type]
push ax [symbol_identifier]
push eax [symbol_identifier]
cmp byte [esi],'.'
je invalid_value
mov bl,[operand_size]
@ -5204,9 +5253,9 @@ jmp_instruction:
call mark_relocation
stos word [edi]
jmp_far_segment:
pop [symbol_identifier] ax
pop [symbol_identifier] eax
mov [value_type],al
pop ax
pop eax
call mark_relocation
stos word [edi]
jmp instruction_assembled
@ -5316,7 +5365,7 @@ movs_instruction:
jnz invalid_address
cmp [segment_register],1
ja invalid_address
push bx
push ebx
lods byte [esi]
cmp al,','
jne invalid_operand
@ -5325,7 +5374,7 @@ movs_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop dx
pop edx
or eax,eax
jnz invalid_address
or bl,ch
@ -5949,7 +5998,7 @@ movd_instruction:
cmp ah,4
jne invalid_operand_size
mov [operand_size],0
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -5959,7 +6008,7 @@ movd_instruction:
lods byte [esi]
call convert_mmx_register
call make_mmx_prefix
pop bx
pop ebx
shl al,3
or bl,al
or bl,11000000b
@ -5972,7 +6021,7 @@ movd_instruction:
movd_mmreg:
call convert_mmx_register
call make_mmx_prefix
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -5984,7 +6033,7 @@ movd_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
mov [postbyte_register],al
test [operand_size],not 4
jnz invalid_operand_size
@ -5997,7 +6046,7 @@ movd_instruction:
call convert_register
cmp ah,4
jne invalid_operand_size
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6048,7 +6097,7 @@ movq_instruction:
movq_mmreg:
lods byte [esi]
call convert_mmx_register
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6060,7 +6109,7 @@ movq_instruction:
call get_address
test [operand_size],not 8
jnz invalid_operand_size
pop ax
pop eax
mov [postbyte_register],al
mov [base_code],0Fh
cmp [operand_size],16
@ -6074,7 +6123,7 @@ movq_instruction:
call store_instruction
jmp instruction_assembled
movq_mmreg_mmreg:
pop bx
pop ebx
lods byte [esi]
call convert_mmx_register
shl bl,3
@ -6123,7 +6172,7 @@ movdq_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6134,14 +6183,14 @@ movdq_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
mov [postbyte_register],al
mov [base_code],0Fh
mov [extended_code],6Fh
call store_mmx_instruction
jmp instruction_assembled
movdq_mmreg_mmreg:
pop bx
pop ebx
lods byte [esi]
call convert_mmx_register
cmp ah,16
@ -6223,7 +6272,7 @@ mmx_instruction:
lods byte [esi]
call convert_mmx_register
call make_mmx_prefix
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6235,14 +6284,14 @@ mmx_instruction:
jne invalid_operand
mmx_mmreg_mem:
call get_address
pop ax
pop eax
mov [postbyte_register],al
call store_mmx_instruction
jmp instruction_assembled
mmx_mmreg_mmreg:
lods byte [esi]
call convert_mmx_register
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6262,7 +6311,7 @@ mmx_ps_instruction:
lods byte [esi]
call convert_mmx_register
call make_mmx_prefix
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6289,7 +6338,7 @@ mmx_ps_instruction:
mov [extended_code],ah
sub al,0Ch
shl al,1
pop bx
pop ebx
shl al,3
or bl,al
or bl,11000000b
@ -6408,7 +6457,7 @@ pshufd_instruction:
call convert_mmx_register
cmp ah,[mmx_size]
jne invalid_operand_size
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6419,14 +6468,14 @@ pshufd_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
mov [postbyte_register],al
call store_mmx_instruction
jmp mmx_imm8
pshufw_mmreg_mmreg:
lods byte [esi]
call convert_mmx_register
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6481,7 +6530,7 @@ sse_instruction:
cmp ah,16
jne invalid_operand_size
sse_reg:
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -6491,7 +6540,7 @@ sse_instruction:
je sse_xmmreg_xmmreg
call get_size_operator
call get_address
pop ax
pop eax
mov [postbyte_register],al
cmp [operand_size],0
je sse_mem_size_ok
@ -6513,7 +6562,7 @@ sse_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6525,6 +6574,7 @@ sse_instruction:
stos byte [edi]
cmp [extended_code],0C6h
jne instruction_assembled
jmp mmx_imm8
ps_dq_instruction:
mov bl,al
lods byte [esi]
@ -6623,7 +6673,7 @@ movhlps_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6724,7 +6774,7 @@ sse_cmp_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6736,7 +6786,7 @@ sse_cmp_instruction:
jne invalid_operand
mov [operand_size],0
call get_address
pop ax
pop eax
mov [postbyte_register],al
cmp [operand_size],0
je sse_cmp_xmmreg_mem_store
@ -6770,7 +6820,7 @@ sse_cmp_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6796,7 +6846,7 @@ cvtpi2pd_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -6808,7 +6858,7 @@ cvtpi2pd_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
mov [postbyte_register],al
cmp [operand_size],0
je cvtpi_size_ok
@ -6822,7 +6872,7 @@ cvtpi2pd_instruction:
call convert_mmx_register
cmp ah,8
jne invalid_operand_size
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6848,7 +6898,7 @@ cvtsi2sd_instruction:
call convert_mmx_register
cmp ah,16
jne invalid_operand_size
push ax
push eax
mov [operand_size],0
lods byte [esi]
cmp al,','
@ -6860,7 +6910,7 @@ cvtsi2sd_instruction:
cmp al,'['
jne invalid_operand
call get_address
pop ax
pop eax
mov [postbyte_register],al
cmp [operand_size],0
je cvtsi_size_ok
@ -6874,7 +6924,7 @@ cvtsi2sd_instruction:
call convert_register
cmp [operand_size],4
jne invalid_operand_size
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -6973,7 +7023,7 @@ maskmovdqu_instruction:
call convert_mmx_register
cmp ah,cl
jne invalid_operand_size
push ax
push eax
lods byte [esi]
cmp al,','
jne invalid_operand
@ -6982,7 +7032,7 @@ maskmovdqu_instruction:
jne invalid_operand
lods byte [esi]
call convert_mmx_register
pop bx
pop ebx
shl bl,3
or bl,al
or bl,11000000b
@ -7231,8 +7281,6 @@ store_instruction:
address_bp:
mov al,110b
postbyte_16bit:
cmp ch,1
je address_8bit_value
cmp ch,2
je address_16bit_value
or ch,ch
@ -7308,8 +7356,6 @@ store_instruction:
or ah,bl
and bh,111b
or ah,bh
cmp ch,1
je sib_address_8bit_value
test ch,4
jnz sib_address_32bit_value
cmp ch,2
@ -7372,8 +7418,6 @@ store_instruction:
and al,111b
cmp al,4
je zero_index_register
cmp ch,1
je simple_address_8bit_value
test ch,4
jnz simple_address_32bit_value
cmp ch,2
@ -7434,8 +7478,11 @@ store_instruction:
jz address_relocation_ok
mov al,2
xchg [value_type],al
mov ebx,[address_symbol]
xchg ebx,[symbol_identifier]
call mark_relocation
mov [value_type],al
mov [symbol_identifier],ebx
address_relocation_ok:
mov eax,edx
stos dword [edi]

View file

@ -32,6 +32,10 @@ start:
je information
inc eax
mov [output_file],eax
movzx ecx,byte [eax-1]
add eax,ecx
cmp byte [eax],0
jne information
mov di,characters
mov cx,100h
@ -190,10 +194,13 @@ macro_block dd ?
macro_block_line_number dd ?
struc_name dd ?
current_locals_prefix dd ?
anonymous_reverse dd ?
anonymous_forward dd ?
labels_list dd ?
label_hash dd ?
org_start dd ?
org_origin dd ?
org_sib dd ?
org_start dd ?
undefined_data_start dd ?
undefined_data_end dd ?
counter dd ?
@ -207,6 +214,7 @@ current_offset dd ?
value dq ?
fp_value rd 8
symbol_identifier dd ?
address_symbol dd ?
format_flags dd ?
number_of_relocations dd ?
number_of_sections dd ?
@ -217,6 +225,7 @@ current_section dd ?
machine dw ?
subsystem dw ?
subsystem_version dd ?
image_base dd ?
macro_status db ?
parenthesis_stack db ?

View file

@ -247,35 +247,100 @@ xms_call dd ? ; XMS driver pointer
xms_handle dw ? ; handle of XMS memory block
open:
push edx esi di
mov esi,edx
mov di,buffer
.name:
lods byte [esi]
stos byte [di]
or al,al
jnz .name
mov dx,buffer
push esi di
call convert_path
mov ax,3D00h
int 21h
mov bx,ax
pop di esi edx
pop di esi
ret
create:
push edx esi di
convert_path:
mov esi,edx
mov di,buffer
.name:
copy_path:
lods byte [esi]
stos byte [es:di]
cmp al,'%'
je environment_variable
cmp al,'/'
jne path_char_ok
mov al,'\'
path_char_ok:
stos byte [di]
or al,al
jnz .name
jnz copy_path
sub di,buffer
cmp di,4000h
ja out_of_memory
mov dx,buffer
ret
environment_variable:
mov ebx,esi
find_variable_end:
lods byte [esi]
or al,al
jz not_environment_variable
cmp al,'%'
jne find_variable_end
push esi
mov si,cs
neg si
add si,[2Ch]
movsx esi,si
sal esi,4
compare_variable_names:
mov edx,ebx
compare_character:
lods byte [esi]
mov ah,[edx]
inc edx
cmp al,'='
je end_of_variable_name
cmp ah,'%'
je next_variable
sub ah,al
jz compare_character
cmp ah,20h
jne next_variable
cmp al,41h
jb next_variable
cmp al,5Ah
jna compare_character
next_variable:
lods byte [esi]
or al,al
jnz next_variable
cmp byte [esi],0
jne compare_variable_names
pop esi
jmp copy_path
end_of_variable_name:
cmp ah,'%'
jne next_variable
copy_variable_value:
lods byte [esi]
cmp al,'/'
jne value_char_ok
mov al,'\'
value_char_ok:
stos byte [di]
or al,al
jnz copy_variable_value
dec di
pop esi
jmp copy_path
not_environment_variable:
mov al,'%'
stos byte [di]
mov esi,ebx
jmp copy_path
create:
push esi di
call convert_path
mov ah,3Ch
xor cx,cx
int 21h
mov bx,ax
pop di esi edx
pop di esi
ret
write:
push edx esi edi ebp
@ -510,7 +575,91 @@ assembler_error:
int 21h
jmp exit_program
times 12 nop
make_timestamp:
mov ah,2Ah
int 21h
push dx cx
movzx ecx,cx
mov eax,ecx
sub eax,1970
mov ebx,365
mul ebx
mov ebp,eax
mov eax,ecx
sub eax,1969
shr eax,2
add ebp,eax
mov eax,ecx
sub eax,1901
mov ebx,100
div ebx
sub ebp,eax
mov eax,ecx
xor edx,edx
sub eax,1601
mov ebx,400
div ebx
add ebp,eax
movzx ecx,byte [esp+3]
mov eax,ecx
dec eax
mov ebx,30
mul ebx
add ebp,eax
cmp ecx,8
jbe months_correction
mov eax,ecx
sub eax,7
shr eax,1
add ebp,eax
mov ecx,8
months_correction:
mov eax,ecx
shr eax,1
add ebp,eax
sub ebp,2
cmp ecx,2
jbe day_correction_ok
pop cx
test ecx,11b
jnz day_correction_ok
xor edx,edx
mov eax,ecx
mov ebx,100
div ebx
or edx,edx
jnz day_correction
mov eax,ecx
mov ebx,400
div ebx
or edx,edx
jnz day_correction_ok
day_correction:
inc ebp
day_correction_ok:
pop dx
movzx eax,dl
dec eax
add eax,ebp
mov ebx,24
mul ebx
push eax
mov ah,2Ch
int 21h
pop eax
push dx
movzx ebx,ch
add eax,ebx
mov ebx,60
mul ebx
movzx ebx,cl
add eax,ebx
mov ebx,60
mul ebx
pop dx
movzx ebx,dh
add eax,ebx
ret
character db ?,0
bytes_count dd ?

View file

@ -36,17 +36,17 @@ convert_expression:
and bh,0F0h
cmp bl,bh
ja push_operator
pop bx
pop ebx
mov byte [edi],bl
inc edi
jmp operators_loop
push_operator:
push ax
push eax
jmp expression_loop
expression_end:
cmp esp,ebp
je expression_converted
pop ax
pop eax
stos byte [edi]
jmp expression_end
expression_converted:
@ -382,6 +382,10 @@ get_fp_value:
je fp_character_exp
cmp al,'e'
je fp_character_exp
cmp al,'F'
je fp_last_character
cmp al,'f'
je fp_last_character
cmp al,'0'
jb not_fp_value
cmp al,'9'
@ -395,13 +399,18 @@ get_fp_value:
fp_character_exp:
cmp ah,1
ja not_fp_value
mov ah,2
or ah,2
cmp ecx,1
jne fp_character_ok
cmp byte [esi],'+'
je fp_exp_sign
cmp byte [esi],'-'
jne fp_character_ok
fp_last_character:
cmp cl,1
jne not_fp_value
or ah,4
jmp fp_character_ok
fp_exp_sign:
inc esi
cmp byte [esi],1Ah
@ -442,6 +451,10 @@ get_fp_value:
je fp_exponent
cmp al,'e'
je fp_exponent
cmp al,'F'
je fp_done
cmp al,'f'
je fp_done
sub al,30h
mov edi,fp_value+16
xor edx,edx
@ -476,6 +489,10 @@ get_fp_value:
je fp_exponent
cmp al,'e'
je fp_exponent
cmp al,'F'
je fp_done
cmp al,'f'
je fp_done
inc [fp_format]
cmp [fp_format],80h
jne fp_counter_ok
@ -524,11 +541,14 @@ get_fp_value:
movzx eax,byte [esi]
inc esi
sub al,30h
cmp al,10
jae exponent_ok
imul edx,10
cmp edx,8000h
jae value_out_of_range
add edx,eax
loop get_exponent
exponent_ok:
mov edi,fp_value
or edx,edx
jz fp_done
@ -773,9 +793,12 @@ calculate_expression:
je calculate_add
cmp al,81h
je calculate_sub
cmp [next_pass_needed],0
jne absolute_values_calculation
mov ah,[ebx+12]
or ah,[edi+12]
jnz invalid_use_of_symbol
absolute_values_calculation:
cmp al,90h
je calculate_mul
cmp al,91h
@ -910,7 +933,7 @@ calculate_expression:
mov [edi+16],eax
get_current_offset:
mov eax,[current_offset]
sub eax,[org_start]
sub eax,[org_origin]
cdq
stos dword [edi]
mov eax,edx
@ -937,12 +960,12 @@ calculate_expression:
add edi,0Ch
jmp calculation_loop
calculate_add:
cmp [next_pass_needed],0
jne add_values
mov ecx,[ebx+16]
cmp byte [edi+12],0
je add_values
mov ecx,[edi+16]
cmp [next_pass_needed],0
jne add_values
cmp byte [ebx+12],0
jne invalid_use_of_symbol
add_values:
@ -1001,14 +1024,12 @@ calculate_expression:
ret
calculate_sub:
xor ah,ah
cmp [next_pass_needed],0
jne sub_values
mov ah,[ebx+12]
mov al,[edi+12]
or al,al
jz sub_values
cmp al,ah
jne invalid_use_of_symbol
jne invalid_sub
xor ah,ah
cmp [output_format],4
jne sub_values
@ -1016,7 +1037,7 @@ calculate_expression:
cmp ecx,[ebx+16]
je sub_values
cmp ecx,[current_section]
jne invalid_use_of_symbol
jne invalid_sub
mov ah,3
sub_values:
mov [ebx+12],ah
@ -1036,6 +1057,10 @@ calculate_expression:
call sub_register
pop esi
jmp calculation_loop
invalid_sub:
cmp [next_pass_needed],0
jne sub_values
jmp invalid_use_of_symbol
sub_register:
or cl,cl
jz add_register_done
@ -1059,19 +1084,19 @@ calculate_expression:
xchg eax,[edi+12]
mov [ebx+12],eax
mul_start:
push esi dx
push esi edx
mov esi,ebx
xor bl,bl
test dword [esi+4],1 shl 31
jz mul_first_sign_ok
bt dword [esi+4],31
jnc mul_first_sign_ok
not dword [esi]
not dword [esi+4]
add dword [esi],1
adc dword [esi+4],0
not bl
mul_first_sign_ok:
test dword [edi+4],1 shl 31
jz mul_second_sign_ok
bt dword [edi+4],31
jnc mul_second_sign_ok
not dword [edi]
not dword [edi+4]
add dword [edi],1
@ -1107,7 +1132,7 @@ calculate_expression:
add dword [esi],1
adc dword [esi+4],0
mul_ok:
pop dx
pop edx
or dx,dx
jz mul_calculated
cmp word [edi+8],0
@ -1149,10 +1174,10 @@ calculate_expression:
pop esi
jmp calculation_loop
calculate_div:
push esi dx
push esi edx
mov esi,ebx
call div_64
pop dx
pop edx
or dx,dx
jz div_calculated
cmp byte [esi+8],0
@ -1260,8 +1285,8 @@ calculate_expression:
jmp calculation_loop
calculate_shl:
mov eax,dword [edi+4]
test eax,1 shl 31
jnz shl_negative
bt eax,31
jc shl_negative
or eax,eax
jnz zero_value
mov ecx,[edi]
@ -1290,8 +1315,8 @@ calculate_expression:
adc dword [edi+4],0
calculate_shr:
mov eax,dword [edi+4]
test eax,1 shl 31
jnz shr_negative
bt eax,31
jc shr_negative
or eax,eax
jnz zero_value
mov ecx,[edi]
@ -1324,10 +1349,13 @@ calculate_expression:
mov dword [ebx+4],0
jmp calculation_loop
calculate_not:
cmp [next_pass_needed],0
jne not_ok
cmp word [edi+8],0
jne invalid_expression
cmp byte [edi+12],0
jne invalid_use_of_symbol
not_ok:
cmp [value_size],1
je not_byte
cmp [value_size],2
@ -1373,10 +1401,13 @@ calculate_expression:
add edi,14h
jmp calculation_loop
calculate_neg:
cmp [next_pass_needed],0
jne neg_ok
cmp word [edi+8],0
jne invalid_expression
cmp byte [edi+12],0
jne invalid_use_of_symbol
neg_ok:
mov eax,[edi]
mov edx,[edi+4]
mov dword [edi],0
@ -1386,17 +1417,14 @@ calculate_expression:
add edi,14h
jmp calculation_loop
calculate_rva:
cmp [next_pass_needed],0
jne rva_ok
cmp word [edi+8],0
jne invalid_expression
cmp [output_format],3
jne invalid_use_of_symbol
mov al,[edi+12]
cmp al,2
je rva_ok
or al,al
jnz invalid_use_of_symbol
cmp [next_pass_needed],0
je invalid_use_of_symbol
cmp byte [edi+12],2
jne invalid_use_of_symbol
rva_ok:
mov byte [edi+12],0
mov eax,[header_data]
@ -1415,16 +1443,16 @@ calculate_expression:
je value_out_of_range
jmp div_done
divider_ok:
test dword [esi+4],1 shl 31
jz div_first_sign_ok
bt dword [esi+4],31
jnc div_first_sign_ok
not dword [esi]
not dword [esi+4]
add dword [esi],1
adc dword [esi+4],0
not bl
div_first_sign_ok:
test dword [edi+4],1 shl 31
jz div_second_sign_ok
bt dword [edi+4],31
jnc div_second_sign_ok
not dword [edi]
not dword [edi+4]
add dword [edi],1
@ -1498,8 +1526,8 @@ calculate_expression:
shr eax,9
jnc fp_dword_ok
inc eax
test eax,1 shl 23
jz fp_dword_ok
bt eax,23
jnc fp_dword_ok
and eax,1 shl 23 - 1
inc bx
shr eax,1
@ -1534,8 +1562,8 @@ calculate_expression:
jnc fp_qword_ok
add eax,1
adc edx,0
test edx,1 shl 20
jz fp_qword_ok
bt edx,20
jnc fp_qword_ok
and edx,1 shl 20 - 1
inc bx
shr edx,1
@ -1628,7 +1656,6 @@ get_dword_value:
mov [value_size],4
mov [forced_size],2
call calculate_expression
got_dword_value:
cmp word [edi+8],0
jne invalid_value
mov al,[edi+12]
@ -1639,8 +1666,8 @@ get_dword_value:
je dword_positive
cmp dword [edi+4],-1
jne range_exceeded
test eax,1 shl 31
jz range_exceeded
bt eax,31
jnc range_exceeded
dword_positive:
ret
get_pword_value:
@ -1730,6 +1757,8 @@ get_address:
jne calculate_address
lods byte [esi]
sub al,70h
cmp al,2
jb invalid_address_size
cmp al,4
ja invalid_address_size
mov [address_size],al
@ -1741,6 +1770,8 @@ get_address_value:
push address_ok
calculate_address:
call calculate_expression
mov eax,[edi+16]
mov [address_symbol],eax
mov al,[edi+12]
mov [value_type],al
cmp al,1
@ -1849,28 +1880,43 @@ get_relative_offset:
mov word [esi+5],')' shl 8 + 81h
call calculation_loop
pop esi
jmp got_dword_value
cmp word [edi+8],0
jne invalid_value
mov al,[edi+12]
mov [value_type],al
mov eax,[edi]
cmp dword [edi+4],0
je offset_positive
cmp dword [edi+4],-1
jne range_exceeded
bt eax,31
jnc range_exceeded
ret
offset_positive:
bt eax,31
jc range_exceeded
ret
calculate_logical_expression:
call get_logical_value
logical_loop:
push ax
push eax
lods byte [esi]
cmp al,'|'
je logical_or
cmp al,'&'
je logical_and
dec esi
pop ax
pop eax
ret
logical_or:
call get_logical_value
pop bx
pop ebx
or al,bl
jmp logical_loop
logical_and:
call get_logical_value
pop bx
pop ebx
and al,bl
jmp logical_loop
@ -1881,7 +1927,7 @@ get_logical_value:
inc esi
or al,-1
negation_ok:
push ax
push eax
cmp byte [esi],'{'
je logical_expression
push esi
@ -2013,11 +2059,11 @@ get_logical_value:
pop esi
call get_value
mov bl,[value_type]
push eax edx bx
push eax edx ebx
lods byte [esi]
mov [compare_type],al
call get_value
pop bx
pop ebx
cmp [next_pass_needed],0
jne values_ok
cmp bl,[value_type]
@ -2093,12 +2139,12 @@ get_logical_value:
logical_expression:
inc esi
call calculate_logical_expression
push ax
push eax
lods byte [esi]
cmp al,'}'
jne invalid_expression
pop ax
pop eax
logical_value_ok:
pop bx
pop ebx
xor al,bl
ret

View file

@ -176,6 +176,8 @@ segment_directive:
mov edx,edi
xor al,al
rep stos byte [edi]
mov [org_origin],edi
mov [org_sib],0
mov [org_start],edi
mov eax,edx
call undefined_data
@ -539,32 +541,24 @@ format_pe:
mov [machine],14Ch ; intel 80386
mov [subsystem],3 ; console subsystem
mov [subsystem_version],3 + 10 shl 16
mov [image_base],400000h
xor edx,edx
pe_settings:
cmp byte [esi],84h
je get_stub_name
cmp byte [esi],80h
je get_pe_base
cmp byte [esi],1Bh
jne pe_settings_ok
lods byte [esi]
lods byte [esi]
test al,80h+40h
jz subsystem_setting
test al,80h
jz machine_setting
cmp al,80h
je pe_dll
jmp pe_settings
pe_dll:
jne pe_settings
bts [format_flags],8
jc symbol_already_defined
jmp pe_settings
machine_setting:
bts [format_flags],6
jc symbol_already_defined
and ax,3Fh
add ax,149h
mov [machine],ax
jmp pe_settings
subsystem_setting:
bts [format_flags],7
jc symbol_already_defined
@ -582,6 +576,23 @@ format_pe:
add esi,12
mov [subsystem_version],eax
jmp pe_settings
get_pe_base:
bts [format_flags],9
jc symbol_already_defined
lods word [esi]
cmp ah,'('
jne invalid_argument
cmp byte [esi],'.'
je invalid_value
push edx edi
add edi,[stub_size]
call get_dword_value
pop edi edx
cmp [value_type],0
jne invalid_use_of_symbol
mov [image_base],eax
cmp byte [esi],84h
jne pe_settings_ok
get_stub_name:
lods byte [esi]
lods word [esi]
@ -624,10 +635,11 @@ format_pe:
mov word [edx+4],ax
mov dword [edx+14h],0E0h ; size of optional header
mov dword [edx+16h],10B818Eh; flags and magic value
mov dword [edx+34h],400000h ; base of image
mov dword [edx+38h],1000h ; section alignment
mov dword [edx+3Ch],200h ; file alignment
mov word [edx+40h],1 ; OS version
mov eax,[image_base]
mov dword [edx+34h],eax
mov ax,[subsystem]
mov [edx+5Ch],ax
mov eax,[subsystem_version]
@ -660,7 +672,9 @@ format_pe:
neg eax
add eax,edi
sub eax,[edx+34h]
mov [org_start],eax
mov [org_origin],eax
mov [org_sib],0
mov [org_start],edi
bt [format_flags],8
jnc instruction_assembled
or dword [edx+16h],2000h
@ -730,7 +744,9 @@ pe_section:
mov eax,edi
sub eax,[ebx+0Ch]
sub eax,[edx+34h]
mov [org_start],eax
mov [org_origin],eax
mov [org_sib],0
mov [org_start],edi
or [reloc_labels],-1
get_section_flags:
lods byte [esi]
@ -739,14 +755,6 @@ pe_section:
cmp al,19h
je section_flag
dec esi
cmp al,13h
jne instruction_assembled
lods byte [esi]
lods byte [esi]
mov [code_type],al
cmp al,16
jne instruction_assembled
or byte [ebx+24h],4
jmp instruction_assembled
set_directory:
movzx eax,byte [esi]
@ -860,11 +868,8 @@ data_directive:
jmp remove_structure_data
pe_entry:
lods byte [esi]
call get_size_operator
cmp al,'('
jne invalid_argument
test ah,not 4
jnz invalid_address
cmp byte [esi],'.'
je invalid_value
call get_dword_value
@ -882,11 +887,8 @@ pe_entry:
jmp instruction_assembled
pe_stack:
lods byte [esi]
call get_size_operator
cmp al,'('
jne invalid_argument
test ah,not 4
jnz invalid_address
cmp byte [esi],'.'
je invalid_value
call get_dword_value
@ -898,11 +900,8 @@ pe_stack:
jne default_stack_commit
lods byte [esi]
lods byte [esi]
call get_size_operator
cmp al,'('
jne invalid_argument
test ah,not 4
jnz invalid_address
cmp byte [esi],'.'
je invalid_value
call get_dword_value
@ -922,11 +921,8 @@ pe_stack:
jmp instruction_assembled
pe_heap:
lods byte [esi]
call get_size_operator
cmp al,'('
jne invalid_argument
test ah,not 4
jnz invalid_address
cmp byte [esi],'.'
je invalid_value
call get_dword_value
@ -938,11 +934,8 @@ pe_heap:
jne default_heap_commit
lods byte [esi]
lods byte [esi]
call get_size_operator
cmp al,'('
jne invalid_argument
test ah,not 4
jnz invalid_address
cmp byte [esi],'.'
je invalid_value
call get_dword_value
@ -1018,6 +1011,9 @@ close_pe:
call close_pe_section
mov edx,[header_data]
mov [edx+50h],eax
call make_timestamp
mov edx,[header_data]
mov [edx+8],eax
mov eax,[number_of_relocations]
cmp eax,0
jle pe_flags_ok
@ -1058,7 +1054,12 @@ format_coff:
mov [ebx],eax
mov [ebx+4],eax
mov [ebx+8],edi
mov dword [ebx+10h],0E0000060h
mov eax,60h
bt [format_flags],0
jnc flat_section_flags_ok
or eax,0E0000000h
flat_section_flags_ok:
mov dword [ebx+10h],eax
mov [current_section],ebx
mov [number_of_sections],1
mov [code_type],32
@ -1076,6 +1077,8 @@ coff_section:
xor eax,eax
mov [ebx],al
mov [ebx+8],edi
mov [org_origin],edi
mov [org_sib],0
mov [org_start],edi
or [reloc_labels],-1
mov [ebx+10h],eax
@ -1144,15 +1147,6 @@ public_directive:
mov [ebx+8],eax
mov eax,[current_line]
mov [ebx+0Ch],eax
cmp byte [esi],86h
jne instruction_assembled
inc esi
lods word [esi]
cmp al,'('
jne invalid_argument
mov [ebx+4],esi
lods dword [esi]
lea esi,[esi+eax+1]
jmp instruction_assembled
extrn_directive:
cmp [output_format],4
@ -1240,7 +1234,7 @@ mark_coff_relocation:
mov [additional_memory],ebx
mov byte [ebx-0Ch],al
mov eax,edi
sub eax,[org_start]
sub eax,[org_origin]
mov [ebx-0Ch+4],eax
mov eax,[symbol_identifier]
mov [ebx-0Ch+8],eax
@ -1280,6 +1274,14 @@ coff_formatter:
mov [additional_memory],edi
mov word [ebx],14Ch
mov word [ebx+12h],104h
bt [format_flags],0
jnc coff_flags_ok
or byte [ebx+12h],80h
coff_flags_ok:
push ebx
call make_timestamp
pop ebx
mov [ebx+4],eax
mov eax,[number_of_sections]
mov [ebx+2],ax
mov esi,[sections_data]

View file

@ -3,7 +3,7 @@
; Copyright (c) 1999-2002, Tomasz Grysztar
; All rights reserved.
program_base = 0x700000
program_base = 0x8048000
org program_base
use32
@ -33,6 +33,8 @@ start:
pop eax
pop [input_file]
pop [output_file]
pop eax
pop [environment]
call init_memory
@ -157,6 +159,7 @@ additional_memory dd ?
additional_memory_end dd ?
input_file dd ?
output_file dd ?
environment dd ?
source_start dd ?
code_start dd ?
code_size dd ?
@ -171,10 +174,13 @@ macro_block dd ?
macro_block_line_number dd ?
struc_name dd ?
current_locals_prefix dd ?
anonymous_reverse dd ?
anonymous_forward dd ?
labels_list dd ?
label_hash dd ?
org_start dd ?
org_origin dd ?
org_sib dd ?
org_start dd ?
undefined_data_start dd ?
undefined_data_end dd ?
counter dd ?
@ -188,6 +194,7 @@ current_offset dd ?
value dq ?
fp_value rd 8
symbol_identifier dd ?
address_symbol dd ?
format_flags dd ?
number_of_relocations dd ?
number_of_sections dd ?
@ -198,6 +205,7 @@ current_section dd ?
machine dw ?
subsystem dw ?
subsystem_version dd ?
image_base dd ?
macro_status db ?
parenthesis_stack db ?
@ -228,6 +236,6 @@ nextbyte db ?
characters rb 100h
converted rb 100h
buffer rb 100h
buffer rb 4000h
program_end:

View file

@ -60,29 +60,105 @@ exit_program:
int 0x80
open:
push edx esi edi ebp
mov ebx,edx
push esi edi ebp
call convert_path
mov eax,5
mov ebx,buffer
mov ecx,O_RDONLY
xor edx,edx
int 0x80
pop ebp edi esi edx
pop ebp edi esi
test eax,eax
js file_error
mov ebx,eax
clc
ret
file_error:
stc
convert_path:
mov esi,edx
mov edi,buffer
copy_path:
lods byte [esi]
cmp al,'%'
je environment_variable
cmp al,'\'
jne path_char_ok
mov al,'/'
path_char_ok:
stos byte [edi]
or al,al
jnz copy_path
cmp edi,buffer+4000h
ja out_of_memory
ret
convert_backslash:
mov al,'/'
stos byte [edi]
jmp copy_path
environment_variable:
mov ebx,esi
find_variable_end:
lods byte [esi]
or al,al
jz not_environment_variable
cmp al,'%'
jne find_variable_end
push esi
mov esi,[environment]
compare_variable_names:
mov edx,ebx
compare_character:
lods byte [esi]
mov ah,[edx]
inc edx
cmp al,'='
je end_of_variable_name
cmp ah,'%'
je next_variable
sub ah,al
jz compare_character
cmp ah,20h
jne next_variable
cmp al,41h
jb next_variable
cmp al,5Ah
jna compare_character
next_variable:
lods byte [esi]
or al,al
jnz next_variable
cmp byte [esi],0
jne compare_variable_names
pop esi
jmp copy_path
end_of_variable_name:
cmp ah,'%'
jne next_variable
copy_variable_value:
lods byte [esi]
cmp al,'\'
jne value_char_ok
mov al,'/'
value_char_ok:
stos byte [edi]
or al,al
jnz copy_variable_value
dec di
pop esi
jmp copy_path
not_environment_variable:
mov al,'%'
stos byte [edi]
mov esi,ebx
jmp copy_path
create:
push edx esi edi ebp
mov ebx,edx
push esi edi ebp
call convert_path
mov eax,5
mov ebx,buffer
mov ecx,O_CREAT+O_TRUNC+O_WRONLY
mov edx,S_IRUSR+S_IWUSR+S_IRGRP
int 0x80
pop ebp edi esi edx
pop ebp edi esi
test eax,eax
js file_error
mov ebx,eax
@ -104,6 +180,9 @@ read:
jne file_error
clc
ret
file_error:
stc
ret
write:
push edx esi edi ebp
mov eax,4
@ -120,6 +199,8 @@ lseek:
mov dl,al
mov eax,19
int 0x80
test eax,eax
js file_error
clc
ret
@ -280,6 +361,12 @@ assembler_error:
call display_string
jmp exit_program
make_timestamp:
mov eax,13
xor ebx,ebx
int 0x80
ret
character db ?,0
error_prefix db 'error: ',0

View file

@ -6,7 +6,10 @@
parser:
mov eax,[memory_end]
mov [labels_list],eax
mov [current_locals_prefix],0
xor eax,eax
mov [current_locals_prefix],eax
mov [anonymous_reverse],eax
mov [anonymous_forward],eax
mov esi,[source_start]
mov edi,[code_start]
push [additional_memory]
@ -24,6 +27,8 @@ parser:
jb parser_loop
xor al,al
stos byte [edi]
cmp [anonymous_forward],0
jne unexpected_end_of_file
pop [additional_memory]
mov eax,[code_start]
mov [source_start],eax
@ -92,13 +97,13 @@ parse_line:
data_label:
pop ecx ebx
pop edi
push ax esi
push eax esi
mov esi,ebx
call identify_label
mov byte [edi],2
inc edi
stos dword [edi]
pop esi ax
pop esi eax
stos byte [edi]
push edi
jmp data_instruction
@ -119,10 +124,16 @@ parse_line:
cmp eax,10h
jb label_identified
mov ebx,[eax+4]
cmp ebx,eax
je anonymous_label_name
dec ebx
mov [current_locals_prefix],ebx
label_identified:
ret
anonymous_label_name:
cmp byte [esi-1],'@'
jne reserved_word_used_as_symbol
ret
local_label_name:
call get_label_id
ret
@ -435,16 +446,11 @@ parse_line:
or al,al
jz line_parsed
cmp al,':'
je empty_label
je invalid_name
cmp al,3Bh
je skip_preprocessed_symbol
dec esi
jmp parse_arguments
empty_label:
mov eax,_counter
call increase_counter
mov [current_locals_prefix],eax
jmp instruction_start
skip_preprocessed_symbol:
lods byte [esi]
movzx eax,al

View file

@ -244,6 +244,12 @@ preprocess_line:
push ecx esi
mov esi,[current_line]
add esi,12
test [macro_status],0C0h
jz concatenations_ok
call process_concatenations
mov esi,[current_line]
add esi,12
concatenations_ok:
mov al,[macro_status]
dec al
jz find_macro_block
@ -299,9 +305,6 @@ preprocess_line:
mov esi,[current_line]
add esi,12
call process_symbolic_constants
mov esi,[current_line]
add esi,12
call process_concatenations
line_preprocessed:
pop esi ecx
pop [struc_name]
@ -349,11 +352,11 @@ process_symbolic_constants:
check_symbol:
movzx ecx,byte [esi]
inc esi
call replace_symbolic_constant
jnc process_after_replaced
call find_symbolic_constant
jnc replace_symbolic_constant
add esi,ecx
jmp process_symbolic_constants
replace_symbolic_constant:
find_symbolic_constant:
push edi
mov ebx,esi
mov eax,ecx
@ -377,6 +380,9 @@ process_symbolic_constants:
ret
symbolic_constant_found:
pop edi
clc
ret
replace_symbolic_constant:
mov ecx,[edx+8]
mov edx,[edx+12]
xchg esi,edx
@ -391,8 +397,6 @@ process_symbolic_constants:
mov cl,al
rep movs byte [edi],[esi]
mov esi,edx
clc
ret
process_after_replaced:
lods byte [esi]
cmp al,1Ah
@ -425,8 +429,8 @@ process_symbolic_constants:
symbol_after_replaced:
movzx ecx,byte [esi]
inc esi
call replace_symbolic_constant
jnc process_after_replaced
call find_symbolic_constant
jnc replace_symbolic_constant
mov al,1Ah
mov ah,cl
stos word [edi]
@ -540,6 +544,39 @@ define_symbolic_constant:
mov [edx],al
mov [edx+4],ebx
jmp line_preprocessed
restore_symbolic_constant:
lods byte [esi]
cmp al,1Ah
jne invalid_name
movzx ecx,byte [esi]
inc esi
call find_symbolic_constant
jc no_symbolic_constant
mov ecx,edx
sub ecx,[labels_list]
add [labels_list],16
shr ecx,2
jz constant_restored
mov ebx,esi
mov esi,edx
xchg edi,edx
add edi,12
sub esi,4
std
rep movs dword [edi],[esi]
cld
mov esi,ebx
mov edi,edx
jmp constant_restored
no_symbolic_constant:
add esi,ecx
constant_restored:
lods byte [esi]
cmp al,','
je restore_symbolic_constant
or al,al
jnz extra_characters_on_line
jmp line_preprocessed
define_struc:
or ah,1
define_macro:
@ -650,6 +687,7 @@ purge_macro:
use_macro:
push [macro_constants] [macro_block] [macro_block_line_number]
push [counter] [counter_limit]
push dword [macro_status]
or [macro_status],80h
or byte [ebx+1],80h
mov edx,esi
@ -1000,7 +1038,8 @@ use_macro:
pop [current_line]
mov eax,[macro_constants]
mov [additional_memory],eax
mov [macro_status],0
pop eax
mov [macro_status],al
pop [counter_limit] [counter]
pop [macro_block_line_number] [macro_block] [macro_constants]
jmp line_preprocessed

View file

@ -148,6 +148,8 @@ get_instruction:
get_label_id:
cmp ecx,100h
jae name_too_long
cmp byte [esi],'@'
je anonymous_label
cmp byte [esi],'.'
jne standard_label
cmp byte [esi+1],'.'
@ -182,6 +184,56 @@ get_label_id:
call get_label_id
pop esi
ret
anonymous_label:
cmp ecx,2
jne standard_label
mov al,[esi+1]
mov ebx,characters
xlat byte [ebx]
cmp al,'@'
je new_anonymous
cmp al,'b'
je anonymous_back
cmp al,'r'
je anonymous_back
cmp al,'f'
jne standard_label
add esi,2
mov eax,[anonymous_forward]
or eax,eax
jnz anonymous_ok
mov eax,[labels_list]
sub eax,16
mov [labels_list],eax
cmp eax,edi
jbe out_of_memory
mov dword [eax],0
mov [eax+4],eax
mov [anonymous_forward],eax
anonymous_ok:
ret
anonymous_back:
add esi,2
mov eax,[anonymous_reverse]
or eax,eax
jz invalid_value
ret
new_anonymous:
add esi,2
mov eax,[anonymous_forward]
or eax,eax
jnz new_anonymous_ok
mov eax,[labels_list]
sub eax,16
mov [labels_list],eax
cmp eax,edi
jbe out_of_memory
mov dword [eax],0
mov [eax+4],eax
new_anonymous_ok:
mov [anonymous_reverse],eax
mov [anonymous_forward],0
ret
standard_label:
cmp ecx,1
jne find_label
@ -296,7 +348,6 @@ single_operand_operators:
db 0
directive_operators:
db 2,'as',86h
db 2,'at',80h
db 2,'eq',81h
db 4,'from',82h
@ -419,9 +470,6 @@ formatter_symbols:
db 6,'export',1Ah,0
db 6,'fixups',1Ah,5
db 3,'gui',1Bh,2
db 4,'i386',1Bh,43h
db 4,'i486',1Bh,44h
db 4,'i586',1Bh,45h
db 6,'import',1Ah,1
db 2,'ms',18h,41h
db 2,'mz',18h,2
@ -440,6 +488,8 @@ preprocessor_directives:
dw define_macro-preprocessor
db 5,'purge'
dw purge_macro-preprocessor
db 7,'restore'
dw restore_symbolic_constant-preprocessor
db 5,'struc'
dw define_struc-preprocessor
db 0
@ -1679,10 +1729,6 @@ instructions_10:
dw cmp_ps_instruction-assembler
db 'cmpunordss',3
dw cmp_ss_instruction-assembler
db 'loadall286',5
dw simple_extended_instruction-assembler
db 'loadall386',7
dw simple_extended_instruction-assembler
db 'maskmovdqu',0
dw maskmovdqu_instruction-assembler
db 'prefetcht0',1

View file

@ -1,5 +1,5 @@
; flat assembler version 1.39
; flat assembler version 1.40
; Copyright (c) 1999-2002, Tomasz Grysztar
; All rights reserved.
;
@ -33,7 +33,7 @@
; cannot simply be copied and put under another distribution licence
; (including the GNU Public Licence).
VERSION_STRING equ "1.39"
VERSION_STRING equ "1.40"
VERSION_MAJOR = 1
VERSION_MINOR = 39
VERSION_MINOR = 40

View file

@ -23,6 +23,10 @@ start:
je information
inc eax
mov [output_file],eax
movzx ecx,byte [eax-1]
add eax,ecx
cmp byte [eax],0
jne information
call init_memory
@ -204,11 +208,14 @@ macro_constants dd ?
macro_block dd ?
macro_block_line_number dd ?
struc_name dd ?
anonymous_reverse dd ?
anonymous_forward dd ?
current_locals_prefix dd ?
labels_list dd ?
label_hash dd ?
org_start dd ?
org_origin dd ?
org_sib dd ?
org_start dd ?
undefined_data_start dd ?
undefined_data_end dd ?
counter dd ?
@ -222,6 +229,7 @@ current_offset dd ?
value dq ?
fp_value rd 8
symbol_identifier dd ?
address_symbol dd ?
format_flags dd ?
number_of_relocations dd ?
number_of_sections dd ?
@ -232,6 +240,7 @@ current_section dd ?
machine dw ?
subsystem dw ?
subsystem_version dd ?
image_base dd ?
macro_status db ?
parenthesis_stack db ?
@ -262,8 +271,8 @@ nextbyte db ?
characters rb 100h
converted rb 100h
params rb 100h
buffer rb 100h
params rb 1000h
buffer rb 4000h
stack 4000h
@ -280,9 +289,11 @@ section '.idata' import data readable writeable
CloseHandle dd rva _CloseHandle
SetFilePointer dd rva _SetFilePointer
GetCommandLine dd rva _GetCommandLineA
GetEnvironmentVariable dd rva _GetEnvironmentVariable
GetStdHandle dd rva _GetStdHandle
VirtualAlloc dd rva _VirtualAlloc
GetTickCount dd rva _GetTickCount
GetSystemTime dd rva _GetSystemTime
GlobalMemoryStatus dd rva _GlobalMemoryStatus
dd 0
@ -302,12 +313,16 @@ section '.idata' import data readable writeable
db 'SetFilePointer',0
_GetCommandLineA dw 0
db 'GetCommandLineA',0
_GetEnvironmentVariable dw 0
db 'GetEnvironmentVariableA',0
_GetStdHandle dw 0
db 'GetStdHandle',0
_VirtualAlloc dw 0
db 'VirtualAlloc',0
_GetTickCount dw 0
db 'GetTickCount',0
_GetSystemTime dw 0
db 'GetSystemTime',0
_GlobalMemoryStatus dw 0
db 'GlobalMemoryStatus',0

View file

@ -74,13 +74,14 @@ exit_program:
call [ExitProcess]
open:
call convert_path
push 0
push 0
push OPEN_EXISTING
push 0
push 0
push GENERIC_READ
push edx
push buffer
call [CreateFile]
cmp eax,-1
je file_error
@ -90,14 +91,53 @@ open:
file_error:
stc
ret
convert_path:
push esi edi
mov esi,edx
mov edi,buffer
copy_path:
lods byte [esi]
cmp al,'%'
je environment_variable
stos byte [edi]
or al,al
jnz copy_path
cmp edi,buffer+4000h
ja out_of_memory
pop edi esi
ret
environment_variable:
mov ebx,esi
find_variable_end:
lods byte [esi]
or al,al
jz not_environment_variable
cmp al,'%'
jne find_variable_end
mov byte [esi-1],0
mov eax,buffer+4000h
sub eax,edi
push eax
push edi
push ebx
call [GetEnvironmentVariable]
add edi,eax
mov byte [esi-1],'%'
jmp copy_path
not_environment_variable:
mov al,'%'
stos byte [edi]
mov esi,ebx
jmp copy_path
create:
call convert_path
push 0
push 0
push CREATE_ALWAYS
push 0
push 0
push GENERIC_WRITE
push edx
push buffer
call [CreateFile]
cmp eax,-1
je file_error
@ -140,6 +180,8 @@ lseek:
push edx
push ebx
call [SetFilePointer]
cmp eax,-1
je file_error
ret
display_string:
@ -175,10 +217,10 @@ display_block:
ret
display_character:
push ebx
mov [character],dl
push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov ebx,eax
mov [character],dl
push 0
push bytes_count
push 1
@ -205,9 +247,9 @@ display_number:
display_digit:
mov dl,al
add dl,30h
push ebx ecx
push ecx
call display_character
pop ecx ebx
pop ecx
digit_ok:
mov eax,ecx
xor edx,edx
@ -310,6 +352,84 @@ assembler_error:
call display_string
jmp exit_program
make_timestamp:
push buffer
call [GetSystemTime]
movzx ecx,word [buffer]
mov eax,ecx
sub eax,1970
mov ebx,365
mul ebx
mov ebp,eax
mov eax,ecx
sub eax,1969
shr eax,2
add ebp,eax
mov eax,ecx
sub eax,1901
mov ebx,100
div ebx
sub ebp,eax
mov eax,ecx
xor edx,edx
sub eax,1601
mov ebx,400
div ebx
add ebp,eax
movzx ecx,word [buffer+2]
mov eax,ecx
dec eax
mov ebx,30
mul ebx
add ebp,eax
cmp ecx,8
jbe months_correction
mov eax,ecx
sub eax,7
shr eax,1
add ebp,eax
mov ecx,8
months_correction:
mov eax,ecx
shr eax,1
add ebp,eax
sub ebp,2
cmp ecx,2
jbe day_correction_ok
movzx ecx,word [buffer]
test ecx,11b
jnz day_correction_ok
xor edx,edx
mov eax,ecx
mov ebx,100
div ebx
or edx,edx
jnz day_correction
mov eax,ecx
mov ebx,400
div ebx
or edx,edx
jnz day_correction_ok
day_correction:
inc ebp
day_correction_ok:
movzx eax,word [buffer+6]
dec eax
add eax,ebp
mov ebx,24
mul ebx
movzx ecx,word [buffer+8]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,word [buffer+10]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,word [buffer+12]
add eax,ecx
ret
character db ?,0
bytes_count dd ?

View file

@ -1,6 +1,19 @@
Visit http://fasm.metro-nt.pl/ for more examples and documentation
Questions or comments please send to fasm@metro-nt.pl
Visit http://fasm.metro-nt.pl for more examples and tools
version 1.40
[04-08-2002]
------------
[+] added restore directive
[+] concatenations processed before symbolic constants now
[+] timestamps generated for COFF and PE
[+] custom base of PE image allowed
[+] added support for anonymous labels
[+] load directive extended for code loading
[+] environment variables in paths allowed
[-] concatenations allowed in macroinstructions only
[-] more fixes
version 1.39
[08-07-2002]
@ -190,7 +203,7 @@ version 1.01
version 1.00
[19-06-2000]
------------
[+] first serious release
[+] first official release
version 0.90
[04-05-1999]