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,360 @@
; flat assembler interface for Linux x64
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
format ELF64 executable 3 at 400000h
entry start
include 'modes.inc'
segment readable executable
start:
mov [con_handle],1
mov esi,_logo
call display_string
mov [command_line],rsp
mov rcx,[rsp]
lea rbx,[rsp+8+rcx*8+8]
mov [environment],rbx
call get_params
jc information
call init_memory
mov esi,_memory_prefix
call display_string
mov eax,[memory_end]
sub eax,[memory_start]
add eax,[additional_memory_end]
sub eax,[additional_memory]
shr eax,10
call display_number
mov esi,_memory_suffix
call display_string
mov eax,96
mov edi,buffer
xor esi,esi
syscall
mov eax,dword [buffer]
mov ecx,1000
mul ecx
mov ebx,eax
mov eax,dword [buffer+4]
div ecx
add eax,ebx
mov [start_time],eax
and [preprocessing_done],0
call preprocessor
or [preprocessing_done],-1
call parser
call assembler
call formatter
call display_user_messages
movzx eax,[current_pass]
inc eax
call display_number
mov esi,_passes_suffix
call display_string
mov eax,96
mov edi,buffer
xor esi,esi
syscall
mov eax,dword [buffer]
mov ecx,1000
mul ecx
mov ebx,eax
mov eax,dword [buffer+4]
div ecx
add eax,ebx
sub eax,[start_time]
jnc time_ok
add eax,3600000
time_ok:
xor edx,edx
mov ebx,100
div ebx
or eax,eax
jz display_bytes_count
xor edx,edx
mov ebx,10
div ebx
push edx
call display_number
mov dl,'.'
call display_character
pop eax
call display_number
mov esi,_seconds_suffix
call display_string
display_bytes_count:
mov eax,[written_size]
call display_number
mov esi,_bytes_suffix
call display_string
xor al,al
jmp exit_program
information:
mov esi,_usage
call display_string
mov al,1
jmp exit_program
get_params:
mov rbx,[command_line]
mov [input_file],0
mov [output_file],0
mov [symbols_file],0
mov [memory_setting],0
mov [passes_limit],100
mov rcx,[rbx]
add rbx,8*2
dec rcx
jz bad_params
mov [definitions_pointer],predefinitions
mov [path_pointer],paths
get_param:
mov rsi,[rbx]
mov al,[rsi]
cmp al,'-'
je option_param
cmp [input_file],0
jne get_output_file
call collect_path
mov [input_file],edx
jmp next_param
get_output_file:
cmp [output_file],0
jne bad_params
call collect_path
mov [output_file],edx
jmp next_param
option_param:
inc rsi
lodsb
cmp al,'m'
je memory_option
cmp al,'M'
je memory_option
cmp al,'p'
je passes_option
cmp al,'P'
je passes_option
cmp al,'d'
je definition_option
cmp al,'D'
je definition_option
cmp al,'s'
je symbols_option
cmp al,'S'
je symbols_option
bad_params:
stc
ret
memory_option:
cmp byte [rsi],0
jne get_memory_setting
dec rcx
jz bad_params
add rbx,8
mov rsi,[rbx]
get_memory_setting:
call get_option_value
or edx,edx
jz bad_params
cmp edx,1 shl (32-10)
jae bad_params
mov [memory_setting],edx
jmp next_param
passes_option:
cmp byte [rsi],0
jne get_passes_setting
dec rcx
jz bad_params
add rbx,8
mov rsi,[rbx]
get_passes_setting:
call get_option_value
or edx,edx
jz bad_params
cmp edx,10000h
ja bad_params
mov [passes_limit],dx
next_param:
add rbx,8
dec rcx
jnz get_param
cmp [input_file],0
je bad_params
mov eax,[definitions_pointer]
mov byte [eax],0
mov [initial_definitions],predefinitions
clc
ret
definition_option:
cmp byte [rsi],0
jne get_definition
dec rcx
jz bad_params
add rbx,8
mov rsi,[rbx]
get_definition:
mov r12d,edi
mov edi,[definitions_pointer]
call convert_definition_option
mov [definitions_pointer],edi
mov edi,r12d
jc bad_params
jmp next_param
symbols_option:
cmp byte [rsi],0
jne get_symbols_setting
dec rcx
jz bad_params
add rbx,8
mov rsi,[rbx]
get_symbols_setting:
call collect_path
mov [symbols_file],edx
jmp next_param
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
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 rsi
clc
ret
invalid_option_value:
stc
ret
convert_definition_option:
mov edx,edi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
copy_definition_name:
lodsb
cmp al,'='
je copy_definition_value
cmp al,20h
je bad_definition_option
or al,al
jz bad_definition_option
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
inc byte [edx]
jnz copy_definition_name
bad_definition_option:
stc
ret
copy_definition_value:
lodsb
cmp al,20h
je definition_value_end
or al,al
jz definition_value_end
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
jmp copy_definition_value
definition_value_end:
dec rsi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
clc
ret
collect_path:
mov edi,[path_pointer]
mov edx,edi
copy_path_to_low_memory:
lodsb
stosb
test al,al
jnz copy_path_to_low_memory
mov [path_pointer],edi
retn
include 'system.inc'
include '..\..\version.inc'
_copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0xA,0
_logo db 'flat assembler version ',VERSION_STRING,0
_usage db 0xA
db 'usage: fasm <source> [output]',0xA
db 'optional settings:',0xA
db ' -m <limit> set the limit in kilobytes for the available memory',0xA
db ' -p <limit> set the maximum allowed number of passes',0xA
db ' -d <name>=<value> define symbolic variable',0xA
db ' -s <file> dump symbolic information for debugging',0xA
db 0
_memory_prefix db ' (',0
_memory_suffix db ' kilobytes memory, x64)',0xA,0
_passes_suffix db ' passes, ',0
_seconds_suffix db ' seconds, ',0
_bytes_suffix db ' bytes.',0xA,0
_no_low_memory db 'failed to allocate memory within 32-bit addressing range',0
include '..\..\errors.inc'
include '..\..\symbdump.inc'
include '..\..\preproce.inc'
include '..\..\parser.inc'
include '..\..\exprpars.inc'
include '..\..\assemble.inc'
include '..\..\exprcalc.inc'
include '..\..\x86_64.inc'
include '..\..\avx.inc'
include '..\..\formats.inc'
include '..\..\tables.inc'
include '..\..\messages.inc'
segment readable writeable
align 4
include '..\..\variable.inc'
command_line dq ?
memory_setting dd ?
path_pointer dd ?
definitions_pointer dd ?
environment dq ?
timestamp dq ?
start_time dd ?
con_handle dd ?
displayed_count dd ?
last_displayed db ?
character db ?
preprocessing_done db ?
buffer rb 1000h
predefinitions rb 1000h
paths rb 10000h

