add flat assembler toolchain

This commit is contained in:
2024-11-24 23:13:28 -05:00
parent 99e8e4072b
commit dbfd94ea40
302 changed files with 145599 additions and 0 deletions

View File

@ -0,0 +1,229 @@
format MZ
heap 0
stack 8000h
entry loader:init
include 'loader.inc'
segment main use32
start:
call get_params
jnc make_listing
mov esi,_usage
call display_string
mov ax,4C02h
int 21h
make_listing:
call listing
mov ax,4C00h
int 21h
error:
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
mov ax,4C00h
int 21h
get_params:
push ds
mov ds,[psp_selector]
mov esi,81h
mov edi,params
find_param:
lodsb
cmp al,20h
je find_param
cmp al,'-'
je option_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [es:input_file],0
jne get_output_file
mov [es:input_file],edi
jmp process_param
get_output_file:
cmp [es:output_file],0
jne bad_params
mov [es:output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
option_param:
lodsb
cmp al,'a'
je addresses_option
cmp al,'A'
je addresses_option
cmp al,'b'
je bytes_per_line_option
cmp al,'B'
je bytes_per_line_option
invalid_option:
pop ds
stc
ret
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc bad_params_value
cmp al,9
ja bad_params_value
imul edx,10
jo bad_params_value
add edx,eax
jc bad_params_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
bad_params_value:
stc
ret
bytes_per_line_option:
lodsb
cmp al,20h
je bytes_per_line_option
cmp al,0Dh
je invalid_option
or al,al
jz invalid_option
dec esi
call get_option_value
jc bad_params
or edx,edx
jz invalid_option
cmp edx,1000
ja invalid_option
mov [es:code_bytes_per_line],edx
jmp find_param
addresses_option:
lodsb
cmp al,20h
je set_addresses_option
cmp al,0Dh
je set_addresses_option
or al,al
jnz bad_params
set_addresses_option:
dec esi
mov [es:show_addresses],1
jmp find_param
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
xor al,al
stosb
pop ds
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
bad_params:
stc
ret
include 'system.inc'
include '..\listing.inc'
_usage db 'listing generator for flat assembler',0Dh,0Ah
db 'usage: listing <input> <output>',0Dh,0Ah
db 'optional settings:',0Dh,0Ah
db ' -a show target addresses for assembled code',0Dh,0Ah
db ' -b <number> set the amount of bytes listed per line',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
input_file dd 0
output_file dd 0
code_bytes_per_line dd 16
show_addresses db 0
line_break db 0Dh,0Ah
input dd ?
assembled_code dd ?
assembled_code_length dd ?
code_end dd ?
code_offset dd ?
code_length dd ?
output_handle dd ?
output_buffer dd ?
current_source_file dd ?
current_source_line dd ?
source dd ?
source_length dd ?
maximum_address_length dd ?
address_start dd ?
last_listed_address dd ?
psp_selector dw ?
environment_selector dw ?
memory_handles_count dd ?
memory_handles rd 400h
params rb 1000h
characters rb 100h
segment buffer_segment
buffer = (buffer_segment-main) shl 4
db 1000h dup ?
segment stack_segment
stack_bottom = (stack_segment-main) shl 4
db 4000h dup ?
stack_top = stack_bottom + $

View File

@ -0,0 +1,102 @@
segment loader use16
init:
mov ax,1687h
int 2Fh
or ax,ax ; DPMI installed?
jnz short no_dpmi
test bl,1 ; 32-bit programs supported?
jz short no_dpmi
mov word [cs:mode_switch],di
mov word [cs:mode_switch+2],es
mov bx,si ; allocate memory for DPMI data
mov ah,48h
int 21h
jnc init_protected_mode
init_failed:
call init_error
db 'error: DPMI initialization failed.',0Dh,0Ah,0
no_dpmi:
call init_error
db 'error: 32-bit DPMI services are not available.',0Dh,0Ah,0
init_error:
pop si
push cs
pop ds
display_error:
lodsb
test al,al
jz short error_finish
mov dl,al
mov ah,2
int 21h
jmp short display_error
error_finish:
mov ax,4CFFh
int 21h
init_protected_mode:
mov es,ax
mov ds,[ds:2Ch]
mov ax,1
call far [cs:mode_switch] ; switch to protected mode
jc init_failed
mov cx,1
xor ax,ax
int 31h ; allocate descriptor for code
jc init_failed
mov si,ax
xor ax,ax
int 31h ; allocate descriptor for data
jc init_failed
mov di,ax
mov dx,cs
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,si
mov ax,9
int 31h ; set code descriptor access rights
jc init_failed
mov dx,ds
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,di
int 31h ; set data descriptor access rights
jc init_failed
mov ecx,main
shl ecx,4
mov dx,cx
shr ecx,16
mov ax,7
int 31h ; set data descriptor base address
jc init_failed
mov bx,si
int 31h ; set code descriptor base address
jc init_failed
mov cx,0FFFFh
mov dx,0FFFFh
mov ax,8 ; set segment limit to 4 GB
int 31h
jc init_failed
mov bx,di
int 31h
jc init_failed
mov ax,ds
mov ds,di
mov [psp_selector],es
mov [environment_selector],ax
cli
mov ss,di
mov esp,stack_top
sti
mov es,di
xor eax,eax
mov [memory_handles_count],eax
push si
push start
retf
mode_switch dd ?

View File

@ -0,0 +1,136 @@
format MZ
heap 0
stack 8000h
entry loader:init
include 'loader.inc'
segment main use32
start:
call get_params
jnc make_dump
mov esi,_usage
call display_string
mov ax,4C02h
int 21h
make_dump:
call preprocessed_source
mov ax,4C00h
int 21h
error:
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
mov ax,4C00h
int 21h
get_params:
push ds
mov ds,[psp_selector]
mov esi,81h
mov edi,params
find_param:
lodsb
cmp al,20h
je find_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [es:input_file],0
jne get_output_file
mov [es:input_file],edi
jmp process_param
get_output_file:
cmp [es:output_file],0
jne bad_params
mov [es:output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
bad_params_value:
stc
ret
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
xor al,al
stosb
pop ds
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
bad_params:
stc
ret
include 'system.inc'
include '..\prepsrc.inc'
_usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah
db 'usage: prepsrc <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
input_file dd 0
output_file dd 0
psp_selector dw ?
environment_selector dw ?
memory_handles_count dd ?
memory_handles rd 400h
params rb 1000h
segment buffer_segment
buffer = (buffer_segment-main) shl 4
db 1000h dup ?
segment stack_segment
stack_bottom = (stack_segment-main) shl 4
db 4000h dup ?
stack_top = stack_bottom + $

View File

@ -0,0 +1,140 @@
format MZ
heap 0
stack 8000h
entry loader:init
include 'loader.inc'
segment main use32
start:
call get_params
jnc make_dump
mov esi,_usage
call display_string
mov ax,4C02h
int 21h
make_dump:
call symbols
mov ax,4C00h
int 21h
error:
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
mov ax,4C00h
int 21h
get_params:
push ds
mov ds,[psp_selector]
mov esi,81h
mov edi,params
find_param:
lodsb
cmp al,20h
je find_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [es:input_file],0
jne get_output_file
mov [es:input_file],edi
jmp process_param
get_output_file:
cmp [es:output_file],0
jne bad_params
mov [es:output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
bad_params_value:
stc
ret
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
xor al,al
stosb
pop ds
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
bad_params:
stc
ret
include 'system.inc'
include '..\symbols.inc'
_usage db 'symbols dumper for flat assembler',0Dh,0Ah
db 'usage: symbols <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
input_file dd 0
output_file dd 0
input dd ?
output_buffer dd ?
output_handle dd ?
psp_selector dw ?
environment_selector dw ?
memory_handles_count dd ?
memory_handles rd 400h
params rb 1000h
segment buffer_segment
buffer = (buffer_segment-main) shl 4
db 1000h dup ?
segment stack_segment
stack_bottom = (stack_segment-main) shl 4
db 4000h dup ?
stack_top = stack_bottom + $

View File

@ -0,0 +1,239 @@
display_string:
lods byte [esi]
or al,al
jz string_end
mov dl,al
mov ah,2
int 21h
jmp display_string
string_end:
ret
alloc:
push ebx esi edi
mov cx,ax
shr eax,16
mov bx,ax
mov ax,501h
int 31h
jc dpmi_allocation_failed
mov ax,bx
shl eax,16
mov ax,cx
mov edx,main
shl edx,4
sub eax,edx
mov bx,si
shl ebx,16
mov bx,di
mov ecx,[memory_handles_count]
inc [memory_handles_count]
shl ecx,3
add ecx,memory_handles
mov [ecx],eax
mov [ecx+4],ebx
pop edi esi ebx
clc
ret
dpmi_allocation_failed:
pop edi esi ebx
stc
ret
free:
push ebx esi edi
mov esi,memory_handles
mov ecx,[memory_handles_count]
find_memory_handle:
cmp eax,[esi]
je memory_handle_found
add esi,8
loop find_memory_handle
pop edi esi
ret
memory_handle_found:
mov ebx,[esi+4]
dec [memory_handles_count]
dec ecx
jz free_memory
remove_memory_handle:
mov edx,[esi+8]
mov edi,[esi+8+4]
mov [esi],edx
mov [esi+4],edi
add esi,8
loop remove_memory_handle
free_memory:
mov esi,ebx
shr esi,16
mov di,bx
mov ax,502h
int 31h
pop edi esi ebx
ret
open:
push esi edi ebp
call adapt_path
mov ax,716Ch
mov bx,100000b
mov dx,1
xor cx,cx
xor si,si
call dos_int
jnc open_done
cmp ax,7100h
je old_open
stc
jmp open_done
old_open:
mov ax,3D00h
xor dx,dx
call dos_int
open_done:
mov bx,ax
pop ebp edi esi
ret
adapt_path:
mov esi,edx
mov edi,buffer
copy_path:
lodsb
cmp al,'/'
jne path_char_ok
mov al,'\'
path_char_ok:
stosb
or al,al
jnz copy_path
ret
dos_int:
push 0 0 0
pushw buffer_segment buffer_segment
stc
pushfw
push eax
push ecx
push edx
push ebx
push 0
push ebp
push esi
push edi
mov ax,300h
mov bx,21h
xor cx,cx
mov edi,esp
push es ss
pop es
int 31h
pop es
mov edi,[esp]
mov esi,[esp+4]
mov ebp,[esp+8]
mov ebx,[esp+10h]
mov edx,[esp+14h]
mov ecx,[esp+18h]
mov ah,[esp+20h]
add esp,32h
sahf
mov eax,[esp-32h+1Ch]
ret
create:
push esi edi ebp
call adapt_path
mov ax,716Ch
mov bx,100001b
mov dx,10010b
xor cx,cx
xor si,si
xor di,di
call dos_int
jnc create_done
cmp ax,7100h
je old_create
stc
jmp create_done
old_create:
mov ah,3Ch
xor cx,cx
xor dx,dx
call dos_int
create_done:
mov bx,ax
pop ebp edi esi
ret
write:
push edx esi edi ebp
mov ebp,ecx
mov esi,edx
write_loop:
mov ecx,1000h
sub ebp,1000h
jnc do_write
add ebp,1000h
mov ecx,ebp
xor ebp,ebp
do_write:
push ecx
mov edi,buffer
shr ecx,2
rep movsd
mov ecx,[esp]
and ecx,11b
rep movsb
pop ecx
mov ah,40h
xor dx,dx
call dos_int
or ebp,ebp
jnz write_loop
pop ebp edi esi edx
ret
read:
push edx esi edi ebp
mov ebp,ecx
mov edi,edx
read_loop:
mov ecx,1000h
sub ebp,1000h
jnc do_read
add ebp,1000h
mov ecx,ebp
xor ebp,ebp
do_read:
push ecx
mov ah,3Fh
xor dx,dx
call dos_int
cmp ax,cx
jne eof
mov esi,buffer
mov ecx,[esp]
shr ecx,2
rep movsd
pop ecx
and ecx,11b
rep movsb
or ebp,ebp
jnz read_loop
read_done:
pop ebp edi esi edx
ret
eof:
pop ecx
stc
jmp read_done
close:
mov ah,3Eh
int 21h
ret
lseek:
mov ah,42h
mov ecx,edx
shr ecx,16
int 21h
pushf
shl edx,16
popf
mov dx,ax
mov eax,edx
ret

View File

@ -0,0 +1,429 @@
flat assembler
Symbolic information file format
Table 1 Header
/-------------------------------------------------------------------------\
| Offset | Size | Description |
|========|=========|======================================================|
| +0 | dword | Signature 1A736166h (little-endian). |
|--------|---------|------------------------------------------------------|
| +4 | byte | Major version of flat assembler. |
|--------|---------|------------------------------------------------------|
| +5 | byte | Minor version of flat assembler. |
|--------|---------|------------------------------------------------------|
| +6 | word | Length of header. |
|--------|---------|------------------------------------------------------|
| +8 | dword | Offset of input file name in the strings table. |
|--------|---------|------------------------------------------------------|
| +12 | dword | Offset of output file name in the strings table. |
|--------|---------|------------------------------------------------------|
| +16 | dword | Offset of strings table. |
|--------|---------|------------------------------------------------------|
| +20 | dword | Length of strings table. |
|--------|---------|------------------------------------------------------|
| +24 | dword | Offset of symbols table. |
|--------|---------|------------------------------------------------------|
| +28 | dword | Length of symbols table. |
|--------|---------|------------------------------------------------------|
| +32 | dword | Offset of preprocessed source. |
|--------|---------|------------------------------------------------------|
| +36 | dword | Length of preprocessed source. |
|--------|---------|------------------------------------------------------|
| +40 | dword | Offset of assembly dump. |
|--------|---------|------------------------------------------------------|
| +44 | dword | Length of assembly dump. |
|--------|---------|------------------------------------------------------|
| +48 | dword | Offset of section names table. |
|--------|---------|------------------------------------------------------|
| +52 | dword | Length of section names table. |
|--------|---------|------------------------------------------------------|
| +56 | dword | Offset of symbol references dump. |
|--------|---------|------------------------------------------------------|
| +60 | dword | Length of symbol references dump. |
\-------------------------------------------------------------------------/
Notes:
If header is shorter than 64 bytes, it comes from a version that does not
support dumping some of the structures. It should then be interpreted
that the data for missing structures could not be provided, not that the
size of that data is zero.
Offsets given in header generally mean positions in the file, however
input and output file names are specified by offsets in the strings table,
so you have to add their offset to the offset of strings table to obtain
the positions of those strings in the file.
The strings table contains just a sequence of ASCIIZ strings, which may
be referred to by other parts of the file. It contains the names of
main input file, the output file, and the names of the sections and
external symbols if there were any.
The symbols table is an array of 32-byte structures, each one in format
specified by table 2.
The preprocessed source is a sequence of preprocessed lines, each one
in format as defined in table 3.
The assembly dump contains an array of 28-byte structures, each one in
format specified by table 4, and at the end of this array an additional
double word containing the offset in output file at which the assembly
was ended.
It is possible that file does not contain assembly dump at all - this
happens when some error occured and only the preprocessed source was
dumped. If error occured during the preprocessing, only the source up to
the point of error is provided. In such case (and only then) the field
at offset 44 contains zero.
The section names table exists only when the output format was an object
file (ELF or COFF), and it is an array of 4-byte entries, each being an
offset of the name of the section in the strings table.
The index of section in this table is the same, as the index of section
in the generated object file.
The symbol references dump contains an array of 8-byte structures, each
one describes an event of some symbol being used. The first double word
of such structure contains an offset of symbol in the symbols table,
and the second double word is an offset of structure in assembly dump,
which specifies at what moment the symbol was referenced.
Table 2 Symbol structure
/-------------------------------------------------------------------------\
| Offset | Size | Description |
|========|=======|========================================================|
| +0 | qword | Value of symbol. |
|--------|-------|--------------------------------------------------------|
| +8 | word | Flags (table 2.1). |
|--------|-------|--------------------------------------------------------|
| +10 | byte | Size of data labelled by this symbol (zero means plain |
| | | label without size attached). |
|--------|-------|--------------------------------------------------------|
| +11 | byte | Type of value (table 2.2). Any value other than zero |
| | | means some kind of relocatable symbol. |
|--------|-------|--------------------------------------------------------|
| +12 | dword | Extended SIB, the first two bytes are register codes |
| | | and the second two bytes are corresponding scales. |
|--------|-------|--------------------------------------------------------|
| +16 | word | Number of pass in which symbol was defined last time. |
|--------|-------|--------------------------------------------------------|
| +18 | word | Number of pass in which symbol was used last time. |
|--------|-------|--------------------------------------------------------|
| +20 | dword | If the symbol is relocatable, this field contains |
| | | information about section or external symbol, to which |
| | | it is relative - otherwise this field has no meaning. |
| | | When the highest bit is cleared, the symbol is |
| | | relative to a section, and the bits 0-30 contain |
| | | the index (starting from 1) in the table of sections. |
| | | When the highest bit is set, the symbol is relative to |
| | | an external symbol, and the bits 0-30 contain the |
| | | the offset of the name of this symbol in the strings |
| | | table. |
|--------|-------|--------------------------------------------------------|
| +24 | dword | If the highest bit is cleared, the bits 0-30 contain |
| | | the offset of symbol name in the preprocessed source. |
| | | This name is a pascal-style string (byte length |
| | | followed by string data). |
| | | Zero in this field means an anonymous symbol. |
| | | If the highest bit is set, the bits 0-30 contain the |
| | | offset of the symbol name in the strings table, and |
| | | this name is a zero-ended string in this case (as are |
| | | all the strings there). |
|--------|-------|--------------------------------------------------------|
| +28 | dword | Offset in the preprocessed source of line that defined |
| | | this symbol (see table 3). |
\-------------------------------------------------------------------------/
Table 2.1 Symbol flags
/-----------------------------------------------------------------\
| Bit | Value | Description |
|=====|=======|===================================================|
| 0 | 1 | Symbol was defined. |
|-----|-------|---------------------------------------------------|
| 1 | 2 | Symbol is an assembly-time variable. |
|-----|-------|---------------------------------------------------|
| 2 | 4 | Symbol cannot be forward-referenced. |
|-----|-------|---------------------------------------------------|
| 3 | 8 | Symbol was used. |
|-----|-------|---------------------------------------------------|
| 4 | 10h | The prediction was needed when checking |
| | | whether the symbol was used. |
|-----|-------|---------------------------------------------------|
| 5 | 20h | Result of last predicted check for being used. |
|-----|-------|---------------------------------------------------|
| 6 | 40h | The prediction was needed when checking |
| | | whether the symbol was defined. |
|-----|-------|---------------------------------------------------|
| 7 | 80h | Result of last predicted check for being defined. |
|-----|-------|---------------------------------------------------|
| 8 | 100h | The optimization adjustment is applied to |
| | | the value of this symbol. |
|-----|-------|---------------------------------------------------|
| 9 | 200h | The value of symbol is negative number encoded |
| | | as two's complement. |
|-----|-------|---------------------------------------------------|
| 10 | 400h | Symbol is a special marker and has no value. |
\-----------------------------------------------------------------/
Notes:
Some of those flags are listed here just for completness, as they
have little use outside of the flat assembler. However the bit 0
is important, because the symbols table contains all the labels
that occured in source, even if some of them were in the
conditional blocks that did not get assembled.
Table 2.2 Symbol value types
/-------------------------------------------------------------------\
| Value | Description |
|=======|===========================================================|
| 0 | Absolute value. |
|-------|-----------------------------------------------------------|
| 1 | Relocatable segment address (only with MZ output). |
|-------|-----------------------------------------------------------|
| 2 | Relocatable 32-bit address. |
|-------|-----------------------------------------------------------|
| 3 | Relocatable relative 32-bit address (value valid only for |
| | symbol used in the same place where it was calculated, |
| | it should not occur in the symbol structure). |
|-------|-----------------------------------------------------------|
| 4 | Relocatable 64-bit address. |
|-------|-----------------------------------------------------------|
| 5 | [ELF only] GOT-relative 32-bit address. |
|-------|-----------------------------------------------------------|
| 6 | [ELF only] 32-bit address of PLT entry. |
|-------|-----------------------------------------------------------|
| 7 | [ELF only] Relative 32-bit address of PLT entry (value |
| | valid only for symbol used in the same place where it |
| | was calculated, it should not occur in the symbol |
| | structure). |
\-------------------------------------------------------------------/
Notes:
The types 3 and 7 should never be encountered in the symbols dump,
they are only used internally by the flat assembler.
If type value is a negative number, it is an opposite of a value
from this table and it means that the symbol of a given type has
been negated.
Table 2.3 Register codes for extended SIB
/------------------\
| Value | Register |
|=======|==========|
| 23h | BX |
|-------|----------|
| 25h | BP |
|-------|----------|
| 26h | SI |
|-------|----------|
| 27h | DI |
|-------|----------|
| 40h | EAX |
|-------|----------|
| 41h | ECX |
|-------|----------|
| 42h | EDX |
|-------|----------|
| 43h | EBX |
|-------|----------|
| 44h | ESP |
|-------|----------|
| 45h | EBP |
|-------|----------|
| 46h | ESI |
|-------|----------|
| 47h | EDI |
|-------|----------|
| 48h | R8D |
|-------|----------|
| 49h | R9D |
|-------|----------|
| 4Ah | R10D |
|-------|----------|
| 4Bh | R11D |
|-------|----------|
| 4Ch | R12D |
|-------|----------|
| 4Dh | R13D |
|-------|----------|
| 4Eh | R14D |
|-------|----------|
| 4Fh | R15D |
|-------|----------|
| 80h | RAX |
|-------|----------|
| 81h | RCX |
|-------|----------|
| 82h | RDX |
|-------|----------|
| 83h | RBX |
|-------|----------|
| 84h | RSP |
|-------|----------|
| 85h | RBP |
|-------|----------|
| 86h | RSI |
|-------|----------|
| 87h | RDI |
|-------|----------|
| 88h | R8 |
|-------|----------|
| 89h | R9 |
|-------|----------|
| 8Ah | R10 |
|-------|----------|
| 8Bh | R11 |
|-------|----------|
| 8Ch | R12 |
|-------|----------|
| 8Dh | R13 |
|-------|----------|
| 8Eh | R14 |
|-------|----------|
| 8Fh | R15 |
|-------|----------|
| 94h | EIP |
|-------|----------|
| 98h | RIP |
\------------------/
Table 3 Preprocessed line
/--------------------------------------------------------------------------\
| Offset | Size | Value |
|========|=================================================================|
| +0 | dword | When the line was loaded from source, this field |
| | | contains either zero (if it is the line from the main |
| | | input file), or an offset inside the preprocessed |
| | | source to the name of file, from which this line was |
| | | loaded (the name of file is zero-ended string). |
| | | When the line was generated by macroinstruction, this |
| | | field contains offset inside the preprocessed source to |
| | | the pascal-style string specifying the name of |
| | | macroinstruction, which generated this line. |
|--------|-------|---------------------------------------------------------|
| +4 | dword | Bits 0-30 contain the number of this line. |
| | | If the highest bit is zeroed, this line was loaded from |
| | | source. |
| | | If the highest bit is set, this line was generated by |
| | | macroinstruction. |
|--------|-------|---------------------------------------------------------|
| +8 | dword | If the line was loaded from source, this field contains |
| | | the position of the line inside the source file, from |
| | | which it was loaded. |
| | | If line was generated by macroinstruction, this field |
| | | contains the offset of preprocessed line, which invoked |
| | | the macroinstruction. |
| | | If line was generated by instantaneous macro, this |
| | | field is equal to the next one. |
|--------|-------|---------------------------------------------------------|
| +12 | dword | If the line was generated by macroinstruction, this |
| | | field contains offset of the preprocessed line inside |
| | | the definition of macro, from which this one was |
| | | generated. |
|--------|-------|---------------------------------------------------------|
| +16 | ? | The tokenized contents of line. |
\--------------------------------------------------------------------------/
Notes:
To determine, whether this is the line loaded from source, or generated by
macroinstruction, you need to check the highest bit of the second double
word.
The contents of line is no longer a text, which it was in source file,
but a sequence of tokens, ended with a zero byte.
Any chain of characters that aren't special ones, separated from other
similar chains with spaces or some other special characters, is converted
into symbol token. The first byte of this element has the value of 1Ah,
the second byte is the count of characters, followed by this amount of
bytes, which build the symbol.
Some characters have a special meaning, and cannot occur inside the
symbol, they split the symbols and are converted into separate tokens.
For example, if source contains this line of text:
mov ax,4
preprocessor converts it into the chain of bytes, shown here with their
hexadecimal values (characters corresponding to some of those values are
placed below the hexadecimal codes):
1A 03 6D 6F 76 1A 02 61 78 2C 1A 01 34 00
m o v a x , 4
The third type of token that can be found in preprocessed line is the
quoted text. This element is created from chain of any bytes other than
line breaks that are placed between the single or double quotes in the
original text. First byte of such element is always 22h, it is followed
by double word which specifies the number of bytes that follow, and the
value of quoted text comes next. For example, this line from source:
mov eax,'ABCD'
is converted into (the notation used is the same as in previous sample):
1A 03 6D 6F 76 1A 03 65 61 78 2C 22 04 00 00 00 41 42 43 44 00
m o v e a x , A B C D
This data defines two symbols followed by symbol character, quoted text
and zero byte that marks end of line.
There is also a special case of symbol token with first byte having the
value 3Bh instead of 1Ah, such symbol means that all the line elements
that follow, including this one, have already been interpreted by
preprocessor and are ignored by assembler.
Table 4 Row of the assembly dump
/-------------------------------------------------------------------------\
| Offset | Size | Description |
|========|=======|========================================================|
| +0 | dword | Offset in output file. |
|--------|-------|--------------------------------------------------------|
| +4 | dword | Offset of line in preprocessed source. |
|--------|-------|--------------------------------------------------------|
| +8 | qword | Value of $ address. |
|--------|-------|--------------------------------------------------------|
| +16 | dword | Extended SIB for the $ address, the first two bytes |
| | | are register codes and the second two bytes are |
| | | corresponding scales. |
|--------|-------|--------------------------------------------------------|
| +20 | dword | If the $ address is relocatable, this field contains |
| | | information about section or external symbol, to which |
| | | it is relative - otherwise this field is zero. |
| | | When the highest bit is cleared, the address is |
| | | relative to a section, and the bits 0-30 contain |
| | | the index (starting from 1) in the table of sections. |
| | | When the highest bit is set, the address is relative |
| | | to an external symbol, and the bits 0-30 contain the |
| | | the offset of the name of this symbol in the strings |
| | | table. |
|--------|-------|--------------------------------------------------------|
| +24 | byte | Type of $ address value (as in table 2.2). |
|--------|-------|--------------------------------------------------------|
| +25 | byte | Type of code - possible values are 16, 32, and 64. |
|--------|-------|--------------------------------------------------------|
| +26 | byte | If the bit 0 is set, then at this point the assembly |
| | | was taking place inside the virtual block, and the |
| | | offset in output file has no meaning here. |
| | | If the bit 1 is set, the line was assembled at the |
| | | point, which was not included in the output file for |
| | | some other reasons (like inside the reserved data at |
| | | the end of section). |
|--------|-------|--------------------------------------------------------|
| +27 | byte | The higher bits of value of $ address. |
\-------------------------------------------------------------------------/
Notes:
Each row of the assembly dump informs, that the given line of preprocessed
source was assembled at the specified address (defined by its type, value
and the extended SIB) and at the specified position in output file.

View File

@ -0,0 +1,23 @@
macro ccall proc,[arg]
{ common
push ebp
mov ebp,esp
local size
size = 0
if ~ arg eq
forward
size = size + 4
common
sub esp,size
end if
and esp,-16
if ~ arg eq
add esp,size
reverse
pushd arg
common
end if
call proc
leave }

View File

@ -0,0 +1,177 @@
format ELF
public main
include 'ccall.inc'
section '.text' executable align 16
main:
mov ecx,[esp+4]
mov [argc],ecx
mov ebx,[esp+8]
mov [argv],ebx
mov [display_handle],1
call get_params
jnc make_listing
mov esi,_usage
call display_string
ccall exit,2
make_listing:
call listing
ccall exit,0
error:
mov [display_handle],2
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
ccall exit,0
get_params:
mov ecx,[argc]
mov ebx,[argv]
add ebx,4
dec ecx
jz bad_params
get_param:
mov esi,[ebx]
mov al,[esi]
cmp al,'-'
je option_param
cmp [input_file],0
jne get_output_file
mov [input_file],esi
jmp next_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],esi
jmp next_param
option_param:
inc esi
lodsb
cmp al,'a'
je addresses_option
cmp al,'A'
je addresses_option
cmp al,'b'
je bytes_per_line_option
cmp al,'B'
je bytes_per_line_option
bad_params:
stc
ret
addresses_option:
cmp byte [esi],0
jne bad_params
mov [show_addresses],1
jmp next_param
bytes_per_line_option:
cmp byte [esi],0
jne get_bytes_per_line_setting
dec ecx
jz bad_params
add ebx,4
mov esi,[ebx]
get_bytes_per_line_setting:
call get_option_value
or edx,edx
jz bad_params
cmp edx,1000
ja bad_params
mov [code_bytes_per_line],edx
next_param:
add ebx,4
dec ecx
jnz get_param
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc invalid_option_value
cmp al,9
ja invalid_option_value
imul edx,10
jo invalid_option_value
add edx,eax
jc invalid_option_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
invalid_option_value:
stc
ret
include 'system.inc'
include '..\listing.inc'
section '.data' writeable align 4
input_file dd 0
output_file dd 0
code_bytes_per_line dd 16
show_addresses db 0
line_break db 0Dh,0Ah
_usage db 'listing generator for flat assembler',0Dh,0Ah
db 'usage: listing <input> <output>',0Dh,0Ah
db 'optional settings:',0Dh,0Ah
db ' -a show target addresses for assembled code',0Dh,0Ah
db ' -b <number> set the amount of bytes listed per line',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
section '.bss' writeable align 4
argc dd ?
argv dd ?
input dd ?
assembled_code dd ?
assembled_code_length dd ?
code_end dd ?
code_offset dd ?
code_length dd ?
output_handle dd ?
output_buffer dd ?
current_source_file dd ?
current_source_line dd ?
source dd ?
source_length dd ?
maximum_address_length dd ?
address_start dd ?
last_listed_address dd ?
display_handle dd ?
character db ?
params rb 1000h
characters rb 100h
buffer rb 1000h

View File

@ -0,0 +1,94 @@
format ELF
public main
include 'ccall.inc'
section '.text' executable align 16
main:
mov ecx,[esp+4]
mov [argc],ecx
mov ebx,[esp+8]
mov [argv],ebx
mov [display_handle],1
call get_params
jnc make_dump
mov esi,_usage
call display_string
ccall exit,2
make_dump:
call preprocessed_source
ccall exit,0
error:
mov [display_handle],2
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
ccall exit,0
get_params:
mov ecx,[argc]
mov ebx,[argv]
add ebx,4
dec ecx
jz bad_params
get_param:
mov esi,[ebx]
mov al,[esi]
cmp [input_file],0
jne get_output_file
mov [input_file],esi
jmp next_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],esi
jmp next_param
bad_params:
stc
ret
next_param:
add ebx,4
dec ecx
jnz get_param
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
include 'system.inc'
include '..\prepsrc.inc'
section '.data' writeable align 4
input_file dd 0
output_file dd 0
_usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah
db 'usage: prepsrc <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
section '.bss' writeable align 4
argc dd ?
argv dd ?
display_handle dd ?
character db ?
params rb 1000h
buffer rb 1000h

View File

@ -0,0 +1,98 @@
format ELF
public main
include 'ccall.inc'
section '.text' executable align 16
main:
mov ecx,[esp+4]
mov [argc],ecx
mov ebx,[esp+8]
mov [argv],ebx
mov [display_handle],1
call get_params
jnc make_dump
mov esi,_usage
call display_string
ccall exit,2
make_dump:
call symbols
ccall exit,0
error:
mov [display_handle],2
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
ccall exit,0
get_params:
mov ecx,[argc]
mov ebx,[argv]
add ebx,4
dec ecx
jz bad_params
get_param:
mov esi,[ebx]
mov al,[esi]
cmp [input_file],0
jne get_output_file
mov [input_file],esi
jmp next_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],esi
jmp next_param
bad_params:
stc
ret
next_param:
add ebx,4
dec ecx
jnz get_param
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
include 'system.inc'
include '..\symbols.inc'
section '.data' writeable align 4
input_file dd 0
output_file dd 0
_usage db 'symbols dumper for flat assembler',0Dh,0Ah
db 'usage: symbols <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
section '.bss' writeable align 4
input dd ?
output_buffer dd ?
output_handle dd ?
argc dd ?
argv dd ?
display_handle dd ?
character db ?
params rb 1000h
buffer rb 1000h

