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,643 @@
include 'macro/struct.inc'
include '../version.inc'
BUFFER_SIZE = 4000h
STACK_SIZE = 4000h
format MZ
heap 0
stack stack_segment:stack_top-stack_bottom
entry loader:startup
use i386
segment loader use16
startup:
mov ax,1687h
int 2Fh
or ax,ax ; DPMI installed?
jnz short no_dpmi
test bl,1 ; 32-bit programs supported?
jz short no_dpmi
mov word [cs:mode_switch],di
mov word [cs:mode_switch+2],es
mov bx,si ; allocate memory for DPMI data
mov ah,48h
int 21h
jnc switch_to_protected_mode
init_failed:
call startup_error
db 'DPMI initialization failed.',0Dh,0Ah,0
no_dpmi:
call startup_error
db '32-bit DPMI services are not available.',0Dh,0Ah,0
startup_error:
pop si
push cs
pop ds
show_message:
lodsb
test al,al
jz message_shown
mov dl,al
mov ah,2
int 21h
jmp show_message
message_shown:
mov ax,4CFFh
int 21h
switch_to_protected_mode:
mov es,ax
mov ds,[ds:2Ch]
mov ax,1
call far [cs:mode_switch] ; switch to protected mode
jc init_failed
mov cx,1
xor ax,ax
int 31h ; allocate descriptor for code
jc init_failed
mov si,ax
xor ax,ax
int 31h ; allocate descriptor for data
jc init_failed
mov di,ax
mov dx,cs
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,si
mov ax,9
int 31h ; set code descriptor access rights
jc init_failed
mov dx,ds
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,di
int 31h ; set data descriptor access rights
jc init_failed
mov ecx,main
shl ecx,4
mov dx,cx
shr ecx,16
mov ax,7
int 31h ; set data descriptor base address
jc init_failed
mov bx,si
int 31h ; set code descriptor base address
jc init_failed
mov cx,0FFFFh
mov dx,0FFFFh
mov ax,8 ; set segment limit to 4 GB
int 31h
jc init_failed
mov bx,di
int 31h
jc init_failed
mov ax,ds
mov ds,di
mov [main_selector],di
mov [psp_selector],es
mov gs,ax ; environment selector in GS
cli
mov ss,di
mov esp,stack_top
sti
mov es,di
mov cx,1
xor ax,ax
int 31h ; allocate descriptor for BIOS data segment
jc init_failed
mov bx,ax
mov ax,gs
lar cx,ax
shr cx,8
mov ax,9
int 31h ; set descriptor access rights
jc init_failed
xor cx,cx
mov dx,400h
mov ax,7
int 31h ; set base address of BIOS data segment
jc init_failed
xor cx,cx
mov dx,0FFh
mov ax,8
int 31h ; set limit of BIOS data segment
jc init_failed
mov fs,bx ; BIOS data selector in FS
push si
push start
retf
mode_switch dd ?
segment main use32
start:
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,[fs:6Ch]
mov [timer],eax
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,[fs:6Ch]
sub eax,[timer]
mov ecx,36000
mul ecx
shrd eax,edx,16
shr edx,16
mov ecx,10
div ecx
mov [timer],edx
or edx,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,[timer]
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
mov ax,4C00h
int 21h
assembly_failed:
call show_errors
call assembly_shutdown
call system_shutdown
mov ax,4C02h
int 21h
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 ax,4C03h
int 21h
display_usage_information:
mov esi,_usage
xor ecx,ecx
call display_string
call system_shutdown
mov ax,4C01h
int 21h
get_arguments:
push ds
mov ds,[psp_selector]
mov esi,81h
mov edi,command_line
mov ecx,7Fh
move_command_line:
lodsb
cmp al,0Dh
je command_line_moved
stosb
loop move_command_line
command_line_moved:
pop ds
xor eax,eax
stosb
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 esi,command_line
mov edi,parameters
get_argument:
xor ah,ah
read_character:
lodsb
test al,al
jz no_more_arguments
cmp al,22h
je switch_quote
cmp ax,20h
je end_argument
stosb
jmp read_character
end_argument:
xor al,al
stosb
find_next_argument:
mov al,[esi]
test al,al
jz no_more_arguments
cmp al,20h
jne next_argument_found
inc esi
jmp find_next_argument
switch_quote:
xor ah,1
jmp read_character
next_argument_found:
cmp al,'-'
je get_option
cmp al,'/'
je get_option
cmp [source_path],0
je get_source_path
cmp [output_path],0
je get_output_path
error_in_arguments:
or al,-1
retn
get_source_path:
mov [source_path],edi
jmp get_argument
get_output_path:
mov [output_path],edi
jmp get_argument
no_more_arguments:
cmp [source_path],0
je error_in_arguments
xor al,al
stosb
retn
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
mov al,[esi]
cmp al,20h
je find_next_argument
test al,al
jnz error_in_arguments
jmp find_next_argument
set_verbose_mode:
call get_option_value
jc error_in_arguments
cmp edx,2
ja error_in_arguments
mov [verbosity_level],edx
jmp find_next_argument
set_errors_limit:
call get_option_value
jc error_in_arguments
test edx,edx
jz error_in_arguments
mov [maximum_number_of_errors],edx
jmp find_next_argument
set_recursion_limit:
call get_option_value
jc error_in_arguments
test edx,edx
jz error_in_arguments
mov [maximum_depth_of_stack],edx
jmp find_next_argument
set_passes_limit:
call get_option_value
jc error_in_arguments
test edx,edx
jz error_in_arguments
mov [maximum_number_of_passes],edx
jmp find_next_argument
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
cmp al,20h
je option_value_ok
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:
push edi
find_command_segment:
cmp byte [esi],20h
jne command_segment_found
inc esi
jmp find_command_segment
command_segment_found:
xor ah,ah
cmp byte [esi],22h
jne measure_command_segment
inc esi
inc ah
measure_command_segment:
mov ebx,esi
scan_command_segment:
mov ecx,esi
mov al,[esi]
test al,al
jz command_segment_measured
cmp ax,20h
je command_segment_measured
cmp ax,22h
je command_segment_measured
inc esi
cmp al,22h
jne scan_command_segment
command_segment_measured:
sub ecx,ebx
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:
xchg esi,ebx
rep movsb
mov esi,ebx
sub edi,[initial_commands]
mov [initial_commands_length],edi
mov al,[esi]
test al,al
jz initial_command_ready
cmp al,20h
jne command_segment_found
initial_command_ready:
mov edi,[initial_commands]
add edi,[initial_commands_length]
mov ax,0Ah
stosw
inc [initial_commands_length]
pop edi
jmp find_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'
_logo db 'flat assembler version g.',VERSION,13,10,0
_usage db 'Usage: fasmg source [output]',13,10
db 'Optional settings:',13,10
db ' -e limit Set the maximum number of displayed errors (default 1)',13,10
db ' -p limit Set the maximum allowed number of passes (default 100)',13,10
db ' -r limit Set the maximum depth of the stack (default 10000)',13,10
db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,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'
align 4
include '../variables.inc'
psp_selector dw ?
main_selector dw ?
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 ?
timestamp dq ?
timer dd ?
verbosity_level dd ?
no_logo db ?
command_line db 80h dup ?
parameters db 80h dup ?
segment buffer_segment
buffer = (buffer_segment-main) shl 4
db BUFFER_SIZE dup ?
segment stack_segment
stack_bottom = (stack_segment-main) shl 4
db STACK_SIZE dup ?
stack_top = stack_bottom + $