View File

@ -0,0 +1,186 @@
; flat assembler interface for Linux x64
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
esp equ +rsp
macro pushD [arg]
{
common
local offset,total
offset = 0
lea rsp,[rsp-total]
forward
offset = offset + 4
if arg eqtype eax
mov dword [rsp+total-offset],arg
else
mov r8d,dword arg
mov [rsp+total-offset],r8d
end if
common
total = offset
}
macro popD [arg]
{
common
local offset
offset = 0
forward
if arg eqtype [mem]
mov r8d,[rsp+offset]
mov dword arg,r8d
else
mov arg,dword [rsp+offset]
end if
offset = offset + 4
common
lea rsp,[rsp+offset]
}
macro add dest,src
{
if dest eq esp
add rsp,src
else
add dest,src
end if
}
macro mov dest,src
{
if src eq esp
mov dest,ESP
else
mov dest,src
end if
}
macro cmp dest,src
{
if dest eq esp
cmp ESP,src
else
cmp dest,src
end if
}
macro use32
{
macro push args
\{
local list,arg,status
define list
define arg
irps sym, args \\{
define status
match =dword, sym \\\{
define status :
\\\}
match [any, status arg sym \\\{
define arg [any
match [mem], arg \\\\{
match previous, list \\\\\{ define list previous,[mem] \\\\\}
match , list \\\\\{ define list [mem] \\\\\}
define arg
\\\\}
define status :
\\\}
match [, status arg sym \\\{
define arg [
define status :
\\\}
match , status \\\{
match previous, list \\\\{ define list previous,sym \\\\}
match , list \\\\{ define list sym \\\\}
\\\}
\\}
match arg, list \\{ pushD arg \\}
\}
macro pop args
\{
local list,arg,status
define list
define arg
irps sym, args \\{
define status
match =dword, sym \\\{
define status :
\\\}
match [any, status arg sym \\\{
define arg [any
match [mem], arg \\\\{
match previous, list \\\\\{ define list previous,[mem] \\\\\}
match , list \\\\\{ define list [mem] \\\\\}
define arg
\\\\}
define status :
\\\}
match [, status arg sym \\\{
define arg [
define status :
\\\}
match , status \\\{
match previous, list \\\\{ define list previous,sym \\\\}
match , list \\\\{ define list sym \\\\}
\\\}
\\}
match arg, list \\{ popD arg \\}
\}
macro jmp arg
\{
if arg eq near eax
jmp near rax
else if arg eq near edx
jmp near rdx
else if arg eqtype [mem]
mov r8d,arg
jmp near r8
else
jmp arg
end if
\}
macro call arg
\{
if 1
match =near =dword [mem], arg \\{
mov r8d,[mem]
call near r8
else
\\}
call arg
end if
\}
macro salc ; for fasm's core it does not need to preserve flags
\{
setc al
neg al
\}
macro jcxz target ; for fasm's core it does not need to preserve flags
\{
test cx,cx
jz target
\}
use64
}
macro use16
{
purge push,pop,jmp,call,salc,jcxz
use16
}
use32

View File

@ -0,0 +1,548 @@
; flat assembler interface for Linux x64
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
O_ACCMODE = 0003o
O_RDONLY = 0000o
O_WRONLY = 0001o
O_RDWR = 0002o
O_CREAT = 0100o
O_EXCL = 0200o
O_NOCTTY = 0400o
O_TRUNC = 1000o
O_APPEND = 2000o
O_NONBLOCK = 4000o
S_ISUID = 4000o
S_ISGID = 2000o
S_ISVTX = 1000o
S_IRUSR = 0400o
S_IWUSR = 0200o
S_IXUSR = 0100o
S_IRGRP = 0040o
S_IWGRP = 0020o
S_IXGRP = 0010o
S_IROTH = 0004o
S_IWOTH = 0002o
S_IXOTH = 0001o
init_memory:
mov eax,esp
and eax,not 0FFFh
add eax,1000h-10000h
mov [stack_limit],eax
xor edi,edi
mov eax,12
syscall
mov ecx,[memory_setting]
shl ecx,10
jnz allocate_memory
mov ecx,1000000h
allocate_memory:
mov r9d,eax
cmp rax,r9
jne high_brk
mov [additional_memory],eax
lea edi,[eax+ecx]
mov eax,12
syscall
mov r9d,eax
cmp rax,r9
jne no_low_memory
mov [memory_end],eax
sub eax,[additional_memory]
shr eax,2
add eax,[additional_memory]
mov [additional_memory_end],eax
mov [memory_start],eax
ret
high_brk:
xor r9d,r9d
or r8,-1
mov r10d,62h ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT
mov edx,3 ; PROT_READ + PROT_WRITE
mov esi,ecx
xor edi,edi
mov eax,9 ; sys_mmap
syscall
cmp eax,-1
je mmap_with_hint
mov r9d,eax
cmp rax,r9
jne mmap_unusable
add r9d,esi
jnc mmap_ok
mmap_unusable:
mov rdi,rax
mov eax,11 ; sys_munmap
syscall
mmap_with_hint:
mov r10d,22h ; MAP_PRIVATE + MAP_ANONYMOUS
mov edx,3 ; PROT_READ + PROT_WRITE
mov edi,480000h
mov eax,9 ; sys_mmap
syscall
cmp eax,-1
je no_low_memory
mov r9d,eax
cmp rax,r9
jne no_low_memory
add r9d,esi
jnc mmap_ok
no_low_memory:
mov esi,lf
call display_string
push _no_low_memory
jmp fatal_error
mmap_ok:
mov [additional_memory],eax
lea edi,[eax+esi]
mov [memory_end],edi
shr esi,2
add eax,esi
mov [additional_memory_end],eax
mov [memory_start],eax
ret
exit_program:
movzx edi,al
mov eax,60
syscall
get_environment_variable:
mov ecx,esi
mov rbx,[environment]
next_variable:
mov rsi,[rbx]
test rsi,rsi
jz no_environment_variable
add rbx,8
compare_variable_names:
mov edx,ecx
compare_character:
lodsb
mov ah,[edx]
inc edx
cmp al,'='
je end_of_variable_name
or ah,ah
jz 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
jmp next_variable
no_environment_variable:
ret
end_of_variable_name:
or ah,ah
jnz next_variable
copy_variable_value:
lodsb
cmp edi,[memory_end]
jae out_of_memory
stosb
or al,al
jnz copy_variable_value
dec edi
ret
open:
mov r12d,esi
mov r13d,edi
call adapt_path
mov eax,2
mov edi,buffer
mov esi,O_RDONLY
xor edx,edx
syscall
mov esi,r12d
mov edi,r13d
test eax,eax
js 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 out_of_memory
ret
create:
mov r12d,esi
mov r13d,edi
mov r15d,edx
call adapt_path
mov edi,buffer
mov esi,O_CREAT+O_TRUNC+O_WRONLY
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
cmp r15d,[output_file]
jne do_create
cmp [output_format],5
jne do_create
bt [format_flags],0
jnc do_create
or edx,S_IXUSR+S_IXGRP+S_IXOTH
do_create:
mov eax,2
syscall
mov esi,r12d
mov edi,r13d
test eax,eax
js file_error
mov ebx,eax
clc
ret
close:
mov r13d,edi
mov edi,ebx
mov eax,3
syscall
mov edi,r13d
ret
read:
mov r12d,esi
mov r13d,edi
mov eax,0
mov edi,ebx
mov esi,edx
mov edx,ecx
syscall
mov ecx,edx
mov edx,esi
mov esi,r12d
mov edi,r13d
test eax,eax
js file_error
cmp eax,ecx
jne file_error
clc
ret
file_error:
stc
ret
write:
mov r12d,esi
mov r13d,edi
mov eax,1
mov edi,ebx
mov esi,edx
mov edx,ecx
syscall
mov ecx,edx
mov edx,esi
mov esi,r12d
mov edi,r13d
test eax,eax
js file_error
clc
ret
lseek:
mov r12d,esi
mov r13d,edi
mov edi,ebx
mov esi,edx
xor edx,edx
mov dl,al
mov eax,8
syscall
mov esi,r12d
mov edi,r13d
cmp eax,-1
je file_error
clc
ret
display_string:
mov edi,esi
mov edx,esi
or ecx,-1
xor al,al
repne scasb
neg ecx
sub ecx,2
mov eax,1
mov edi,[con_handle]
mov esi,edx
mov edx,ecx
syscall
ret
display_character:
mov r12d,esi
mov r13d,edi
mov [character],dl
mov eax,1
mov edi,[con_handle]
mov esi,character
mov edx,1
syscall
mov esi,r12d
mov edi,r13d
ret
display_number:
mov r14d,ebx
mov ecx,1000000000
xor edx,edx
xor bl,bl
display_loop:
div ecx
mov r15d,edx
cmp ecx,1
je display_digit
or bl,bl
jnz display_digit
or al,al
jz digit_ok
not bl
display_digit:
mov dl,al
add dl,30h
mov r10d,ecx
call display_character
mov ecx,r10d
digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
mov eax,r15d
or ecx,ecx
jnz display_loop
mov ebx,r14d
ret
display_user_messages:
mov [displayed_count],0
call show_display_buffer
cmp [displayed_count],0
je line_break_ok
cmp [last_displayed],0Ah
je line_break_ok
mov dl,0Ah
call display_character
line_break_ok:
ret
display_block:
jecxz block_displayed
add [displayed_count],ecx
mov al,[esi+ecx-1]
mov [last_displayed],al
mov r13d,edi
mov eax,1
mov edi,[con_handle]
mov edx,ecx
syscall
mov edi,r13d
block_displayed:
ret
fatal_error:
mov [con_handle],2
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,0FFh
jmp exit_program
assembler_error:
mov [con_handle],2
call display_user_messages
mov ebx,[current_line]
test ebx,ebx
jz display_error_message
push dword 0
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
push ebx
test byte [ebx+7],80h
jz display_error_line
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
display_error_line:
mov esi,[ebx]
call display_string
mov esi,line_number_start
call display_string
mov eax,[ebx+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
pop esi
cmp ebx,esi
je line_number_ok
mov dl,20h
call display_character
push esi
mov esi,[esi]
movzx ecx,byte [esi]
inc esi
call display_block
mov esi,line_number_start
call display_string
pop esi
mov eax,[esi+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
line_number_ok:
mov esi,line_data_start
call display_string
mov esi,ebx
mov edx,[esi]
call open
mov al,2
xor edx,edx
call lseek
mov edx,[esi+8]
sub eax,edx
jz line_data_displayed
push eax
xor al,al
call lseek
mov ecx,[esp]
mov edx,[additional_memory]
lea eax,[edx+ecx]
cmp eax,[additional_memory_end]
ja out_of_memory
call read
call close
pop ecx
mov esi,[additional_memory]
get_line_data:
mov al,[esi]
cmp al,0Ah
je display_line_data
cmp al,0Dh
je display_line_data
cmp al,1Ah
je display_line_data
or al,al
jz display_line_data
inc esi
loop get_line_data
display_line_data:
mov ecx,esi
mov esi,[additional_memory]
sub ecx,esi
call display_block
line_data_displayed:
mov esi,lf
call display_string
pop ebx
or ebx,ebx
jnz display_error_line
cmp [preprocessing_done],0
je display_error_message
mov esi,preprocessed_instruction_prefix
call display_string
mov esi,[current_line]
add esi,16
mov edi,[additional_memory]
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je instruction_converted
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
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_instruction
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_instruction
instruction_converted:
xor al,al
stosb
mov esi,[additional_memory]
call display_string
mov esi,lf
call display_string
display_error_message:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,2
jmp exit_program
make_timestamp:
mov r13d,edi
mov eax,201
mov edi,timestamp
syscall
mov eax,dword [timestamp]
mov edx,dword [timestamp+4]
mov edi,r13d
ret
error_prefix db 'error: ',0
error_suffix db '.'
lf db 0xA,0
line_number_start db ' [',0
line_data_start db ':',0xA,0
preprocessed_instruction_prefix db 'processed: ',0