View File

@ -0,0 +1,107 @@
extrn malloc
extrn getenv
extrn fopen
extrn fclose
extrn fread
extrn fwrite
extrn fseek
extrn ftell
extrn time
extrn exit
extrn 'free' as libc_free
extrn 'write' as libc_write
alloc:
ccall malloc,eax
test eax,eax
jz allocation_failed
clc
ret
allocation_failed:
stc
ret
free:
ccall libc_free,eax
ret
display_string:
lodsb
or al,al
jz string_displayed
mov dl,al
call display_character
jmp display_string
string_displayed:
ret
display_character:
mov [character],dl
ccall libc_write,[display_handle],character,1
ret
open:
push esi edi ebp
call adapt_path
ccall fopen,buffer,open_mode
pop ebp edi esi
or eax,eax
jz file_error
mov ebx,eax
clc
ret
adapt_path:
mov esi,edx
mov edi,buffer
copy_path:
lods byte [esi]
cmp al,'\'
jne path_char_ok
mov al,'/'
path_char_ok:
stos byte [edi]
or al,al
jnz copy_path
cmp edi,buffer+1000h
ja not_enough_memory
ret
create:
push esi edi ebp
call adapt_path
ccall fopen,buffer,create_mode
pop ebp edi esi
or eax,eax
jz file_error
mov ebx,eax
clc
ret
close:
ccall fclose,ebx
ret
read:
push ebx ecx edx esi edi
ccall fread,edx,1,ecx,ebx
pop edi esi edx ecx ebx
cmp eax,ecx
jne file_error
clc
ret
file_error:
stc
ret
write:
push ebx ecx edx esi edi
ccall fwrite,edx,1,ecx,ebx
pop edi esi edx ecx ebx
cmp eax,ecx
jne file_error
clc
ret
lseek:
push ebx
movzx eax,al
ccall fseek,ebx,edx,eax
mov ebx,[esp]
ccall ftell,ebx
pop ebx
ret
open_mode db 'r',0
create_mode db 'w',0

