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,503 @@
include 'macro/struct.inc'
format ELF executable 3
entry start
include '../version.inc'
struct timeval
time_t dd ?
suseconds_t dd ?
ends
segment readable executable
start:
mov ecx,[esp]
mov [argc],ecx
lea ebx,[esp+4]
mov [argv],ebx
lea esi,[esp+4+ecx*4+4]
mov [env],esi
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
mov eax,78 ; sys_gettimeofday
mov ebx,start_time
xor ecx,ecx
int 0x80
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
mov eax,78 ; sys_gettimeofday
mov ebx,end_time
xor ecx,ecx
int 0x80
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
xor ebx,ebx
mov eax,1 ; sys_exit
int 0x80
assembly_failed:
call show_errors
call assembly_shutdown
call system_shutdown
mov ebx,2
mov eax,1 ; sys_exit
int 0x80
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
mov ebx,3
mov eax,1 ; sys_exit
int 0x80
display_usage_information:
mov esi,_usage
xor ecx,ecx
call display_string
call system_shutdown
mov ebx,1
mov eax,1 ; sys_exit
int 0x80
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 '../malloc.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'
segment readable
_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'
segment readable writeable
align 16
include '../variables.inc'
align 16
timestamp dq ?
loff dq ?
argc dd ?
argv dd ?
env dd ?
mmap_args rd 6
malloc_freelist dd ?
source_path dd ?
output_path dd ?
maximum_number_of_passes dd ?
initial_commands dd ?
initial_commands_length dd ?
initial_commands_maximum_length dd ?
start_time timeval
end_time timeval
tenths_of_second dd ?
verbosity_level dd ?
no_logo db ?
path_buffer rb 1000h
segment readable writeable gnustack

View File

