added fasm2 as well

This commit is contained in:
2024-11-25 00:04:53 -05:00
parent 8a974e9c89
commit dceb330571
165 changed files with 78512 additions and 0 deletions

View File

@ -0,0 +1,23 @@
macro ccall proc*,[arg]
{
common
local size,count
mov ebp,esp
if size
sub esp,size
end if
and esp,0FFFFFFF0h
count = 0
if ~ arg eq
forward
mov dword [esp+count*4],arg
count = count + 1
common
end if
size = count*4
call proc
mov esp,ebp
}
macro cinvoke proc*,arg& { ccall [proc],arg }

View File

@ -0,0 +1,489 @@
format ELF
public main
include '../version.inc'
include 'macro/struct.inc'
include 'macro/proc32.inc'
extrn 'malloc' as libc.malloc
extrn 'realloc' as libc.realloc
extrn 'free' as libc.free
extrn 'fopen' as libc.fopen
extrn 'fclose' as libc.fclose
extrn 'fread' as libc.fread
extrn 'fwrite' as libc.fwrite
extrn 'fseek' as libc.fseek
extrn 'ftell' as libc.ftell
extrn 'time' as libc.time
extrn 'write' as libc.write
extrn getenv
extrn gettimeofday
extrn exit
struct timeval
time_t dd ?
suseconds_t dd ?
ends
section '.text' executable align 16
main:
mov ecx,[esp+4]
mov [argc],ecx
mov ebx,[esp+8]
mov [argv],ebx
call system_init
call get_arguments
mov bl,al
cmp [no_logo],0
jne logo_ok
mov esi,_logo
xor ecx,ecx
call display_string
logo_ok:
test bl,bl
jnz display_usage_information
xor al,al
mov ecx,[verbosity_level]
jecxz init
or al,TRACE_ERROR_STACK
dec ecx
jz init
or al,TRACE_DISPLAY
init:
call assembly_init
ccall gettimeofday,start_time,0
assemble:
mov esi,[initial_commands]
mov edx,[source_path]
call assembly_pass
jc assembly_done
mov eax,[current_pass]
cmp eax,[maximum_number_of_passes]
jb assemble
call show_display_data
mov esi,_error_prefix
xor ecx,ecx
call display_error_string
mov esi,_code_cannot_be_generated
xor ecx,ecx
call display_error_string
mov esi,_message_suffix
xor ecx,ecx
call display_error_string
jmp assembly_failed
assembly_done:
call show_display_data
cmp [first_error],0
jne assembly_failed
cmp [no_logo],0
jne summary_done
mov eax,[current_pass]
xor edx,edx
call itoa
call display_string
mov esi,_passes
cmp [current_pass],1
jne display_passes_suffix
mov esi,_pass
display_passes_suffix:
xor ecx,ecx
call display_string
ccall gettimeofday,end_time,0
mov eax,[end_time.time_t]
sub eax,[start_time.time_t]
mov ecx,1000000
mul ecx
add eax,[end_time.suseconds_t]
adc edx,0
sub eax,[start_time.suseconds_t]
sbb edx,0
add eax,50000
mov ecx,1000000
div ecx
mov ebx,eax
mov eax,edx
xor edx,edx
mov ecx,100000
div ecx
mov [tenths_of_second],eax
xchg eax,ebx
or ebx,eax
jz display_output_length
xor edx,edx
call itoa
call display_string
mov esi,_message_suffix
mov ecx,1
call display_string
mov eax,[tenths_of_second]
xor edx,edx
call itoa
call display_string
mov esi,_seconds
xor ecx,ecx
call display_string
display_output_length:
call get_output_length
push eax edx
call itoa
call display_string
pop edx eax
mov esi,_bytes
cmp eax,1
jne display_bytes_suffix
test edx,edx
jnz display_bytes_suffix
mov esi,_byte
display_bytes_suffix:
xor ecx,ecx
call display_string
mov esi,_new_line
xor ecx,ecx
call display_string
summary_done:
mov ebx,[source_path]
mov edi,[output_path]
call write_output_file
jc write_failed
call assembly_shutdown
call system_shutdown
ccall exit,0
assembly_failed:
call show_errors
call assembly_shutdown
call system_shutdown
ccall exit,2
write_failed:
mov ebx,_write_failed
jmp fatal_error
out_of_memory:
mov ebx,_out_of_memory
jmp fatal_error
fatal_error:
mov esi,_error_prefix
xor ecx,ecx
call display_error_string
mov esi,ebx
xor ecx,ecx
call display_error_string
mov esi,_message_suffix
xor ecx,ecx
call display_error_string
call assembly_shutdown
call system_shutdown
ccall exit,3
display_usage_information:
mov esi,_usage
xor ecx,ecx
call display_string
call system_shutdown
ccall exit,1
get_arguments:
xor eax,eax
mov [initial_commands],eax
mov [source_path],eax
mov [output_path],eax
mov [no_logo],al
mov [verbosity_level],eax
mov [maximum_number_of_passes],100
mov [maximum_number_of_errors],1
mov [maximum_depth_of_stack],10000
mov ecx,[argc]
mov ebx,[argv]
add ebx,4
dec ecx
jz error_in_arguments
get_argument:
mov esi,[ebx]
mov al,[esi]
cmp al,'-'
je get_option
cmp [source_path],0
jne get_output_file
mov [source_path],esi
jmp next_argument
get_output_file:
cmp [output_path],0
jne error_in_arguments
mov [output_path],esi
jmp next_argument
get_option:
inc esi
lodsb
cmp al,'e'
je set_errors_limit
cmp al,'E'
je set_errors_limit
cmp al,'i'
je insert_initial_command
cmp al,'I'
je insert_initial_command
cmp al,'p'
je set_passes_limit
cmp al,'P'
je set_passes_limit
cmp al,'r'
je set_recursion_limit
cmp al,'R'
je set_recursion_limit
cmp al,'v'
je set_verbose_mode
cmp al,'V'
je set_verbose_mode
cmp al,'n'
je set_no_logo
cmp al,'N'
jne error_in_arguments
set_no_logo:
or [no_logo],-1
cmp byte [esi],0
je next_argument
error_in_arguments:
or al,-1
ret
set_verbose_mode:
cmp byte [esi],0
jne get_verbose_setting
dec ecx
jz error_in_arguments
add ebx,4
mov esi,[ebx]
get_verbose_setting:
call get_option_value
cmp edx,2
ja error_in_arguments
mov [verbosity_level],edx
jmp next_argument
set_errors_limit:
cmp byte [esi],0
jne get_errors_setting
dec ecx
jz error_in_arguments
add ebx,4
mov esi,[ebx]
get_errors_setting:
call get_option_value
test edx,edx
jz error_in_arguments
mov [maximum_number_of_errors],edx
jmp next_argument
set_recursion_limit:
cmp byte [esi],0
jne get_recursion_setting
dec ecx
jz error_in_arguments
add ebx,4
mov esi,[ebx]
get_recursion_setting:
call get_option_value
test edx,edx
jz error_in_arguments
mov [maximum_depth_of_stack],edx
jmp next_argument
set_passes_limit:
cmp byte [esi],0
jne get_passes_setting
dec ecx
jz error_in_arguments
add ebx,4
mov esi,[ebx]
get_passes_setting:
call get_option_value
test edx,edx
jz error_in_arguments
mov [maximum_number_of_passes],edx
next_argument:
add ebx,4
dec ecx
jnz get_argument
cmp [source_path],0
je error_in_arguments
xor al,al
ret
get_option_value:
xor eax,eax
mov edx,eax
find_option_value:
cmp byte [esi],20h
jne get_option_digit
inc esi
jmp find_option_value
get_option_digit:
lodsb
test 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
insert_initial_command:
cmp byte [esi],0
jne measure_initial_command
dec ecx
jz error_in_arguments
add ebx,4
mov esi,[ebx]
measure_initial_command:
push ebx ecx edi
mov edi,esi
or ecx,-1
xor al,al
repne scasb
not ecx
dec ecx
mov edi,[initial_commands]
lea eax,[ecx+2]
test edi,edi
jz allocate_initial_commands_buffer
mov edx,[initial_commands_length]
add edi,edx
add eax,edx
cmp eax,[initial_commands_maximum_length]
ja grow_initial_commands_buffer
copy_initial_command:
rep movsb
mov ax,0Ah
stosw
dec edi
sub edi,[initial_commands]
mov [initial_commands_length],edi
pop edi ecx ebx
jmp next_argument
allocate_initial_commands_buffer:
push ecx
mov ecx,eax
call malloc
mov [initial_commands],eax
mov [initial_commands_maximum_length],ecx
mov edi,eax
pop ecx
jmp copy_initial_command
grow_initial_commands_buffer:
push ecx
mov ecx,eax
mov eax,[initial_commands]
call realloc
mov [initial_commands],eax
mov [initial_commands_maximum_length],ecx
mov edi,eax
add edi,[initial_commands_length]
pop ecx
jmp copy_initial_command
include 'system.inc'
include '../assembler.inc'
include '../symbols.inc'
include '../expressions.inc'
include '../conditions.inc'
include '../floats.inc'
include '../directives.inc'
include '../calm.inc'
include '../errors.inc'
include '../map.inc'
include '../reader.inc'
include '../output.inc'
include '../console.inc'
section '.data'
_logo db 'flat assembler version g.',VERSION,10,0
_usage db 'Usage: fasmg source [output]',10
db 'Optional settings:',10
db ' -p limit Set the maximum allowed number of passes (default 100)',10
db ' -e limit Set the maximum number of displayed errors (default 1)',10
db ' -r limit Set the maximum depth of the stack (default 10000)',10
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
db ' -i command Insert instruction at the beginning of source',13,10
db ' -n Do not show logo nor summary',13,10
db 0
_pass db ' pass, ',0
_passes db ' passes, ',0
_dot db '.'
_seconds db ' seconds, ',0
_byte db ' byte.',0
_bytes db ' bytes.',0
_write_failed db 'failed to write the output file',0
_out_of_memory db 'not enough memory to complete the assembly',0
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
_open_mode db 'r',0
_create_mode db 'w',0
include '../tables.inc'
include '../messages.inc'
section '.bss' writeable align 4
include '../variables.inc'
source_path dd ?
output_path dd ?
maximum_number_of_passes dd ?
initial_commands dd ?
initial_commands_length dd ?
initial_commands_maximum_length dd ?
argc dd ?
argv dd ?
timestamp dq ?
start_time timeval
end_time timeval
tenths_of_second dd ?
verbosity_level dd ?
no_logo db ?
path_buffer rb 1000h