View File

@ -0,0 +1,690 @@
listing:
mov edx,[input_file]
call open
jc input_not_found
call load_file
mov [input],eax
cmp ecx,38h
jb invalid_input
cmp dword [eax],1A736166h
jne invalid_input
cmp dword [eax+44],0
je incomplete_input
add [eax+16],eax
add [eax+24],eax
add [eax+32],eax
add [eax+40],eax
add [eax+48],eax
mov edx,[eax+16]
add [eax+8],edx
add [eax+12],edx
mov edx,[eax+12]
call open
jc code_not_found
call load_file
mov [assembled_code],eax
mov [assembled_code_length],ecx
call close
mov [maximum_address_length],0
mov ebx,[input]
mov esi,[ebx+40]
lea ebp,[esi-4]
add ebp,[ebx+44]
get_offsets_for_lines:
cmp esi,ebp
je offsets_prepared
mov edx,[esi+4]
add edx,[ebx+32]
find_line_loaded_from_source:
test byte [edx+7],1 shl 7
jz store_offset_in_line
mov edx,[edx+8]
add edx,[ebx+32]
jmp find_line_loaded_from_source
store_offset_in_line:
cmp dword [edx+12],0
jne get_next_offset
mov [edx+12],esi
movzx ecx,byte [esi+27]
and cl,1
mov edi,[esi+20]
test edi,edi
jz base_name_length_ok
xor ecx,ecx
btr edi,31
jc count_base_name_characters
dec edi
shl edi,2
add edi,[ebx+48]
mov edi,[edi]
count_base_name_characters:
mov ecx,[ebx+20]
sub ecx,edi
add edi,[ebx+16]
mov edx,edi
xor al,al
repne scasb
mov ecx,edi
sub ecx,edx
base_name_length_ok:
cmp byte [esi+18],1
jb first_register_length_ok
ja first_register_with_scale
add ecx,5
jmp first_register_length_ok
first_register_with_scale:
add ecx,5+3
first_register_length_ok:
cmp byte [esi+19],1
jb second_register_length_ok
ja second_register_with_scale
add ecx,5
jmp second_register_length_ok
second_register_with_scale:
add ecx,5+3
second_register_length_ok:
cmp ecx,[maximum_address_length]
jb get_next_offset
mov [maximum_address_length],ecx
get_next_offset:
add esi,28
jmp get_offsets_for_lines
offsets_prepared:
mov eax,[esi]
mov [code_end],eax
add [maximum_address_length],19
mov edi,characters
xor al,al
make_characters_table:
stosb
inc al
jnz make_characters_table
mov edi,characters
mov esi,symbol_characters+1
movzx ecx,byte [esi-1]
xor eax,eax
mark_symbol_characters:
lodsb
mov byte [edi+eax],0
loop mark_symbol_characters
mov eax,[code_bytes_per_line]
imul eax,3
add eax,[maximum_address_length]
add eax,18
call alloc
jc not_enough_memory
mov [output_buffer],eax
mov esi,[ebx+32]
mov ebp,esi
add ebp,[ebx+36]
mov edx,[output_file]
call create
jc writing_error
mov [output_handle],ebx
xor eax,eax
mov [current_source_file],eax
mov [last_listed_address],eax
mov [code_length],eax
generate_listing:
cmp esi,ebp
jae listing_done
mov edi,[output_buffer]
test byte [esi+7],1 shl 7
jnz next_line
mov ebx,[esi+12]
test ebx,ebx
jz no_code_listing
test byte [ebx+26],11b
jnz no_code_listing
push esi
mov edx,[esi]
mov ecx,[esi+4]
find_next_code_point:
add esi,16
call skip_preprocessed_line
cmp esi,ebp
je last_code_point
cmp edx,[esi]
jne next_line_ok
cmp ecx,[esi+4]
je find_next_code_point
next_line_ok:
test byte [esi+7],1 shl 7
jnz find_next_code_point
mov eax,[esi+12]
test eax,eax
jz find_next_code_point
test byte [eax+26],11b
jnz find_next_code_point
mov eax,[eax]
jmp calculate_code_length
last_code_point:
mov eax,[code_end]
calculate_code_length:
pop esi
mov edx,[ebx]
sub eax,edx
jz no_code_listing
mov [code_length],eax
mov [code_offset],edx
add eax,edx
cmp eax,[assembled_code_length]
jbe write_file_offset
mov [code_length],0
write_file_offset:
call write_hex_dword
mov ax,': '
stosw
call list_address
call list_code
jmp code_listing_ok
no_code_listing:
mov al,20h
mov ecx,8+2
rep stosb
call list_address
mov ecx,[code_bytes_per_line]
imul ecx,3
mov al,20h
rep stosb
code_listing_ok:
call write_listing_data
mov eax,[input]
mov edx,[esi]
test edx,edx
jz main_source_file
add edx,[eax+32]
jmp source_name_ok
main_source_file:
mov edx,[eax+8]
source_name_ok:
cmp edx,[current_source_file]
je source_loaded
push ebx
push edx
call open
jc source_not_found
pop eax
xchg eax,[current_source_file]
test eax,eax
jz load_source
mov eax,[source]
call free
load_source:
call load_file
mov [source],eax
mov [source_length],ecx
call close
pop ebx
source_loaded:
mov eax,[source]
add eax,[esi+8]
mov [current_source_line],eax
push esi ebp
call write_source_line
pop ebp esi
write_supplemental_rows:
mov eax,[code_length]
or eax,[current_source_line]
jz next_line
mov edi,[output_buffer]
mov ecx,8+2
movzx eax,[show_addresses]
imul eax,[maximum_address_length]
add ecx,eax
mov al,20h
rep stosb
call list_code
call write_listing_data
push esi ebp
call write_source_line
pop ebp esi
jmp write_supplemental_rows
next_line:
mov edx,[esi]
mov ecx,[esi+4]
find_next_line:
add esi,16
call skip_preprocessed_line
cmp edx,[esi]
jne generate_listing
cmp ecx,[esi+4]
jne generate_listing
jmp find_next_line
list_address:
cmp [show_addresses],0
je address_ok
mov [address_start],edi
mov eax,[esi+12]
test eax,eax
jz address_finished
cmp [last_listed_address],0
je make_address
push esi edi
lea esi,[eax+8]
mov edi,[last_listed_address]
mov ecx,17
repe cmpsb
pop edi esi
je address_finished
make_address:
mov ebx,[esi+12]
lea eax,[ebx+8]
mov [last_listed_address],eax
mov al,'['
stosb
mov edx,[ebx+20]
test edx,edx
jz write_main_address
push esi
mov esi,edx
mov eax,[input]
btr esi,31
jc base_name_ready
dec esi
shl esi,2
add esi,[eax+48]
mov esi,[esi]
base_name_ready:
add esi,[eax+16]
copy_section_name:
lodsb
test al,al
jz section_name_ok
stosb
jmp copy_section_name
section_name_ok:
pop esi
mov al,':'
test edx,80000000h
jz address_separator_ok
cmp byte [ebx+27],0
jne address_separator_ok
mov al,'+'
address_separator_ok:
stosb
write_main_address:
cmp byte [ebx+27],0
jne write_negative_address
mov edx,[ebx+8+4]
call write_hex_dword
mov edx,[ebx+8]
call write_hex_dword
jmp write_address_registers
write_negative_address:
mov al,'-'
stosb
mov eax,[ebx+8]
mov edx,[ebx+8+4]
not eax
not edx
add eax,1
adc edx,0
push eax
call write_hex_dword
pop edx
call write_hex_dword
write_address_registers:
mov dl,[ebx+16]
mov dh,[ebx+18]
call address_register
mov dl,[ebx+17]
mov dh,[ebx+19]
call address_register
mov ax,']'
stosb
address_finished:
mov ecx,[maximum_address_length]
sub ecx,edi
add ecx,[address_start]
mov al,20h
rep stosb
address_ok:
ret
address_register:
cmp dh,0
je register_ok
jl negative_register
mov al,'+'
jmp register_sign_ok
negative_register:
mov al,'-'
register_sign_ok:
stosb
push esi
mov esi,address_registers
find_register:
lodsb
test al,al
jz register_found
cmp al,dl
je register_found
cmp dl,[esi]
je register_found
lodsb
movzx eax,al
add esi,eax
jmp find_register
register_found:
lodsb
movzx ecx,al
rep movsb
pop esi
cmp dh,1
je register_ok
mov al,'*'
stosb
test dh,0F0h
jz first_scale_digit_ok
mov al,dh
shr al,4
cmp al,10
sbb al,69h
das
stosb
first_scale_digit_ok:
mov al,dh
and al,1111b
cmp al,10
sbb al,69h
das
stosb
register_ok:
ret
list_code:
mov ecx,[code_length]
cmp ecx,[code_bytes_per_line]
jb code_bytes_count_ready
mov ecx,[code_bytes_per_line]
code_bytes_count_ready:
sub [code_length],ecx
mov edx,[code_offset]
add [code_offset],ecx
jecxz code_bytes_ok
push ecx
add edx,[assembled_code]
list_code_bytes:
mov al,[edx]
and al,1111b
cmp al,10
sbb al,69h
das
mov ah,al
mov al,[edx]
shr al,4
cmp al,10
sbb al,69h
das
stosw
mov al,20h
stosb
inc edx
loop list_code_bytes
pop ecx
code_bytes_ok:
neg ecx
add ecx,[code_bytes_per_line]
imul ecx,3
mov al,20h
rep stosb
ret
write_listing_data:
mov ecx,[output_buffer]
sub ecx,edi
and ecx,111b
mov al,20h
rep stosb
mov edx,[output_buffer]
mov ecx,edi
sub ecx,edx
mov ebx,[output_handle]
call write
jc writing_error
ret
write_source_line:
mov esi,[current_source_line]
test esi,esi
je write_line_break
mov ebp,[source_length]
add ebp,[source]
mov ebx,characters
xor cl,cl
start_cutting:
xor dl,dl
cut_source_line:
cmp esi,ebp
je end_of_file
lodsb
cmp al,0Dh
je cr_character
cmp al,0Ah
je lf_character
cmp al,1Ah
je end_of_line
or al,al
jz end_of_line
cmp dl,3Bh
je cut_source_line
cmp al,3Bh
je start_special_block
cmp dl,22h
je inside_string
cmp dl,27h
je inside_string
cmp al,'\'
je check_for_line_continuation
xlatb
test al,al
jz start_cutting
cmp dl,0FFh
je cut_source_line
cmp al,22h
je start_special_block
cmp al,27h
je start_special_block
mov dl,0FFh
jmp cut_source_line
start_special_block:
mov dl,al
jmp cut_source_line
inside_string:
cmp al,dl
jne cut_source_line
jmp start_cutting
check_for_line_continuation:
or cl,0FFh
cmp esi,ebp
je end_of_file
mov al,[esi]
cmp al,20h
je start_cutting
cmp al,0Dh
je start_cutting
cmp al,0Ah
je start_cutting
cmp al,3Bh
je start_cutting
xor cl,cl
jmp start_cutting
cr_character:
mov edx,esi
mov word [line_break],0Dh
cmp esi,ebp
je line_with_break
mov al,[esi]
cmp al,0Ah
jne line_with_break
inc edx
mov [line_break+1],al
jmp line_with_break
lf_character:
mov edx,esi
mov word [line_break],0Ah
cmp esi,ebp
je line_with_break
mov al,[esi]
cmp al,0Dh
jne line_with_break
inc edx
mov [line_break+1],al
line_with_break:
dec esi
jmp write_line
end_of_line:
dec esi
end_of_file:
mov edx,esi
write_line:
cmp cl,0FFh
je continued_line
xor edx,edx
continued_line:
xchg edx,[current_source_line]
mov ecx,esi
sub ecx,edx
mov ebx,[output_handle]
call write
jc writing_error
write_line_break:
mov edx,line_break
mov ecx,2
cmp [line_break+1],0
jne line_break_size_ok
dec ecx
line_break_size_ok:
call write
jc writing_error
ret
listing_done:
mov ebx,[output_handle]
call close
ret
load_file:
push ebx
mov al,2
xor edx,edx
call lseek
test eax,eax
jz empty_file
push eax
call alloc
jc not_enough_memory
push eax
xor al,al
xor edx,edx
call lseek
mov ecx,[esp+4]
mov edx,[esp]
call read
jc reading_error
pop eax ecx
pop ebx
ret
empty_file:
pop ebx
mov ecx,eax
ret
write_hex_dword:
mov ecx,8
write_hex_digits:
xor al,al
shld eax,edx,4
cmp al,10
sbb al,69h
das
stosb
shl edx,4
loop write_hex_digits
ret
skip_preprocessed_line:
lods byte [esi]
cmp al,1Ah
je skip_preprocessed_symbol
cmp al,3Bh
je skip_preprocessed_symbol
cmp al,22h
je skip_preprocessed_string
or al,al
jnz skip_preprocessed_line
ret
skip_preprocessed_symbol:
lods byte [esi]
movzx eax,al
add esi,eax
jmp skip_preprocessed_line
skip_preprocessed_string:
lods dword [esi]
add esi,eax
jmp skip_preprocessed_line
not_enough_memory:
call error
db 'not enough memory to load the required data',0
input_not_found:
call error
db 'the input file was not found',0
code_not_found:
call error
db 'the assembled file was not found',0
source_not_found:
call error
db 'could not find some of the source files',0
reading_error:
call error
db 'some error occured while trying to read file',0
writing_error:
call error
db 'some error occured while trying to write file',0
invalid_input:
call error
db 'input file is not a recognized assembly information format',0
incomplete_input:
call error
db 'input file does not contain an assembly dump',0
symbol_characters db 27, 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\'
address_registers db 23h,2,'bx'
db 25h,2,'bp'
db 26h,2,'si'
db 27h,2,'di'
db 40h,3,'eax'
db 41h,3,'ecx'
db 42h,3,'edx'
db 43h,3,'ebx'
db 44h,3,'esp'
db 45h,3,'ebp'
db 46h,3,'esi'
db 47h,3,'edi'
db 48h,3,'r8d'
db 49h,3,'r9d'
db 4Ah,4,'r10d'
db 4Bh,4,'r11d'
db 4Ch,4,'r12d'
db 4Dh,4,'r13d'
db 4Eh,4,'r14d'
db 4Fh,4,'r15d'
db 80h,3,'rax'
db 81h,3,'rcx'
db 82h,3,'rdx'
db 83h,3,'rbx'
db 84h,3,'rsp'
db 85h,3,'rbp'
db 86h,3,'rsi'
db 87h,3,'rdi'
db 88h,2,'r8'
db 89h,2,'r9'
db 8Ah,3,'r10'
db 8Bh,3,'r11'
db 8Ch,3,'r12'
db 8Dh,3,'r13'
db 8Eh,3,'r14'
db 8Fh,3,'r15'
db 0F4h,3,'eip'
db 0F8h,3,'rip'
db 0,1,'?'