@ -0,0 +1,298 @@
LINE_FEED = 0Ah
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
system_init:
mov eax,13 ; sys_time
mov ebx,timestamp
int 0x80
retn
system_shutdown:
retn
open:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push esi edi ebp
call adapt_path
mov eax,5 ; sys_open
mov ecx,O_RDONLY
xor edx,edx
int 0x80
pop ebp edi esi
test eax,eax
js 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
interface_error:
stc
retn
create:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push esi edi ebp
call adapt_path
mov eax,5 ; sys_open
mov ecx,O_CREAT+O_TRUNC+O_WRONLY
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
int 0x80
pop ebp edi esi
test eax,eax
js 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 ebp
mov eax,4 ; sys_write
xchg ecx,edx
int 0x80
pop ebp edi esi ecx ebx
test eax,eax
js interface_error
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 ebp
mov eax,3 ; sys_read
xchg ecx,edx
int 0x80
pop ebp edi esi ecx ebx
test eax,eax
js interface_error
cmp eax,ecx
jne interface_error
clc
ret
close:
; in: ebx = file handle
; preserves: ebx, esi, edi
push ebx esi edi ebp
mov eax,6 ; sys_close
int 0x80
pop ebp edi esi 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 ebp
movzx edi,cl
mov ecx,edx
mov edx,eax
mov eax,140 ; sys_llseek
mov esi,loff
int 0x80
pop ebp ebx edi esi
test eax,eax
js interface_error
mov eax,dword [loff]
mov edx,dword [loff+4]
clc
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 ebp
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:
mov eax,4 ; sys_write
mov ebx,1
mov edx,ecx
mov ecx,esi
int 0x80
pop ebp esi ebx
retn
display_error_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx esi ebp
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:
mov eax,4 ; sys_write
mov ebx,2
mov edx,ecx
mov ecx,esi
int 0x80
pop ebp 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
mov edx,[env]
scan_environment:
mov ebx,[edx]
test ebx,ebx
jz no_environment_variable
xor ecx,ecx
compare_character:
mov al,[ebx+ecx]
mov ah,[esi+ecx]
inc ecx
cmp al,'='
je end_of_variable_name
test ah,ah
jz next_variable
sub ah,al
je compare_character
cmp ah,20h
jne next_variable
cmp al,'A'
jb next_variable
cmp al,'Z'
jna compare_character
next_variable:
add edx,4
jmp scan_environment
end_of_variable_name:
test ah,ah
jnz next_variable
add ebx,ecx
pop ecx
xor eax,eax
copy_environment_variable:
mov dl,[ebx+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
environment_variable_ok:
pop ebx
ret
no_environment_variable:
pop ecx
mov eax,1
jecxz environment_variable_ok
and byte [edi],0
pop ebx
ret
VALLOC_MINIMUM_SIZE = 100000h
valloc:
; in: ecx = requested minimum size
; out: eax - allocated block, ecx = allocated size, zero if failed
; preserves: ebx, esi, edi
cmp ecx,VALLOC_MINIMUM_SIZE
jbe valloc_size_minimum
dec ecx
and ecx,(-1) shl 12
add ecx,1 shl 12
jmp valloc_size_ready
valloc_size_minimum:
mov ecx,VALLOC_MINIMUM_SIZE
valloc_size_ready:
push ebx edi
mov ebx,mmap_args
mov edi,ebx
xor eax,eax
stosd
mov eax,ecx
stosd
mov eax,3 ; PROT_READ + PROT_WRITE
stosd
mov eax,22h ; MAP_PRIVATE + MAP_ANONYMOUS
stosd
or eax,-1
stosd
xor eax,eax
stosd
mov eax,0x5A ; old_mmap
int 0x80
cmp eax,-1
jne valloc_ok
xor ecx,ecx
valloc_ok:
pop edi ebx
retn

View File

@ -0,0 +1,79 @@
macro use32on64?
define esp rsp
define promote
iterate <reg32,reg64>, eax,rax, ebx,rbx, ecx,rcx, edx,rdx, esi,rsi, edi,rdi, esp,rsp, ebp,rbp
promote.reg32? equ reg64
end iterate
iterate instr, jmp,call
calminstruction instr? arg
local tmp
match [tmp], arg
jyes zero_extend
transform arg, promote
arrange tmp, =instr arg
assemble tmp
exit
zero_extend:
arrange tmp, =mov =r8d,[tmp]
assemble tmp
arrange tmp, =instr =r8
assemble tmp
end calminstruction
end iterate
calminstruction push? arg
local car, cdr
match car cdr?, arg
loop:
transform car, promote
jno non_reg
arrange car, =push car
assemble car
match car cdr?, cdr
jyes loop
exit
non_reg:
arrange tmp, =mov =r8d,arg
assemble tmp
arrange tmp, =push =r8
assemble tmp
exit
end calminstruction
calminstruction pop? arg
local car, cdr
match car cdr?, arg
loop:
transform car, promote
jno non_reg
arrange car, =pop car
assemble car
match car cdr?, cdr
jyes loop
exit
non_reg:
arrange tmp, =pop =r8
assemble tmp
arrange tmp, =mov arg,=r8d
assemble tmp
exit
end calminstruction
macro jecxz? target
if target-($+1) < 80h & target-($+1) >= -80h
jecxz target
else
local j,k
jecxz j
jmp k
j: jmp target
k:
end if
end macro
end macro

View File

@ -0,0 +1,124 @@
macro use32on64
{
define esp rsp
define promote.eax rax
define promote.ebx rbx
define promote.ecx rcx
define promote.edx rdx
define promote.esi rsi
define promote.edi rdi
define promote.ebp rbp
define promote.esp rsp
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 ops,list \\{
irp op, ops \\\{
if op eqtype eax
push promote.\\\#op
else
mov r8d,op
push r8
end if
\\\}
\\}
\}
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 ops,list \\{
irp op, ops \\\{
if op eqtype eax
pop promote.\\\#op
else
pop r8
mov op,r8d
end if
\\\}
\\}
\}
irp instr, jmp,call
\{
macro instr op
\\{
if op eqtype [0]
mov r8d,op
instr r8
else if op eqtype 0
instr op
else
instr promote.\\#op
end if
\\}
\}
macro jecxz target
\{
if target-($+1) < 80h & target-($+1) >= -80h
jecxz target
else
local j,k
jecxz j
jmp k
j: jmp target
k:
end if
\}
}

View File