View File

@ -0,0 +1,415 @@
LINE_FEED equ 13,10
system_init:
cld
mov [malloc_freelist],0
mov ah,2Ah
int 21h
push dx cx
movzx ecx,cx
mov eax,ecx
sub eax,1970
mov ebx,365
mul ebx
mov ebp,eax
mov eax,ecx
sub eax,1969
shr eax,2
add ebp,eax
mov eax,ecx
sub eax,1901
mov ebx,100
div ebx
sub ebp,eax
mov eax,ecx
xor edx,edx
sub eax,1601
mov ebx,400
div ebx
add ebp,eax
movzx ecx,byte [esp+3]
mov eax,ecx
dec eax
mov ebx,30
mul ebx
add ebp,eax
cmp ecx,8
jbe months_correction
mov eax,ecx
sub eax,7
shr eax,1
add ebp,eax
mov ecx,8
months_correction:
mov eax,ecx
shr eax,1
add ebp,eax
cmp ecx,2
pop cx
jbe day_correction_ok
sub ebp,2
test ecx,11b
jnz day_correction_ok
xor edx,edx
mov eax,ecx
mov ebx,100
div ebx
or edx,edx
jnz day_correction
mov eax,ecx
mov ebx,400
div ebx
or edx,edx
jnz day_correction_ok
day_correction:
inc ebp
day_correction_ok:
pop dx
movzx eax,dl
dec eax
add eax,ebp
mov ebx,24
mul ebx
push eax
mov ah,2Ch
int 21h
pop eax
push dx
movzx ebx,ch
add eax,ebx
mov ebx,60
mul ebx
movzx ebx,cl
add eax,ebx
mov ebx,60
mul ebx
pop bx
movzx ebx,bh
add eax,ebx
adc edx,0
mov dword [timestamp],eax
mov dword [timestamp+4],edx
retn
system_shutdown:
; call mcheck
retn
dos_int:
push 0
push 0
push 0
pushw buffer_segment
pushw buffer_segment
stc
pushfw
push eax
push ecx
push edx
push ebx
push 0
push ebp
push esi
push edi
mov ax,300h
mov bx,21h
xor cx,cx
mov edi,esp
push es ss
pop es
int 31h
pop es
mov edi,[esp]
mov esi,[esp+4]
mov ebp,[esp+8]
mov ebx,[esp+10h]
mov edx,[esp+14h]
mov ecx,[esp+18h]
mov ah,[esp+20h]
sahf
mov eax,[esp+1Ch]
lea esp,[esp+32h]
retn
open:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
push esi edi
call adapt_path
mov ax,716Ch
mov bx,100000b
mov dx,1
xor cx,cx
xor si,si
call dos_int
jnc open_done
cmp ax,7100h
je old_open
stc
jmp open_done
old_open:
mov ax,3D00h
xor dx,dx
call dos_int
open_done:
mov bx,ax
pop edi esi
retn
adapt_path:
mov esi,edx
mov edi,buffer
copy_path:
lodsb
cmp al,'/'
jne path_char_ok
mov al,'\'
path_char_ok:
stosb
cmp edi,buffer+BUFFER_SIZE
jae out_of_memory
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
mov ax,716Ch
mov bx,100001b
mov dx,10010b
xor cx,cx
xor si,si
xor di,di
call dos_int
jnc create_done
cmp ax,7100h
je old_create
stc
jmp create_done
old_create:
mov ah,3Ch
xor cx,cx
xor dx,dx
call dos_int
create_done:
mov bx,ax
pop edi esi
retn
write:
; in: ebx = file handle, edx - data, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push esi edi ebp
mov ebp,ecx
mov esi,edx
write_loop:
mov ecx,BUFFER_SIZE
sub ebp,BUFFER_SIZE
jnc do_write
add ebp,BUFFER_SIZE
mov ecx,ebp
xor ebp,ebp
do_write:
push ecx
mov edi,buffer
rep movsb
pop ecx
mov ah,40h
xor dx,dx
call dos_int
or ebp,ebp
jnz write_loop
pop ebp edi esi
ret
read:
; in: ebx = file handle, edx - buffer, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push esi edi ebp
mov ebp,ecx
mov edi,edx
read_loop:
mov ecx,BUFFER_SIZE
sub ebp,BUFFER_SIZE
jnc do_read
add ebp,BUFFER_SIZE
mov ecx,ebp
xor ebp,ebp
do_read:
push ecx
mov ah,3Fh
xor dx,dx
call dos_int
cmp ax,cx
jne read_eof
mov esi,buffer
pop ecx
rep movsb
or ebp,ebp
jnz read_loop
read_done:
pop ebp edi esi
ret
read_eof:
pop ecx
stc
jmp read_done
close:
; in: ebx = file handle
; preserves: ebx, esi, edi
mov ah,3Eh
int 21h
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
mov dx,ax
xchg ecx,eax
shr ecx,16
mov ah,42h
int 21h
pushf
shl edx,16
popf
mov dx,ax
mov eax,edx
xor edx,edx
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
mov ebx,1
jmp write_string
display_error_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx
mov ebx,2
write_string:
test ecx,ecx
jnz string_length_ok
xor al,al
mov edi,esi
or ecx,-1
repne scasb
neg ecx
sub ecx,2
string_length_ok:
mov edx,esi
call write
pop 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 esi edi
mov ebx,esi
xor esi,esi
compare_variable_names:
mov edx,ebx
compare_name_character:
lods byte [gs:esi]
mov ah,[edx]
inc edx
cmp al,'='
je end_of_variable_name
test ah,ah
jz next_variable
sub ah,al
jz compare_name_character
cmp ah,20h
jne next_variable
cmp al,41h
jb next_variable
cmp al,5Ah
jna compare_name_character
next_variable:
lods byte [gs:esi]
test al,al
jnz next_variable
cmp byte [gs:esi],0
jne compare_variable_names
mov ah,al
end_of_variable_name:
test ah,ah
jnz next_variable
add ecx,edi
mov edx,esi
copy_variable_value:
lods byte [gs:esi]
cmp edi,ecx
jae variable_value_next_character
stosb
variable_value_next_character:
or al,al
jnz copy_variable_value
lea eax,[esi-1]
sub eax,edx
pop edi esi ebx
ret
VALLOC_MIN = 40000h
valloc:
; in: ecx = requested minimum size
; out: eax - allocated block, ecx = allocated size, zero if failed
; preserves: ebx, esi, edi
cmp ecx,VALLOC_MIN
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_MIN
valloc_size_ready:
push ebx esi edi
push ecx
mov ebx,ecx
shr ebx,16
mov ax,501h
int 31h
movzx eax,cx
pop ecx
jc valloc_failed
shl ebx,16
or eax,ebx
mov edx,main
shl edx,4
sub eax,edx
pop edi esi ebx
ret
valloc_failed:
xor ecx,ecx
pop edi esi ebx
retn