View File

@ -0,0 +1,115 @@
preprocessed_source:
mov edx,[input_file]
call open
jc input_not_found
mov al,2
xor edx,edx
call lseek
cmp eax,30h
jb invalid_input
push eax
call alloc
jc not_enough_memory
push eax
xor al,al
xor edx,edx
call lseek
mov ecx,[esp+4]
mov edx,[esp]
call read
jc reading_error
pop eax ecx
cmp dword [eax],1A736166h
jne invalid_input
mov esi,[eax+32]
add esi,eax
mov ebp,[eax+36]
add ebp,esi
mov edi,eax
push eax
preprocessed_to_text:
cmp esi,ebp
jae conversion_done
add esi,16
xor dl,dl
convert_preprocessed_line:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je preprocessor_symbols
or al,al
jz line_converted
stosb
xor dl,dl
jmp convert_preprocessed_line
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_preprocessed_line
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_preprocessed_line
preprocessor_symbols:
mov al,3Bh
stosb
jmp copy_symbol
line_converted:
mov ax,0A0Dh
stosw
jmp preprocessed_to_text
conversion_done:
mov edx,[output_file]
call create
jc writing_error
pop edx
mov ecx,edi
sub ecx,edx
call write
jc writing_error
call close
ret
not_enough_memory:
call error
db 'not enough memory to load the required data',0
input_not_found:
call error
db 'the input file was not found',0
reading_error:
call error
db 'some error occured while trying to read file',0
writing_error:
call error
db 'some error occured while trying to write file',0
invalid_input:
call error
db 'input file is not a recognized assembly information format',0