@ -0,0 +1,546 @@
match ,{
include '32on64.inc'
} match -,{
else
include '32on64.alm'
end match
_ equ }
include 'macro/struct.inc'
format ELF64 executable 3
entry start
include '../../version.inc'
struct timeval
time_t dq ?
suseconds_t dq ?
ends
segment readable executable
start:
mov rcx,[rsp]
mov [argc],rcx
lea rbx,[rsp+8]
mov [argv],rbx
lea rsi,[rsp+8+rcx*8+8]
mov [env],rsi
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
mov eax,96 ; sys_gettimeofday
mov edi,start_time
xor esi,esi
syscall
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
mov eax,96 ; sys_gettimeofday
mov edi,end_time
xor esi,esi
syscall
mov rax,[end_time.time_t]
sub rax,[start_time.time_t]
mov rcx,1000000
mul rcx
add rax,[end_time.suseconds_t]
adc rdx,0
sub rax,[start_time.suseconds_t]
sbb rdx,0
add rax,50000
mov rcx,1000000
div rcx
mov rbx,rax
mov rax,rdx
xor rdx,rdx
mov rcx,100000
div rcx
mov [tenths_of_second],eax
xchg rax,rbx
or rbx,rax
jz display_output_length
mov rdx,rax
shr rdx,32
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 rax rdx
call itoa
call display_string
pop rdx rax
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
xor edi,edi ; exit code 0
mov eax,60 ; sys_exit
syscall
assembly_failed:
call show_errors
call assembly_shutdown
call system_shutdown
mov edi,2
mov eax,60 ; sys_exit
syscall
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
mov edi,3
mov eax,60 ; sys_exit
syscall
internal_error:
int3
display_usage_information:
mov esi,_usage
xor ecx,ecx
call display_string
call system_shutdown
mov edi,1
mov eax,60 ; sys_exit
syscall
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 rcx,[argc]
mov rbx,[argv]
add rbx,8
dec ecx
jz error_in_arguments
get_argument:
mov rsi,[rbx]
mov al,[rsi]
cmp al,'-'
je get_option
cmp [source_path],0
jne get_output_file
call strdup
mov [source_path],eax
jmp next_argument
get_output_file:
cmp [output_path],0
jne error_in_arguments
call strdup
mov [output_path],eax
jmp next_argument
get_option:
inc rsi
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 [rsi],0
je next_argument
error_in_arguments:
or al,-1
ret
set_verbose_mode:
cmp byte [rsi],0
jne get_verbose_setting
dec ecx
jz error_in_arguments
add rbx,8
mov rsi,[rbx]
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 [rsi],0
jne get_errors_setting
dec ecx
jz error_in_arguments
add rbx,8
mov rsi,[rbx]
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 [rsi],0
jne get_recursion_setting
dec ecx
jz error_in_arguments
add rbx,8
mov rsi,[rbx]
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 [rsi],0
jne get_passes_setting
dec ecx
jz error_in_arguments
add rbx,8
mov rsi,[rbx]
get_passes_setting:
call get_option_value
test edx,edx
jz error_in_arguments
mov [maximum_number_of_passes],edx
next_argument:
add rbx,8
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 [rsi],20h
jne get_option_digit
inc rsi
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 rsi
clc
ret
invalid_option_value:
stc
ret
insert_initial_command:
cmp byte [rsi],0
jne measure_initial_command
dec ecx
jz error_in_arguments
add rbx,8
mov rsi,[rbx]
measure_initial_command:
push rbx rcx rdi
mov rdi,rsi
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 rdi rcx rbx
jmp next_argument
allocate_initial_commands_buffer:
push rsi rcx
mov ecx,eax
call malloc
mov [initial_commands],eax
mov [initial_commands_maximum_length],ecx
mov edi,eax
pop rcx rsi
jmp copy_initial_command
grow_initial_commands_buffer:
push rsi rcx
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 rcx rsi
jmp copy_initial_command
strdup:
; in: rsi - ASCIIZ string
; out: eax - copy of the string in 32-bit addressable memory
; preserves: rbx, rcx, rsi
push rbx rcx rsi
mov rdi,rsi
or ecx,-1
xor al,al
repne scasb
not ecx
push rsi rcx
call malloc
pop rcx rsi
mov edi,eax
rep movsb
pop rsi rcx rbx
ret
include 'system.inc'
use32on64
include '../../malloc.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'
segment readable
_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
include '../../tables.inc'
include '../../messages.inc'
segment readable writeable
align 16
include '../../variables.inc'
align 16
timestamp dq ?
argc dq ?
argv dq ?
env dq ?
mmap_hint dd ?
malloc_freelist dd ?
source_path dd ?
output_path dd ?
maximum_number_of_passes dd ?
initial_commands dd ?
initial_commands_length dd ?
initial_commands_maximum_length dd ?
start_time timeval
end_time timeval
tenths_of_second dd ?
verbosity_level dd ?
no_logo db ?
local_heap_available db ?
path_buffer rb 1000h
segment readable writeable
align 1000h
LOCAL_HEAP_SIZE = 1000000h
local_heap rb LOCAL_HEAP_SIZE
segment readable writeable gnustack

View File

