added fasm2 as well
This commit is contained in:
495
toolchain/fasm2/source/macos/fasmg.asm
Normal file
495
toolchain/fasm2/source/macos/fasmg.asm
Normal file
@ -0,0 +1,495 @@
|
||||
|
||||
include 'macro/struct.inc'
|
||||
include 'macro/proc32.inc'
|
||||
|
||||
format MachO executable
|
||||
entry start
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
interpreter '/usr/lib/dyld'
|
||||
uses '/usr/lib/libSystem.B.dylib'
|
||||
|
||||
import libc.malloc,'_malloc',\
|
||||
libc.realloc,'_realloc',\
|
||||
libc.free,'_free',\
|
||||
libc.fopen,'_fopen',\
|
||||
libc.fclose,'_fclose',\
|
||||
libc.fread,'_fread',\
|
||||
libc.fwrite,'_fwrite',\
|
||||
libc.fseek,'_fseek',\
|
||||
libc.ftell,'_ftell',\
|
||||
libc.time,'_time',\
|
||||
libc.write,'_write',\
|
||||
getenv,'_getenv',\
|
||||
gettimeofday,'_gettimeofday',\
|
||||
exit,'_exit'
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
segment '__TEXT' readable executable
|
||||
|
||||
section '__text' align 16
|
||||
|
||||
start:
|
||||
mov ecx,[esp]
|
||||
mov [argc],ecx
|
||||
lea ebx,[esp+4]
|
||||
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 '__cstring' align 4
|
||||
|
||||
_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 '__DATA' readable writable
|
||||
|
||||
section '__bss' 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
|
489
toolchain/fasm2/source/macos/fasmg.o.asm
Normal file
489
toolchain/fasm2/source/macos/fasmg.o.asm
Normal file
@ -0,0 +1,489 @@
|
||||
|
||||
include 'macro/struct.inc'
|
||||
include 'macro/proc32.inc'
|
||||
|
||||
format MachO
|
||||
public main as '_main'
|
||||
|
||||
include '../version.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' as getenv
|
||||
extrn '_gettimeofday' as gettimeofday
|
||||
extrn '_exit' as exit
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
section '__TEXT':'__text' 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 '__TEXT':'__cstring' align 4
|
||||
|
||||
_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 '__DATA':'__data' 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
|
1174
toolchain/fasm2/source/macos/macho.inc
Normal file
1174
toolchain/fasm2/source/macos/macho.inc
Normal file
File diff suppressed because it is too large
Load Diff
225
toolchain/fasm2/source/macos/system.inc
Normal file
225
toolchain/fasm2/source/macos/system.inc
Normal 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
|
23
toolchain/fasm2/source/macos/x64/ccall.inc
Normal file
23
toolchain/fasm2/source/macos/x64/ccall.inc
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
iterate reg, rdi, rsi, rdx, rcx, r8, r9
|
||||
arguments.%? equ reg
|
||||
end iterate
|
||||
|
||||
macro ccall? proc*,args&
|
||||
local size
|
||||
mov rbp,rsp
|
||||
and rsp,0FFFFFFFFFFFFFFF0h
|
||||
match any, args
|
||||
iterate arg, args
|
||||
if sizeof (arg)
|
||||
lea arguments.%,[arg]
|
||||
else if ~ arg eq arguments.%
|
||||
mov arguments.%,arg
|
||||
end if
|
||||
end iterate
|
||||
end match
|
||||
call proc
|
||||
mov rsp,rbp
|
||||
end macro
|
540
toolchain/fasm2/source/macos/x64/fasmg.asm
Normal file
540
toolchain/fasm2/source/macos/x64/fasmg.asm
Normal file
@ -0,0 +1,540 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
include 'macro/struct.inc'
|
||||
|
||||
include 'ccall.inc'
|
||||
|
||||
format MachO64 executable at 1000h
|
||||
entry start
|
||||
|
||||
include '../../linux/x64/32on64.alm'
|
||||
|
||||
include '../../version.inc'
|
||||
|
||||
interpreter '/usr/lib/dyld'
|
||||
uses '/usr/lib/libSystem.B.dylib'
|
||||
|
||||
import libc.fopen,'_fopen',\
|
||||
libc.fclose,'_fclose',\
|
||||
libc.fread,'_fread',\
|
||||
libc.fwrite,'_fwrite',\
|
||||
libc.fseek,'_fseek',\
|
||||
libc.ftell,'_ftell',\
|
||||
libc.time,'_time',\
|
||||
libc.write,'_write',\
|
||||
mmap,'_mmap',\
|
||||
munmap,'_munmap',\
|
||||
getenv,'_getenv',\
|
||||
gettimeofday,'_gettimeofday',\
|
||||
exit,'_exit'
|
||||
|
||||
struct timeval
|
||||
time_t dq ?
|
||||
suseconds_t dd ?,?
|
||||
ends
|
||||
|
||||
segment '__TEXT' readable executable
|
||||
|
||||
section '__text' align 16
|
||||
|
||||
start:
|
||||
mov rcx,[rsp]
|
||||
mov [argc],rcx
|
||||
lea rbx,[rsp+8]
|
||||
mov [argv],rbx
|
||||
|
||||
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 rax,[end_time.time_t]
|
||||
sub rax,[start_time.time_t]
|
||||
mov rcx,1000000
|
||||
mul rcx
|
||||
mov ecx,[end_time.suseconds_t]
|
||||
add ecx,50000
|
||||
add rax,rcx
|
||||
adc rdx,0
|
||||
mov ecx,[start_time.suseconds_t]
|
||||
sub rax,rcx
|
||||
sbb rdx,0
|
||||
mov rcx,1000000
|
||||
div rcx
|
||||
mov rbx,rax
|
||||
mov rax,rdx
|
||||
xor edx,edx
|
||||
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
|
||||
|
||||
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 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'
|
||||
|
||||
section '__cstring' align 4
|
||||
|
||||
_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 '__DATA' readable writable
|
||||
|
||||
section '__bss' align 4
|
||||
|
||||
include '../../variables.inc'
|
||||
|
||||
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 ?
|
||||
|
||||
files dd ?
|
||||
files_count dd ?
|
||||
files_maximum_count dd ?
|
||||
|
||||
argc dq ?
|
||||
argv dq ?
|
||||
timestamp dq ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
local_heap_available db ?
|
||||
|
||||
path_buffer rb 1000h
|
||||
|
||||
align 1000h
|
||||
|
||||
LOCAL_HEAP_SIZE = 1000000h
|
||||
|
||||
local_heap rb LOCAL_HEAP_SIZE
|
287
toolchain/fasm2/source/macos/x64/system.inc
Normal file
287
toolchain/fasm2/source/macos/x64/system.inc
Normal file
@ -0,0 +1,287 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
system_init:
|
||||
ccall libc.time,timestamp
|
||||
or [local_heap_available],1
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push rsi rdi
|
||||
call adapt_path
|
||||
ccall libc.fopen,rbx,_open_mode
|
||||
put_file_entry:
|
||||
pop rdi rsi
|
||||
test rax,rax
|
||||
jz interface_error
|
||||
push rax
|
||||
mov eax,[files]
|
||||
mov ecx,[files_count]
|
||||
mov ebx,ecx
|
||||
inc ecx
|
||||
mov [files_count],ecx
|
||||
cmp ecx,[files_maximum_count]
|
||||
ja grow_files_buffer
|
||||
store_file_entry:
|
||||
pop rdx
|
||||
mov [eax+ebx*8],rdx
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
grow_files_buffer:
|
||||
shl ecx,4
|
||||
test eax,eax
|
||||
jz allocate_files_buffer
|
||||
call realloc
|
||||
jmp allocated_files_buffer
|
||||
allocate_files_buffer:
|
||||
call malloc
|
||||
allocated_files_buffer:
|
||||
mov [files],eax
|
||||
shr ecx,3
|
||||
mov [files_maximum_count],ecx
|
||||
jmp store_file_entry
|
||||
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 rsi rdi
|
||||
call adapt_path
|
||||
ccall libc.fopen,rbx,_create_mode
|
||||
jmp put_file_entry
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rbx rcx rsi rdi
|
||||
mov eax,[files]
|
||||
mov rax,[eax+ebx*8]
|
||||
ccall libc.fwrite,rdx,1,rcx,rax
|
||||
pop rdi rsi rcx rbx
|
||||
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 rbx rcx rsi rdi
|
||||
mov eax,[files]
|
||||
mov rax,[eax+ebx*8]
|
||||
ccall libc.fread,rdx,1,rcx,rax
|
||||
pop rdi rsi rcx rbx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi
|
||||
mov edi,[files]
|
||||
mov rdi,[edi+ebx*8]
|
||||
ccall libc.fclose,rdi
|
||||
pop rdi rsi
|
||||
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 rbx
|
||||
shl rdx,32
|
||||
or rax,rdx
|
||||
movzx ecx,cl
|
||||
mov edi,[files]
|
||||
mov rdi,[edi+ebx*8]
|
||||
push rdi
|
||||
ccall libc.fseek,rdi,rax,rcx
|
||||
test eax,eax
|
||||
jnz lseek_error
|
||||
pop rdi
|
||||
ccall libc.ftell,rdi
|
||||
cmp rax,-1
|
||||
je lseek_error
|
||||
mov rdx,rax
|
||||
shr rdx,32
|
||||
mov eax,eax
|
||||
pop rbx rdi rsi
|
||||
clc
|
||||
ret
|
||||
lseek_error:
|
||||
pop rbx rdi rsi
|
||||
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 rbx rsi
|
||||
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,rsi,rcx
|
||||
pop rsi rbx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push rbx rsi
|
||||
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,rsi,rcx
|
||||
pop 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 rsi rdi
|
||||
ccall getenv,rsi
|
||||
pop rdi rsi rcx rbx
|
||||
test rax,rax
|
||||
jz no_environment_variable
|
||||
push rsi
|
||||
mov rsi,rax
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[rsi+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
|
||||
pop rsi
|
||||
environment_variable_ok:
|
||||
ret
|
||||
no_environment_variable:
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
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:
|
||||
push rcx
|
||||
ccall mmap,0,rcx, \
|
||||
3, \ ; PROT_READ + PROT_WRITE
|
||||
9002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT
|
||||
-1,0
|
||||
pop rsi
|
||||
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:
|
||||
ccall munmap,rax,rsi
|
||||
valloc_mmap_with_hint:
|
||||
push rsi
|
||||
mov edi,[mmap_hint]
|
||||
ccall mmap,rdi,rsi, \
|
||||
3, \ ; PROT_READ + PROT_WRITE
|
||||
1002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS
|
||||
-1,0
|
||||
pop rsi
|
||||
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
|
Reference in New Issue
Block a user