View File

@ -0,0 +1,26 @@
This directory contains some tools, which extract various types of information
from the symbolic information file generated by flat assembler, and present
them in a human-readable form.
The listing tool creates a listing of assembled code - this tool needs to be
executed in the exact configuration, in which the assembly was taking place.
All the source files and the output file aswell must not have been moved or
modified - if any of them was altered before generating the listing, it is
going to contain garbage instead of useful information. For example, if you
assembled the file with the command like:
fasm example.asm example.exe -s example.fas
you should generate listing by immediately running this command from the same
directory:
listing example.fas example.lst
In addition, the "-a" switch is recommended to use in the case of executable
formats, as it allows to get the run-time addresses for all the assembled code
and data.
The preprocessed source and symbols dump tools are simpler ones - they only
need the symbolic information file as input and generate proper output text
regardless of the availability of other files.

View File

@ -0,0 +1,444 @@
symbols:
mov edx,[input_file]
call open
jc input_not_found
mov al,2
xor edx,edx
call lseek
cmp eax,30h
jb invalid_input
push eax
call alloc
jc not_enough_memory
push eax
xor al,al
xor edx,edx
call lseek
mov ecx,[esp+4]
mov edx,[esp]
call read
jc reading_error
pop eax ecx
cmp dword [eax],1A736166h
jne invalid_input
mov [input],eax
add [eax+16],eax
add [eax+24],eax
add [eax+32],eax
add [eax+48],eax
mov edx,[eax+16]
add [eax+8],edx
mov ebx,eax
mov eax,[ebx+20]
add eax,[ebx+36]
cmp eax,1000h
ja allocate_output_buffer
mov eax,1000h
allocate_output_buffer:
call alloc
jc not_enough_memory
mov [output_buffer],eax
mov edx,[output_file]
call create
jc writing_error
mov [output_handle],ebx
mov ebx,[input]
mov edx,[ebx+24]
mov ebp,[ebx+28]
add ebp,edx
dump_symbols:
cmp edx,ebp
je dump_done
test byte [edx+8],1
jz next_symbol
test byte [edx+9],4
jnz next_symbol
mov edi,[output_buffer]
mov esi,[edx+24]
test esi,esi
jz anonymous_symbol
mov ebx,[input]
btr esi,31
jc symbol_name_in_strings_table
add esi,[ebx+32]
lodsb
movzx ecx,al
rep movsb
jmp symbol_name_ok
symbol_name_in_strings_table:
add esi,[ebx+16]
call write_string
jmp symbol_name_ok
anonymous_symbol:
mov al,'@'
stosb
stosb
symbol_name_ok:
test byte [edx+9],2
jnz negative_value
mov eax,': 0x'
stosd
mov eax,[edx+4]
call write_hex_dword
mov eax,[edx]
call write_hex_dword
jmp write_address_registers
negative_value:
mov eax,': -0'
stosd
mov al,'x'
stosb
mov ecx,[edx]
mov eax,[edx+4]
not ecx
not eax
add ecx,1
adc eax,0
push ecx
or ecx,eax
jnz negative_value_ok
mov byte [edi],'1'
inc edi
negative_value_ok:
call write_hex_dword
pop eax
call write_hex_dword
write_address_registers:
mov bl,[edx+12]
mov bh,[edx+14]
call write_address_register
mov bl,[edx+13]
mov bh,[edx+15]
call write_address_register
mov bl,[edx+11]
cmp bl,0
je symbol_type_ok
jl negated_symbol
mov ax,', '
stosw
jmp write_symbol_type
negated_symbol:
mov ax,', '
stosw
mov esi,_negated
call write_string
neg bl
write_symbol_type:
cmp bl,1
je segment_type
cmp bl,5
je rva_type
cmp bl,6
je plt_type
test byte [edx+20+3],80h
jnz external
mov esi,_relocatable
call write_string
cmp dword [edx+20],0
je symbol_type_ok
mov esi,_in_section
call write_string
jmp write_symbol_base
simple_relocatable:
mov esi,_relocatable
call write_string
jmp symbol_type_ok
external:
mov esi,_relative_to_external
call write_string
jmp write_symbol_base
segment_type:
mov esi,_relocatable_segment
call write_string
jmp symbol_type_ok
rva_type:
mov esi,_rva
call write_string
jmp write_symbol_base
plt_type:
mov esi,_plt
call write_string
write_symbol_base:
mov esi,[edx+20]
btr esi,31
jc write_external_name
dec esi
shl esi,2
mov ebx,[input]
add esi,[ebx+48]
mov esi,[esi]
add esi,[ebx+16]
call write_string
mov al,'('
stosb
mov eax,[edx+20]
call write_dec_number
mov al,')'
stosb
jmp symbol_type_ok
write_external_name:
mov ebx,[input]
add esi,[ebx+16]
call write_string
jmp symbol_type_ok
symbol_type_ok:
mov esi,_defined
call write_string
mov ebx,[edx+28]
mov eax,[input]
add ebx,[eax+32]
call write_line_identifier
mov ax,0A0Dh
stosw
push edx
mov ebx,[output_handle]
mov ecx,edi
mov edx,[output_buffer]
sub ecx,edx
call write
pop edx
next_symbol:
add edx,32
jmp dump_symbols
dump_done:
mov ebx,[output_handle]
call close
ret
write_string:
lodsb
test al,al
jz string_ok
stosb
jmp write_string
string_ok:
ret
write_hex_dword:
mov ebx,eax
mov ecx,8
write_hex_digits:
xor al,al
shld eax,ebx,4
cmp al,10
sbb al,69h
das
stosb
shl ebx,4
loop write_hex_digits
ret
write_dec_number:
push ebx edx
mov ecx,1000000000
xor edx,edx
xor bl,bl
dec_number_loop:
div ecx
push edx
cmp ecx,1
je write_dec_digit
or bl,bl
jnz write_dec_digit
or al,al
jz dec_digit_ok
not bl
write_dec_digit:
add al,30h
stosb
dec_digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
pop eax
or ecx,ecx
jnz dec_number_loop
pop edx ebx
ret
write_address_register:
cmp bh,0
je register_ok
jl negative_register
mov al,'+'
jmp register_sign_ok
negative_register:
mov al,'-'
register_sign_ok:
stosb
push esi
mov esi,address_registers
find_register:
lodsb
test al,al
jz register_not_found
cmp al,bl
je register_found
cmp bl,[esi]
je register_found
lodsb
movzx eax,al
add esi,eax
jmp find_register
register_not_found:
mov al,bl
shr al,5
cmp al,0Ch shr 1
je xmm_register
cmp al,0Eh shr 1
je ymm_register
cmp al,6 shr 1
je zmm_register
register_found:
lodsb
movzx ecx,al
rep movsb
write_register_scale:
pop esi
cmp bh,1
je register_ok
mov al,'*'
stosb
movzx eax,bh
call write_dec_number
register_ok:
ret
zmm_register:
mov al,'z'
jmp vector_address_register
ymm_register:
mov al,'y'
jmp vector_address_register
xmm_register:
mov al,'x'
vector_address_register:
stosb
mov ax,'mm'
stosw
mov al,bl
and eax,11111b
call write_dec_number
jmp write_register_scale
write_line_identifier:
test dword [ebx+4],80000000h
jnz identify_macro_generated_line
mov esi,[ebx]
mov eax,[input]
test esi,esi
jz main_file
add esi,[eax+32]
jmp file_name_ok
main_file:
mov esi,[eax+8]
file_name_ok:
call write_string
mov al,'['
stosb
mov eax,[ebx+4]
call write_dec_number
mov al,']'
stosb
ret
identify_macro_generated_line:
mov al,'{'
stosb
mov esi,_generated_by
call write_string
push ebx
mov ebx,[ebx+8]
mov eax,[input]
add ebx,[eax+32]
call write_line_identifier
pop ebx
mov eax,[ebx+8]
cmp eax,[ebx+12]
je macro_generated_line_identifier_ok
mov esi,_from
call write_string
push ebx
mov ebx,[ebx+12]
mov eax,[input]
add ebx,[eax+32]
call write_line_identifier
pop ebx
macro_generated_line_identifier_ok:
mov al,'}'
stosb
ret
not_enough_memory:
call error
db 'not enough memory to load the required data',0
input_not_found:
call error
db 'the input file was not found',0
code_not_found:
call error
db 'the assembled file was not found',0
source_not_found:
call error
db 'could not find some of the source files',0
reading_error:
call error
db 'some error occured while trying to read file',0
writing_error:
call error
db 'some error occured while trying to write file',0
invalid_input:
call error
db 'input file is not a recognized assembly information format',0
address_registers db 23h,2,'bx'
db 25h,2,'bp'
db 26h,2,'si'
db 27h,2,'di'
db 40h,3,'eax'
db 41h,3,'ecx'
db 42h,3,'edx'
db 43h,3,'ebx'
db 44h,3,'esp'
db 45h,3,'ebp'
db 46h,3,'esi'
db 47h,3,'edi'
db 48h,3,'r8d'
db 49h,3,'r9d'
db 4Ah,4,'r10d'
db 4Bh,4,'r11d'
db 4Ch,4,'r12d'
db 4Dh,4,'r13d'
db 4Eh,4,'r14d'
db 4Fh,4,'r15d'
db 80h,3,'rax'
db 81h,3,'rcx'
db 82h,3,'rdx'
db 83h,3,'rbx'
db 84h,3,'rsp'
db 85h,3,'rbp'
db 86h,3,'rsi'
db 87h,3,'rdi'
db 88h,2,'r8'
db 89h,2,'r9'
db 8Ah,3,'r10'
db 8Bh,3,'r11'
db 8Ch,3,'r12'
db 8Dh,3,'r13'
db 8Eh,3,'r14'
db 8Fh,3,'r15'
db 94h,3,'eip'
db 98h,3,'rip'
db 0,1,'?'
_negated db 'negated ',0
_relocatable_segment db 'relocatable segment',0
_relocatable db 'relocatable',0
_in_section db ' in section ',0
_relative_to_external db 'relative to external ',0
_rva db 'relative to RVA or GOT-based offset of ',0
_plt db 'relative to address of PLT entry for ',0
_defined db ', defined in ',0
_generated_by db 'line generated by ',0
_from db ' from ',0