@ -0,0 +1,334 @@
LINE_FEED = 0Ah
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
system_init:
mov eax,201 ; sys_time
mov edi,timestamp
syscall
or [local_heap_available],1
retn
system_shutdown:
call mcheck
retn
open:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push rsi rdi
call adapt_path
mov eax,2 ; sys_open
mov esi,O_RDONLY
xor edx,edx
syscall
pop rdi rsi
test eax,eax
js interface_error
mov ebx,eax
clc
ret
interface_error:
stc
ret
adapt_path:
xor ecx,ecx
mov edi,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 [edi+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 rsi rdi
call adapt_path
mov esi,O_CREAT+O_TRUNC+O_WRONLY
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
mov eax,2 ; sys_open
syscall
pop rdi rsi
test eax,eax
js 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 rsi rdi
mov eax,1 ; sys_write
mov edi,ebx
mov esi,edx
mov edx,ecx
syscall
pop rdi rsi
test eax,eax
js interface_error
cmp eax,edx
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 rsi rdi
mov eax,0 ; sys_read
mov edi,ebx
mov esi,edx
mov edx,ecx
syscall
pop rdi rsi
test eax,eax
js interface_error
cmp eax,edx
jne interface_error
clc
ret
close:
; in: ebx = file handle
; preserves: ebx, esi, edi
push rdi
mov edi,ebx
mov eax,3 ; sys_close
syscall
pop rdi
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
push rsi rdi
mov edi,ebx
mov esi,edx
mov eax,eax
shl rsi,32
or rsi,rax
xor edx,edx
mov dl,cl
mov eax,8 ; sys_lseek
syscall
pop rdi rsi
cmp rax,-1
je interface_error
mov rdx,rax
shr rdx,32
clc
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 rbx rsi rbp
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:
mov eax,1 ; sys_write
mov edi,1
mov edx,ecx
syscall
pop rbp rsi rbx
retn
display_error_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push rbx rsi rbp
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:
mov eax,1 ; sys_write
mov edi,2
mov edx,ecx
syscall
pop rbp rsi rbx
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 rbx rcx
mov rdx,[env]
scan_environment:
mov rbx,[rdx]
test rbx,rbx
jz no_environment_variable
xor ecx,ecx
compare_character:
mov al,[rbx+rcx]
mov ah,[esi+ecx]
inc ecx
cmp al,'='
je end_of_variable_name
test ah,ah
jz next_variable
sub ah,al
je compare_character
cmp ah,20h
jne next_variable
cmp al,'A'
jb next_variable
cmp al,'Z'
jna compare_character
next_variable:
add rdx,8
jmp scan_environment
end_of_variable_name:
test ah,ah
jnz next_variable
add rbx,rcx
pop rcx
xor eax,eax
copy_environment_variable:
mov dl,[rbx+rax]
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
environment_variable_ok:
pop rbx
ret
no_environment_variable:
pop rcx
mov eax,1
jecxz environment_variable_ok
and byte [edi],0
pop rbx
ret
VALLOC_MINIMUM_SIZE = 100000h
valloc:
; in: ecx = requested minimum size
; out: eax - allocated block, ecx = allocated size, zero if failed
; preserves: ebx, esi, edi
cmp ecx,VALLOC_MINIMUM_SIZE
jbe valloc_size_minimum
dec ecx
and ecx,(-1) shl 12
add ecx,1 shl 12
jmp valloc_size_ready
valloc_size_minimum:
mov ecx,VALLOC_MINIMUM_SIZE
valloc_size_ready:
push rbx rsi rdi
cmp [local_heap_available],0
je valloc_mmap
cmp ecx,LOCAL_HEAP_SIZE
ja valloc_mmap
and [local_heap_available],0
mov eax,local_heap
mov ecx,LOCAL_HEAP_SIZE
jmp valloc_ok
valloc_mmap:
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 valloc_mmap_with_hint
mov ecx,eax
cmp rcx,rax
jne valloc_mmap_unusable
add ecx,esi
jnc mmap_ok
valloc_mmap_unusable:
mov rdi,rax
mov eax,11 ; sys_munmap
syscall
valloc_mmap_with_hint:
mov r10d,22h ; MAP_PRIVATE + MAP_ANONYMOUS
mov edx,3 ; PROT_READ + PROT_WRITE
mov edi,[mmap_hint]
mov eax,9 ; sys_mmap
syscall
cmp eax,-1
je valloc_failed
mov ecx,eax
cmp rcx,rax
jne valloc_failed
add ecx,esi
jc valloc_failed
mmap_ok:
sub ecx,eax
valloc_ok:
lea edx,[eax+ecx]
mov [mmap_hint],edx
pop rdi rsi rbx
retn
valloc_failed:
xor ecx,ecx
pop rdi rsi rbx
retn