View File

@ -0,0 +1,60 @@
include '../../examples/x86/include/80386.inc'
macro format?.ELF? variant
match , variant
format binary as 'o'
include '../../examples/x86/include/format/elf32.inc'
use32
else match =executable? settings, variant:
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include '../../examples/x86/include/format/elfexe.inc'
use32
else
err 'invalid argument'
end match
end macro
macro struct? name
macro ends?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge ends?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
macro ccall? proc*,args&
local size
mov ebp,esp
if size
sub esp,size
end if
and esp,0FFFFFFF0h
match any, args
iterate arg, args
mov dword [esp+(%-1)*4],arg
if % = 1
size := %%*4
end if
end iterate
else
size := 0
end match
call proc
mov esp,ebp
end macro

View File

@ -0,0 +1,17 @@
macro struct name*
{
local body
define body struc name \{
irp d, db,rb,dw,rw,dd,rd,dq,rq \{ struc d value& \\{ define body \\\.\\#. d value \\} \}
macro ends
\{
define body \\}
irp d, db,rb,dw,rw,dd,rd,dq,rq \\{ restruc d \\}
irpv line, body \\{ line \\}
virtual at 0
name name
sizeof.#name = $
end virtual
\}
}

View File

@ -0,0 +1,225 @@
LINE_FEED = 0Ah
system_init:
ccall libc.time,timestamp
retn
system_shutdown:
retn
malloc:
malloc_fixed:
malloc_growable:
; in: ecx = requested size
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
; preserves: ebx, esi, edi
; note:
; use of malloc_fixed hints that block will be kept as is until the end of assembly
; use of malloc_growable hints that block is likely to be resized
push ebx ecx esi edi
ccall libc.malloc,ecx
pop edi esi ecx ebx
test eax,eax
jz out_of_memory
retn
realloc:
; in: eax - memory block, ecx = requested size
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
; preserves: ebx, esi, edi
push ebx ecx esi edi
ccall libc.realloc,eax,ecx
pop edi esi ecx ebx
test eax,eax
jz out_of_memory
retn
mfree:
; in: eax - memory block
; out: cf set on error
; preserves: ebx, esi, edi
; note: eax may have value 0 or -1, it should be treated as invalid input then
test eax,eax
jz interface_error
cmp eax,-1
je interface_error
push ebx esi edi
ccall libc.free,eax
pop edi esi ebx
clc
retn
interface_error:
stc
retn
open:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push esi edi
call adapt_path
ccall libc.fopen,ebx,_open_mode
pop edi esi
test eax,eax
jz interface_error
mov ebx,eax
clc
retn
adapt_path:
xor ecx,ecx
mov ebx,path_buffer
copy_path:
mov al,[edx+ecx]
cmp al,'\'
jne path_char_ok
mov al,'/'
path_char_ok:
cmp ecx,1000h
jae out_of_memory
mov [ebx+ecx],al
inc ecx
test al,al
jnz copy_path
retn
create:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push esi edi
call adapt_path
ccall libc.fopen,ebx,_create_mode
pop edi esi
test eax,eax
jz interface_error
mov ebx,eax
clc
retn
write:
; in: ebx = file handle, edx - data, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push ebx ecx esi edi
ccall libc.fwrite,edx,1,ecx,ebx
pop edi esi ecx ebx
cmp eax,ecx
jne interface_error
clc
ret
read:
; in: ebx = file handle, edx - buffer, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push ebx ecx esi edi
ccall libc.fread,edx,1,ecx,ebx
pop edi esi ecx ebx
cmp eax,ecx
jne interface_error
clc
ret
close:
; in: ebx = file handle
; preserves: ebx, esi, edi
ccall libc.fclose,ebx
ret
lseek:
; in: ebx = file handle, cl = method, edx:eax = offset
; out: edx:eax = new offset from the beginning of file, cf set on error
; preserves: ebx, esi, edi
test edx,edx
jnz interface_error
push esi edi ebx
movzx ecx,cl
ccall libc.fseek,ebx,eax,ecx
test eax,eax
jnz lseek_error
mov ebx,[esp]
ccall libc.ftell,ebx
cmp eax,-1
je lseek_error
xor edx,edx
pop ebx edi esi
clc
ret
lseek_error:
pop ebx edi esi
stc
ret
get_timestamp:
; out: edx:eax = timestamp
; preserves: ebx, ecx, esi, edi
; note: during the passes of a single assembly this function should always return the same value
mov eax,dword [timestamp]
mov edx,dword [timestamp+4]
retn
display_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx esi
test ecx,ecx
jnz write_string_to_stdout
xor al,al
mov edi,esi
or ecx,-1
repne scasb
neg ecx
sub ecx,2
write_string_to_stdout:
ccall libc.write,1,esi,ecx
pop esi ebx
retn
display_error_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx esi
test ecx,ecx
jnz write_string_to_stderr
xor al,al
mov edi,esi
or ecx,-1
repne scasb
neg ecx
sub ecx,2
write_string_to_stderr:
ccall libc.write,2,esi,ecx
pop esi ebx
retn
get_environment_variable:
; in:
; esi - name
; edi - buffer for value
; ecx = size of buffer
; out:
; eax = length of value
; preserves: ebx, esi, edi
push ebx ecx esi edi
ccall getenv,esi
pop edi esi ecx ebx
test eax,eax
jz no_environment_variable
push esi
mov esi,eax
xor eax,eax
copy_environment_variable:
mov dl,[esi+eax]
cmp eax,ecx
jae next_environment_variable_character
mov [edi+eax],dl
next_environment_variable_character:
inc eax
test dl,dl
jnz copy_environment_variable
pop esi
environment_variable_ok:
ret
no_environment_variable:
mov eax,1
jecxz environment_variable_ok
and byte [edi],0
ret