View File

@ -0,0 +1,229 @@
format PE console 4.0
entry start
include 'win32a.inc'
section '.data' data readable writeable
_usage db 'listing generator for flat assembler',0Dh,0Ah
db 'usage: listing <input> <output>',0Dh,0Ah
db 'optional settings:',0Dh,0Ah
db ' -a show target addresses for assembled code',0Dh,0Ah
db ' -b <number> set the amount of bytes listed per line',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
line_break db 0Dh,0Ah
input_file dd 0
output_file dd 0
code_bytes_per_line dd 16
show_addresses db 0
input dd ?
assembled_code dd ?
assembled_code_length dd ?
code_end dd ?
code_offset dd ?
code_length dd ?
output_handle dd ?
output_buffer dd ?
current_source_file dd ?
current_source_line dd ?
source dd ?
source_length dd ?
maximum_address_length dd ?
address_start dd ?
last_listed_address dd ?
display_handle dd ?
bytes_count dd ?
params rb 1000h
characters rb 100h
section '.text' code readable executable
start:
mov [display_handle],STD_OUTPUT_HANDLE
call get_params
jnc make_listing
mov esi,_usage
call display_string
invoke ExitProcess,2
make_listing:
call listing
invoke ExitProcess,0
error:
mov [display_handle],STD_ERROR_HANDLE
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
invoke ExitProcess,1
get_params:
invoke GetCommandLine
mov esi,eax
mov edi,params
find_command_start:
lodsb
cmp al,20h
je find_command_start
cmp al,22h
je skip_quoted_name
skip_name:
lodsb
cmp al,20h
je find_param
or al,al
jz all_params
jmp skip_name
skip_quoted_name:
lodsb
cmp al,22h
je find_param
or al,al
jz all_params
jmp skip_quoted_name
find_param:
lodsb
cmp al,20h
je find_param
cmp al,'-'
je option_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [input_file],0
jne get_output_file
mov [input_file],edi
jmp process_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
option_param:
lodsb
cmp al,'a'
je addresses_option
cmp al,'A'
je addresses_option
cmp al,'b'
je bytes_per_line_option
cmp al,'B'
je bytes_per_line_option
bad_params:
stc
ret
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc invalid_option_value
cmp al,9
ja invalid_option_value
imul edx,10
jo invalid_option_value
add edx,eax
jc invalid_option_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
invalid_option_value:
stc
ret
bytes_per_line_option:
lodsb
cmp al,20h
je bytes_per_line_option
cmp al,0Dh
je bad_params
or al,al
jz bad_params
dec esi
call get_option_value
or edx,edx
jz bad_params
cmp edx,1000
ja bad_params
mov [code_bytes_per_line],edx
jmp find_param
addresses_option:
lodsb
cmp al,20h
je set_addresses_option
cmp al,0Dh
je set_addresses_option
or al,al
jnz bad_params
set_addresses_option:
dec esi
mov [show_addresses],1
jmp find_param
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
include 'system.inc'
include '..\listing.inc'
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL'
include 'api\kernel32.inc'

View File

@ -0,0 +1,138 @@
format PE console 4.0
entry start
include 'win32a.inc'
section '.data' data readable writeable
_usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah
db 'usage: prepsrc <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
input_file dd 0
output_file dd 0
display_handle dd ?
bytes_count dd ?
params rb 1000h
section '.text' code readable executable
start:
mov [display_handle],STD_OUTPUT_HANDLE
call get_params
jnc make_dump
mov esi,_usage
call display_string
invoke ExitProcess,2
make_dump:
call preprocessed_source
invoke ExitProcess,0
error:
mov [display_handle],STD_ERROR_HANDLE
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
invoke ExitProcess,1
get_params:
invoke GetCommandLine
mov esi,eax
mov edi,params
find_command_start:
lodsb
cmp al,20h
je find_command_start
cmp al,22h
je skip_quoted_name
skip_name:
lodsb
cmp al,20h
je find_param
or al,al
jz all_params
jmp skip_name
skip_quoted_name:
lodsb
cmp al,22h
je find_param
or al,al
jz all_params
jmp skip_quoted_name
find_param:
lodsb
cmp al,20h
je find_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [input_file],0
jne get_output_file
mov [input_file],edi
jmp process_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
bad_params:
stc
ret
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
include 'system.inc'
include '..\prepsrc.inc'
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL'
include 'api\kernel32.inc'

View File

@ -0,0 +1,142 @@
format PE console 4.0
entry start
include 'win32a.inc'
section '.data' data readable writeable
_usage db 'symbols dumper for flat assembler',0Dh,0Ah
db 'usage: symbols <input> <output>',0Dh,0Ah
db 0
_error_prefix db 'error: ',0
_error_suffix db '.',0Dh,0Ah,0
input_file dd 0
output_file dd 0
input dd ?
output_buffer dd ?
output_handle dd ?
display_handle dd ?
bytes_count dd ?
params rb 1000h
section '.text' code readable executable
start:
mov [display_handle],STD_OUTPUT_HANDLE
call get_params
jnc make_dump
mov esi,_usage
call display_string
invoke ExitProcess,2
make_dump:
call symbols
invoke ExitProcess,0
error:
mov [display_handle],STD_ERROR_HANDLE
mov esi,_error_prefix
call display_string
pop esi
call display_string
mov esi,_error_suffix
call display_string
invoke ExitProcess,1
get_params:
invoke GetCommandLine
mov esi,eax
mov edi,params
find_command_start:
lodsb
cmp al,20h
je find_command_start
cmp al,22h
je skip_quoted_name
skip_name:
lodsb
cmp al,20h
je find_param
or al,al
jz all_params
jmp skip_name
skip_quoted_name:
lodsb
cmp al,22h
je find_param
or al,al
jz all_params
jmp skip_quoted_name
find_param:
lodsb
cmp al,20h
je find_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [input_file],0
jne get_output_file
mov [input_file],edi
jmp process_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
bad_params:
stc
ret
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
cmp [input_file],0
je bad_params
cmp [output_file],0
je bad_params
clc
ret
include 'system.inc'
include '..\symbols.inc'
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL'
include 'api\kernel32.inc'

View File

@ -0,0 +1,66 @@
display_string:
invoke GetStdHandle,[display_handle]
mov edx,eax
mov edi,esi
or ecx,-1
xor al,al
repne scasb
neg ecx
sub ecx,2
invoke WriteFile,edx,esi,ecx,bytes_count,0
retn
alloc:
invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE
or eax,eax
jz allocation_error
clc
retn
allocation_error:
stc
retn
free:
invoke VirtualFree,eax,0,MEM_RELEASE
retn
open:
invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
cmp eax,-1
je file_error
mov ebx,eax
clc
retn
file_error:
stc
retn
create:
invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
cmp eax,-1
je file_error
mov ebx,eax
clc
retn
write:
invoke WriteFile,ebx,edx,ecx,bytes_count,0
or eax,eax
jz file_error
clc
retn
read:
push ecx
invoke ReadFile,ebx,edx,ecx,bytes_count,0
pop edx
or eax,eax
jz file_error
cmp edx,[bytes_count]
jne file_error
clc
retn
close:
invoke CloseHandle,ebx
retn
lseek:
movzx eax,al
invoke SetFilePointer,ebx,edx,0,eax
cmp eax,-1
je file_error
retn