add flat assembler toolchain

This commit is contained in:
2024-11-24 23:13:28 -05:00
parent 99e8e4072b
commit dbfd94ea40
302 changed files with 145599 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
; flat assembler interface for DOS
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
init_dpmi_memory:
mov ax,500h ; get free memory information
mov edi,[buffer_address]
int 31h
mov ebx,[edi]
allocate_dpmi_memory:
mov edx,[memory_setting]
shl edx,10
jz dpmi_memory_size_ok
cmp ebx,edx
jbe dpmi_memory_size_ok
mov ebx,edx
dpmi_memory_size_ok:
mov [memory_end],ebx
mov ecx,ebx
shr ebx,16
mov ax,501h
int 31h
jnc dpmi_memory_ok
mov ebx,[memory_end]
shr ebx,1
cmp ebx,4000h
jb out_of_memory
jmp allocate_dpmi_memory
dpmi_memory_ok:
shl ebx,16
mov bx,cx
sub ebx,[program_base]
jc out_of_memory
mov [memory_start],ebx
add [memory_end],ebx
mov ax,100h ; get free conventional memory size
mov bx,-1
int 31h
movzx ecx,bx
shl ecx,4
jecxz no_conventional_memory
mov ax,100h ; allocate all conventional memory
int 31h
movzx edi,ax
shl edi,4
sub edi,[program_base]
jc no_conventional_memory
mov [additional_memory],edi
mov [additional_memory_end],edi
add [additional_memory_end],ecx
mov eax,[memory_end]
sub eax,[memory_start]
shr eax,2
cmp eax,ecx
ja no_conventional_memory
ret
no_conventional_memory:
mov eax,[memory_end]
mov ebx,[memory_start]
sub eax,ebx
shr eax,2
mov [additional_memory],ebx
add ebx,eax
mov [additional_memory_end],ebx
mov [memory_start],ebx
ret
dpmi_dos_int:
mov [real_mode_segment],main
simulate_real_mode:
push 0 ; SS:SP (DPMI will allocate stack)
push 0 ; CS:IP (ignored)
push 0
push [real_mode_segment] ; DS
push [real_mode_segment] ; ES
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]
ret
dpmi_dos_int_with_buffer:
mov [real_mode_segment],buffer
jmp simulate_real_mode

View File

@ -0,0 +1,435 @@
; flat assembler interface for DOS
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
format MZ
heap 0
stack 8000h
entry main:start
include 'modes.inc'
segment main use16
start:
mov ax,ds
mov dx,[2Ch]
push cs cs
pop ds es
mov [psp_segment],ax
mov [environment_segment],dx
mov dx,_logo
mov ah,9
int 21h
cld
call go32
use32
call get_params
jc information
call init_memory
mov esi,_memory_prefix
call display_string
mov eax,[memory_end]
sub eax,[memory_start]
add eax,[additional_memory_end]
sub eax,[additional_memory]
shr eax,10
call display_number
mov esi,_memory_suffix
call display_string
xor ah,ah
int 1Ah
mov ax,cx
shl eax,16
mov ax,dx
mov [start_time],eax
cmp [mode],dpmi
je compile
jmp main+(first_segment shr 4):first_gate-first_segment
compile:
and [preprocessing_done],0
call preprocessor
or [preprocessing_done],-1
call parser
call assembler
call formatter
finish:
call display_user_messages
movzx eax,[current_pass]
inc eax
call display_number
mov esi,_passes_suffix
call display_string
xor ah,ah
int 1Ah
mov ax,cx
shl eax,16
mov ax,dx
sub eax,[start_time]
mov ebx,100
mul ebx
mov ebx,182
div ebx
or eax,eax
jz display_bytes_count
xor edx,edx
mov ebx,10
div ebx
push edx
call display_number
mov ah,2
mov dl,'.'
int 21h
pop eax
call display_number
mov esi,_seconds_suffix
call display_string
display_bytes_count:
mov eax,[written_size]
call display_number
mov esi,_bytes_suffix
call display_string
xor al,al
jmp exit_program
information:
mov esi,_usage
call display_string
mov al,1
jmp exit_program
get_params:
mov [input_file],0
mov [output_file],0
mov [symbols_file],0
mov [memory_setting],0
mov [passes_limit],100
mov [definitions_pointer],predefinitions
push ds
mov ds,[psp_segment]
mov esi,81h
mov edi,params
find_param:
lodsb
cmp al,20h
je find_param
cmp al,'-'
je option_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [es:input_file],0
jne get_output_file
mov [es:input_file],edi
jmp process_param
get_output_file:
cmp [es:output_file],0
jne bad_params
mov [es:output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
stosb
jmp string_param
option_param:
lodsb
cmp al,'m'
je memory_option
cmp al,'M'
je memory_option
cmp al,'p'
je passes_option
cmp al,'P'
je passes_option
cmp al,'d'
je definition_option
cmp al,'D'
je definition_option
cmp al,'s'
je symbols_option
cmp al,'S'
je symbols_option
invalid_option:
pop ds
stc
ret
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc bad_params_value
cmp al,9
ja bad_params_value
imul edx,10
jo bad_params_value
add edx,eax
jc bad_params_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
bad_params_value:
stc
ret
memory_option:
lodsb
cmp al,20h
je memory_option
cmp al,0Dh
je invalid_option
or al,al
jz invalid_option
dec esi
call get_option_value
jc invalid_option
or edx,edx
jz invalid_option
cmp edx,1 shl (32-10)
jae invalid_option
mov [es:memory_setting],edx
jmp find_param
passes_option:
lodsb
cmp al,20h
je passes_option
cmp al,0Dh
je invalid_option
or al,al
jz invalid_option
dec esi
call get_option_value
jc bad_params
or edx,edx
jz invalid_option
cmp edx,10000h
ja invalid_option
mov [es:passes_limit],dx
jmp find_param
definition_option:
lodsb
cmp al,20h
je definition_option
cmp al,0Dh
je bad_params
or al,al
jz bad_params
dec esi
push edi
mov edi,[es:definitions_pointer]
call convert_definition_option
mov [es:definitions_pointer],edi
pop edi
jc invalid_option
jmp find_param
symbols_option:
mov [es:symbols_file],edi
find_symbols_file_name:
lodsb
cmp al,20h
jne process_param
jmp find_symbols_file_name
param_end:
dec esi
string_param_end:
xor al,al
stosb
jmp find_param
all_params:
xor al,al
stosb
pop ds
cmp [input_file],0
je no_input_file
mov eax,[definitions_pointer]
mov byte [eax],0
mov [initial_definitions],predefinitions
clc
ret
bad_params:
pop ds
no_input_file:
stc
ret
convert_definition_option:
mov ecx,edi
xor al,al
stosb
copy_definition_name:
lodsb
cmp al,'='
je copy_definition_value
cmp al,20h
je bad_definition_option
cmp al,0Dh
je bad_definition_option
or al,al
jz bad_definition_option
stosb
inc byte [es:ecx]
jnz copy_definition_name
bad_definition_option:
stc
ret
copy_definition_value:
lodsb
cmp al,20h
je definition_value_end
cmp al,0Dh
je definition_value_end
or al,al
jz definition_value_end
cmp al,'\'
jne definition_value_character
cmp byte [esi],20h
jne definition_value_character
lodsb
definition_value_character:
stosb
jmp copy_definition_value
definition_value_end:
dec esi
xor al,al
stosb
clc
ret
include '..\version.inc'
_logo db 'flat assembler version ',VERSION_STRING,24h
_copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0Dh,0Ah,0
_usage db 0Dh,0Ah
db 'usage: fasm <source> [output]',0Dh,0Ah
db 'optional settings:',0Dh,0Ah
db ' -m <limit> set the limit in kilobytes for the available memory',0Dh,0Ah
db ' -p <limit> set the maximum allowed number of passes',0Dh,0Ah
db ' -d <name>=<value> define symbolic variable',0Dh,0Ah
db ' -s <file> dump symbolic information for debugging',0Dh,0Ah
db 0
_memory_prefix db ' (',0
_memory_suffix db ' kilobytes memory)',0Dh,0Ah,0
_passes_suffix db ' passes, ',0
_seconds_suffix db ' seconds, ',0
_bytes_suffix db ' bytes.',0Dh,0Ah,0
error_prefix db 'error: ',0
error_suffix db '.'
cr_lf db 0Dh,0Ah,0
line_number_start db ' [',0
line_data_start db ':',0Dh,0Ah,0
preprocessed_instruction_prefix db 'processed: ',0
include 'dpmi.inc'
align 16
first_segment:
include '..\preproce.inc'
include '..\parser.inc'
include '..\exprpars.inc'
align 16
second_segment:
include '..\exprcalc.inc'
include '..\errors.inc'
include '..\symbdump.inc'
include 'system.inc'
first_gate:
and [preprocessing_done],0
call preprocessor
or [preprocessing_done],-1
call parser
jmp main+(second_segment shr 4):second_gate-second_segment
first_segment_top = $ - first_segment
include '..\assemble.inc'
include '..\formats.inc'
include '..\x86_64.inc'
include '..\avx.inc'
second_gate:
call assembler
call formatter
jmp main:finish
second_segment_top = $ - second_segment
if first_segment_top>=10000h | second_segment_top>=10000h
if UNREAL_ENABLED>0
UNREAL_ENABLED = -1
else
UNREAL_ENABLED = 0
end if
else
if UNREAL_ENABLED<0
UNREAL_ENABLED = -1
else
UNREAL_ENABLED = 1
end if
end if
include '..\tables.inc'
include '..\messages.inc'
align 4
include '..\variable.inc'
memory_setting dd ?
start_time dd ?
definitions_pointer dd ?
params rb 100h
predefinitions rb 100h
mode dw ?
real_mode_segment dw ?
displayed_count dd ?
last_displayed rb 2
preprocessing_done db ?
segment buffer
rb 1000h

View File

@ -0,0 +1,539 @@
; flat assembler interface for DOS
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
segment modes use16
real32:
mov ax,7202h
push ax
popf
pushf
pop bx
cmp ax,bx
je processor_ok
call init_error
db 'required 80386 or better',24h
processor_ok:
mov eax,ds
shl eax,4
mov [program_base],eax
mov eax,buffer
shl eax,4
sub eax,[program_base]
mov [buffer_address],eax
if UNREAL_ENABLED>0
smsw ax
test al,1
jnz dpmi
mov eax,cs ; calculate linear address of GDT
shl eax,4
or dword [cs:real32_GDT+10],eax
or dword [cs:real16_GDT+10],eax
add [cs:real32_GDT_address],eax
add [cs:real16_GDT_address],eax
cli
lgdt [cs:real32_GDTR]
mov eax,cr0
or al,1
mov cr0,eax
jmp 1 shl 3:test_pm32
no_rm32:
sti
jmp dpmi
test_pm32:
use32
mov eax,cr0
and al,not 1
mov cr0,eax
mov ebx,0FFFFh
jmp modes:test_rm32
test_rm32:
inc ebx
jz short no_rm32
lgdt [cs:real16_GDTR]
mov eax,cr0
or al,1
mov cr0,eax
jmp 1 shl 3:test_pm16
test_pm16:
use16
mov eax,cr0
and al,not 1
mov cr0,eax
jmp modes:test_rm16
test_rm16:
sti
mov bx,(400h+(100h*interrupt.size)) shr 4
mov ah,48h
int 21h
jc not_enough_memory
push ds es
mov es,ax
push cs
pop ds
movzx eax,ax
shl eax,4
mov [real32_IDT_base],eax
mov dx,100h
xor bx,bx
mov di,400h
init_interrupts:
mov si,interrupt
mov [si+interrupt.vector],bx
mov word [es:bx],di
mov word [es:bx+2],es
mov cx,interrupt.size
rep movsb
add bx,4
dec dx
jnz init_interrupts
pop es ds
call modes:switch_real32
use32
mov [mode],real32
retfw
use16
switch_real32:
pushfw
push eax
push word ds
push word es
push word fs
push word gs
cli
mov eax,ss
mov cr3,eax
lgdt [cs:real32_GDTR]
mov eax,cr0 ; switch to protected mode
or al,1
mov cr0,eax
jmp 1 shl 3:pm32_start
pm32_start:
use32
mov ax,2 shl 3 ; load 32-bit data descriptor
mov ds,ax ; to all data segment registers
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov eax,cr0 ; switch back to real mode
and al,not 1
mov cr0,eax
jmp modes:pm32_end
pm32_end:
mov eax,cr3
mov ss,ax
lidt [cs:real32_IDTR]
pop word gs
pop word fs
pop word es
pop word ds
pop eax
popfw
retfw
switch_real16:
pushfw
push eax
cli
lgdt [cs:real16_GDTR]
mov eax,cr0 ; switch to protected mode
or al,1
mov cr0,eax
jmp 1 shl 3:pm16_start
pm16_start:
use16
mov eax,cr0 ; switch back to real mode
and al,not 1
mov cr0,eax
jmp modes:pm16_end
pm16_end:
lidt [cs:real16_IDTR]
pop eax
popfw
retfd
use32
interrupt:
call modes:switch_real16
use16
movzx esp,sp
push word [esp+4]
push cs
call .real16
pushfw
pop word [esp+4]
call modes:switch_real32
use32
iretw
.real16:
use16
push eax
push ds
xor ax,ax
mov ds,ax
mov eax,[word 0]
label .vector word at $-2-interrupt
pop ds
xchg eax,[esp]
retfw
.size = $-interrupt
label real32_GDTR pword
real32_GDT_limit dw 3*8-1 ; limit of GDT
real32_GDT_address dd real32_GDT ; linear address of GDT
real32_GDT rw 4 ; null descriptor
dw 0FFFFh,0,9A00h,0CFh ; 32-bit code descriptor
dw 0FFFFh,0,9200h,08Fh ; 4 GB data descriptor
label real16_GDTR pword
real16_GDT_limit dw 2*8-1 ; limit of GDT
real16_GDT_address dd real16_GDT ; linear address of GDT
real16_GDT rw 4 ; null descriptor
dw 0FFFFh,0,9A00h,0 ; 16-bit code descriptor
label real32_IDTR pword
real32_IDT_limit dw 3FFh
real32_IDT_base dd ?
label real16_IDTR pword
real16_IDT_limit dw 3FFh
real16_IDT_base dd 0
end if
dpmi:
mov ax,1687h
int 2Fh
or ax,ax ; DPMI installed?
jnz no_dpmi
test bl,1 ; 32-bit programs supported?
jz 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
jc not_enough_memory
mov ds,[environment_segment]
mov es,ax
mov ax,1
call far [cs:mode_switch] ; switch to protected mode
jc no_dpmi
mov cx,1
xor ax,ax
int 31h ; allocate descriptor for code
mov si,ax
xor ax,ax
int 31h ; allocate descriptor for data
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
mov dx,ds
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,di
int 31h ; set data descriptor access rights
mov ecx,main
shl ecx,4
mov dx,cx
shr ecx,16
mov ax,7
int 31h ; set data descriptor base address
movzx ecx,word [esp+2]
shl ecx,4
mov dx,cx
shr ecx,16
mov bx,si
int 31h ; set code descriptor base address
mov cx,0FFFFh
mov dx,0FFFFh
mov ax,8 ; set segment limit to 4 GB
int 31h
mov bx,di
int 31h
mov ax,ds
mov ds,di
mov [psp_segment],es
mov [environment_segment],ax
mov es,di
mov [mode],dpmi
pop ebx
movzx ebx,bx
push esi
push ebx
retfd
init_error:
push cs
pop ds
mov dx,init_error_prefix
mov ah,9
int 21h
pop dx
int 21h
mov dx,init_error_suffix
int 21h
mov ax,04CFFh
int 21h
init_error_prefix db 0Dh,0Ah,'error: ',24h
init_error_suffix db '.',0Dh,0Ah,24h
mode_switch dd ?
not_enough_memory:
call init_error
db 'not enough conventional memory',24h
if UNREAL_ENABLED>0
no_dpmi:
smsw ax
test al,1
jz no_real32
call init_error
db 'system is in protected mode without 32-bit DPMI services',24h
no_real32:
call init_error
db 'processor is not able to enter 32-bit real mode',24h
else
no_dpmi:
call init_error
db 'no 32-bit DPMI services are available',24h
end if
use32
if UNREAL_ENABLED>0
init_real32_memory:
mov ax,4300h ; check for XMS
int 2Fh
cmp al,80h ; XMS present?
je xms_init
mov ax,0E801h ; check for large free extended memory
int 15h
jnc large_raw_memory
mov ah,88h ; how much extended memory free?
int 15h
or ax,ax
jz no_extended_memory
movzx eax,ax ; convert AX kilobytes to pointer
shl eax,10
jmp use_raw_memory
large_raw_memory:
movzx ecx,cx
shl ecx,10
movzx edx,dx
shl edx,16
mov eax,ecx
add eax,edx
use_raw_memory:
add eax,100000h
sub eax,[program_base]
mov [memory_end],eax
push ds
push 0 ; DS := 0
pop ds
call enable_a20 ; enable A20
call test_a20 ; is A20 enabled?
jz a20_ok
pop ds
jmp no_extended_memory
a20_ok:
lds bx,dword [4*19h]
mov eax,100000h ; initial free extended memory base
cmp dword [bx+12h],'VDIS' ; VDISK memory allocation?
jne short no_vdisk ; if present, get base of free memory
mov eax,dword [bx+2Ch] ; get first free extended memory byte
add eax,0Fh ; align on paragraph
and eax,0FFFFF0h ; address is only 24bit
no_vdisk:
push 0FFFFh ; DS := FFFFh for ext mem addressing
pop ds
cmp dword [13h],'VDIS' ; VDISK memory allocation?
jne short vdisk_ok ; if present, get base of free memory
movzx ebx,word [2Eh] ; get first free kilobyte
shl ebx,10
cmp eax,ebx ; pick larger of 2 addresses
ja short vdisk_ok
mov eax,ebx
vdisk_ok:
pop ds
sub eax,[program_base]
mov [memory_start],eax
mov edx,[memory_setting]
shl edx,10
jz extended_memory_ok
mov eax,[memory_end]
sub eax,[memory_start]
sub eax,edx
jbe extended_memory_ok
sub [memory_end],eax
jmp extended_memory_ok
enable_a20:
call test_a20 ; is A20 already enabled?
jz a20_enabled ; if yes, done
in al,92h ; PS/2 A20 enable
or al,2
out 92h,al
call test_a20 ; is A20 enabled?
jz a20_enabled ; if yes, done
call kb_wait ; AT A20 enable
jnz a20_enabled
mov al,0D1h
out 64h,al
call kb_wait
jnz a20_enabled
mov al,0DFh
out 60h,al
call kb_wait
a20_enabled:
retn
kb_wait: ; wait for safe to write to 8042
xor cx,cx
.loop:
in al,64h ; read 8042 status
test al,2 ; buffer full?
loopnz .loop ; if yes, loop
retn
test_a20: ; test for enabled A20
mov al,[0] ; get byte from 0:0
mov ah,al ; preserve old byte
not al ; modify byte
xchg al,[100000h] ; put modified byte to 0FFFFh:10h
cmp ah,[0] ; set zero if byte at 0:0 not modified
mov [100000h],al ; restore byte at 0FFFFh:10h
retn ; return, zero if A20 enabled
xms_init:
push es
mov ax,4310h ; get XMS driver address
int 2Fh
mov word [cs:xms_proc],bx ; store XMS driver address
mov word [cs:xms_proc+2],es
pop es
mov ah,3 ; enable A20
call call_xms
cmp ax,1 ; error enabling A20?
jne no_extended_memory
mov ah,88h ; get free extended memory size (XMS 3.0)
xor bl,bl
call call_xms
or bl,bl
jz xms_large_init
mov ah,8 ; get free extended memory size
xor bl,bl
call call_xms
or bl,bl
jnz no_extended_memory
mov dx,ax
movzx eax,ax
shl eax,10
mov [memory_end],eax
mov ah,9 ; allocate largest memory block
xms_allocate:
mov ecx,[memory_setting]
shl ecx,10
jz xms_size_ok
cmp ecx,[memory_end]
jae xms_size_ok
mov [memory_end],ecx
mov edx,[memory_setting]
xms_size_ok:
call call_xms
mov [cs:xms_handle],dx
cmp ax,1
jne no_extended_memory
mov ah,0Ch ; lock extended memory block
call call_xms
cmp ax,1
jne no_extended_memory
shl edx,16
mov dx,bx
sub edx,[program_base]
mov [memory_start],edx ; store memory block address
add [memory_end],edx
jmp extended_memory_ok
xms_large_init:
mov edx,eax
shl eax,10
mov [memory_end],eax
mov ah,89h ; allocate largest memory block (XMS 3.0)
jmp xms_allocate
call_xms:
call modes:switch_real16
use16
call far dword [cs:xms_proc]
call modes:switch_real32
use32
retn
no_extended_memory:
xor eax,eax
mov [memory_start],eax
extended_memory_ok:
mov ah,48h ; get free conventional memory size
mov bx,-1
int 21h
movzx ecx,bx
shl ecx,4
mov ah,48h ; allocate all conventional memory
int 21h
movzx edi,ax
shl edi,4
sub edi,[program_base]
mov [additional_memory],edi
mov [additional_memory_end],edi
add [additional_memory_end],ecx
cmp [memory_start],0
je only_conventional_memory
mov eax,[memory_end]
sub eax,[memory_start]
shr eax,2
cmp eax,ecx
jbe real32_memory_ok
mov eax,[memory_end]
mov ebx,[memory_start]
sub eax,ebx
shr eax,2
mov [additional_memory],ebx
add ebx,eax
mov [additional_memory_end],ebx
mov [memory_start],ebx
real32_memory_ok:
retf
only_conventional_memory:
shr ecx,2 ; use part of conventional memory
add edi,ecx ; as a substitute for extended memory
mov [memory_start],edi
xchg [additional_memory_end],edi
mov [memory_end],edi
retf
free_real32_memory:
cmp [cs:xms_handle],0
je no_xms
mov ah,0Dh ; unlock extended memory block
mov dx,[cs:xms_handle]
call call_xms
mov ah,0Ah ; free extended memory block
call call_xms
no_xms:
retf
xms_proc dd ? ; XMS driver pointer
xms_handle dw ? ; handle of XMS memory block
end if

View File

@ -0,0 +1,600 @@
; flat assembler interface for DOS
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
go32:
use16
call modes:real32
use32
retw
program_base dd ?
buffer_address dd ?
psp_segment dw ?
environment_segment dw ?
if UNREAL_ENABLED>0
init_memory:
mov [stack_limit],0
cmp [mode],dpmi
je init_dpmi_memory
call modes:init_real32_memory
ret
dos_int:
cmp [mode],dpmi
je dpmi_dos_int
stc
int 21h
ret
dos_int_with_buffer:
cmp [mode],dpmi
je dpmi_dos_int_with_buffer
push ds buffer
pop ds
stc
int 21h
pop ds
ret
exit_program:
cmp [mode],dpmi
je exit_state_ok
push eax
call modes:free_real32_memory
pop eax
exit_state_ok:
mov ah,4Ch
int 21h
else
init_memory:
mov [stack_limit],0
jmp init_dpmi_memory
dos_int:
jmp dpmi_dos_int
dos_int_with_buffer:
jmp dpmi_dos_int_with_buffer
exit_program:
mov ah,4Ch
int 21h
end if
get_environment_variable:
mov ebx,esi
push ds
mov ds,[environment_segment]
xor esi,esi
compare_variable_names:
mov edx,ebx
compare_character:
lodsb
mov ah,[es:edx]
inc edx
cmp al,'='
je end_of_variable_name
or ah,ah
jz next_variable
sub ah,al
jz compare_character
cmp ah,20h
jne next_variable
cmp al,41h
jb next_variable
cmp al,5Ah
jna compare_character
next_variable:
lodsb
or al,al
jnz next_variable
cmp byte [esi],0
jne compare_variable_names
pop ds
ret
end_of_variable_name:
or ah,ah
jnz next_variable
copy_variable_value:
lodsb
cmp edi,[es:memory_end]
jae out_of_memory
stosb
or al,al
jnz copy_variable_value
dec edi
pop ds
ret
open:
push esi edi
call adapt_path
mov ax,716Ch
mov bx,100000b
mov dx,1
xor cx,cx
xor si,si
call dos_int_with_buffer
jnc open_done
cmp ax,7100h
je old_open
stc
jmp open_done
old_open:
mov ax,3D00h
xor dx,dx
call dos_int_with_buffer
open_done:
mov bx,ax
pop edi esi
ret
adapt_path:
mov esi,edx
mov edi,[buffer_address]
copy_path:
lodsb
cmp al,'/'
jne path_char_ok
mov al,'\'
path_char_ok:
stosb
or al,al
jnz copy_path
ret
create:
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_with_buffer
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_with_buffer
create_done:
mov bx,ax
pop edi esi
ret
write:
push edx esi edi ebp
mov ebp,ecx
mov esi,edx
.loop:
mov ecx,1000h
sub ebp,1000h
jnc .write
add ebp,1000h
mov ecx,ebp
xor ebp,ebp
.write:
push ecx
mov edi,[buffer_address]
shr ecx,2
rep movsd
mov ecx,[esp]
and ecx,11b
rep movsb
pop ecx
mov ah,40h
xor dx,dx
call dos_int_with_buffer
or ebp,ebp
jnz .loop
pop ebp edi esi edx
ret
read:
push edx esi edi ebp
mov ebp,ecx
mov edi,edx
.loop:
mov ecx,1000h
sub ebp,1000h
jnc .read
add ebp,1000h
mov ecx,ebp
xor ebp,ebp
.read:
push ecx
mov ah,3Fh
xor dx,dx
call dos_int_with_buffer
cmp ax,cx
jne .eof
mov esi,[buffer_address]
mov ecx,[esp]
shr ecx,2
rep movsd
pop ecx
and ecx,11b
rep movsb
or ebp,ebp
jnz .loop
.exit:
pop ebp edi esi edx
ret
.eof:
pop ecx
stc
jmp .exit
close:
mov ah,3Eh
int 21h
ret
lseek:
mov ah,42h
mov ecx,edx
shr ecx,16
int 21h
pushf
shl edx,16
popf
mov dx,ax
mov eax,edx
ret
display_string:
lods byte [esi]
or al,al
jz string_end
mov dl,al
mov ah,2
int 21h
jmp display_string
string_end:
ret
display_number:
push ebx
mov ecx,1000000000
xor edx,edx
xor bl,bl
display_loop:
div ecx
push edx
cmp ecx,1
je display_digit
or bl,bl
jnz display_digit
or al,al
jz digit_ok
not bl
display_digit:
mov dl,al
add dl,30h
mov ah,2
int 21h
digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
pop eax
or ecx,ecx
jnz display_loop
pop ebx
ret
display_user_messages:
mov [displayed_count],0
call show_display_buffer
cmp [displayed_count],1
jb line_break_ok
je make_line_break
mov ax,word [last_displayed]
cmp ax,0A0Dh
je line_break_ok
cmp ax,0D0Ah
je line_break_ok
make_line_break:
mov ah,2
mov dl,0Dh
int 21h
mov dl,0Ah
int 21h
line_break_ok:
ret
display_block:
add [displayed_count],ecx
cmp ecx,1
ja take_last_two_characters
jb display_character
mov al,[last_displayed+1]
mov ah,[esi]
mov word [last_displayed],ax
jmp display_character
take_last_two_characters:
mov ax,[esi+ecx-2]
mov word [last_displayed],ax
display_character:
lods byte [esi]
mov dl,al
mov ah,2
int 21h
loopd display_character
ret
fatal_error:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,0FFh
jmp exit_program
assembler_error:
call display_user_messages
mov ebx,[current_line]
test ebx,ebx
jz display_error_message
pushd 0
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
push ebx
test byte [ebx+7],80h
jz display_error_line
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
display_error_line:
mov esi,[ebx]
call display_string
mov esi,line_number_start
call display_string
mov eax,[ebx+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
mov ah,2
int 21h
pop esi
cmp ebx,esi
je line_number_ok
mov dl,20h
mov ah,2
int 21h
push esi
mov esi,[esi]
movzx ecx,byte [esi]
inc esi
call display_block
mov esi,line_number_start
call display_string
pop esi
mov eax,[esi+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
mov ah,2
int 21h
line_number_ok:
mov esi,line_data_start
call display_string
mov esi,ebx
mov edx,[esi]
call open
mov al,2
xor edx,edx
call lseek
mov edx,[esi+8]
sub eax,edx
jz line_data_displayed
mov [counter],eax
xor al,al
call lseek
mov esi,[additional_memory]
read_line_data:
mov ecx,100h
cmp ecx,[counter]
jbe bytes_count_ok
mov ecx,[counter]
bytes_count_ok:
sub [counter],ecx
lea eax,[esi+ecx]
cmp eax,[additional_memory_end]
ja out_of_memory
push ecx
mov edx,esi
call read
pop ecx
get_line_data:
mov al,[esi]
cmp al,0Ah
je display_line_data
cmp al,0Dh
je display_line_data
cmp al,1Ah
je display_line_data
or al,al
jz display_line_data
inc esi
loop get_line_data
cmp [counter],0
ja read_line_data
display_line_data:
call close
mov ecx,esi
mov esi,[additional_memory]
sub ecx,esi
call display_block
line_data_displayed:
mov esi,cr_lf
call display_string
pop ebx
or ebx,ebx
jnz display_error_line
cmp [preprocessing_done],0
je display_error_message
mov esi,preprocessed_instruction_prefix
call display_string
mov esi,[current_line]
add esi,16
mov edi,[additional_memory]
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je instruction_converted
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_instruction
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_instruction
instruction_converted:
xor al,al
stosb
mov esi,[additional_memory]
call display_string
mov esi,cr_lf
call display_string
display_error_message:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,2
jmp exit_program
make_timestamp:
mov 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
ret

View File

@ -0,0 +1,191 @@
; flat assembler core
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
out_of_memory:
push _out_of_memory
jmp fatal_error
stack_overflow:
push _stack_overflow
jmp fatal_error
main_file_not_found:
push _main_file_not_found
jmp fatal_error
write_failed:
push _write_failed
jmp fatal_error
code_cannot_be_generated:
push _code_cannot_be_generated
jmp general_error
format_limitations_exceeded:
push _format_limitations_exceeded
jmp general_error
invalid_definition:
push _invalid_definition
general_error:
cmp [symbols_file],0
je fatal_error
call dump_preprocessed_source
jmp fatal_error
file_not_found:
push _file_not_found
jmp error_with_source
error_reading_file:
push _error_reading_file
jmp error_with_source
invalid_file_format:
push _invalid_file_format
jmp error_with_source
invalid_macro_arguments:
push _invalid_macro_arguments
jmp error_with_source
incomplete_macro:
push _incomplete_macro
jmp error_with_source
unexpected_characters:
push _unexpected_characters
jmp error_with_source
invalid_argument:
push _invalid_argument
jmp error_with_source
illegal_instruction:
push _illegal_instruction
jmp error_with_source
invalid_operand:
push _invalid_operand
jmp error_with_source
invalid_operand_size:
push _invalid_operand_size
jmp error_with_source
operand_size_not_specified:
push _operand_size_not_specified
jmp error_with_source
operand_sizes_do_not_match:
push _operand_sizes_do_not_match
jmp error_with_source
invalid_address_size:
push _invalid_address_size
jmp error_with_source
address_sizes_do_not_agree:
push _address_sizes_do_not_agree
jmp error_with_source
disallowed_combination_of_registers:
push _disallowed_combination_of_registers
jmp error_with_source
long_immediate_not_encodable:
push _long_immediate_not_encodable
jmp error_with_source
relative_jump_out_of_range:
push _relative_jump_out_of_range
jmp error_with_source
invalid_expression:
push _invalid_expression
jmp error_with_source
invalid_address:
push _invalid_address
jmp error_with_source
invalid_value:
push _invalid_value
jmp error_with_source
value_out_of_range:
push _value_out_of_range
jmp error_with_source
undefined_symbol:
mov edi,message
mov esi,_undefined_symbol
call copy_asciiz
push message
cmp [error_info],0
je error_with_source
mov esi,[error_info]
mov esi,[esi+24]
or esi,esi
jz error_with_source
mov byte [edi-1],20h
call write_quoted_symbol_name
jmp error_with_source
copy_asciiz:
lods byte [esi]
stos byte [edi]
test al,al
jnz copy_asciiz
ret
write_quoted_symbol_name:
mov al,27h
stosb
movzx ecx,byte [esi-1]
rep movs byte [edi],[esi]
mov ax,27h
stosw
ret
symbol_out_of_scope:
mov edi,message
mov esi,_symbol_out_of_scope_1
call copy_asciiz
cmp [error_info],0
je finish_symbol_out_of_scope_message
mov esi,[error_info]
mov esi,[esi+24]
or esi,esi
jz finish_symbol_out_of_scope_message
mov byte [edi-1],20h
call write_quoted_symbol_name
finish_symbol_out_of_scope_message:
mov byte [edi-1],20h
mov esi,_symbol_out_of_scope_2
call copy_asciiz
push message
jmp error_with_source
invalid_use_of_symbol:
push _invalid_use_of_symbol
jmp error_with_source
name_too_long:
push _name_too_long
jmp error_with_source
invalid_name:
push _invalid_name
jmp error_with_source
reserved_word_used_as_symbol:
push _reserved_word_used_as_symbol
jmp error_with_source
symbol_already_defined:
push _symbol_already_defined
jmp error_with_source
missing_end_quote:
push _missing_end_quote
jmp error_with_source
missing_end_directive:
push _missing_end_directive
jmp error_with_source
unexpected_instruction:
push _unexpected_instruction
jmp error_with_source
extra_characters_on_line:
push _extra_characters_on_line
jmp error_with_source
section_not_aligned_enough:
push _section_not_aligned_enough
jmp error_with_source
setting_already_specified:
push _setting_already_specified
jmp error_with_source
data_already_defined:
push _data_already_defined
jmp error_with_source
too_many_repeats:
push _too_many_repeats
jmp error_with_source
assertion_failed:
push _assertion_failed
jmp error_with_source
invoked_error:
push _invoked_error
error_with_source:
cmp [symbols_file],0
je assembler_error
call dump_preprocessed_source
call restore_preprocessed_source
jmp assembler_error

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,536 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
insert_block:
test [editor_mode],FEMODE_VERTICALSEL
jz block_to_insert_ok
push esi
or edx,-1
xor ecx,ecx
count_line_characters:
lodsb
cmp al,9
je cannot_insert
cmp al,0Dh
je count_next_line
or al,al
jz end_of_line
inc ecx
jmp count_line_characters
end_of_line:
dec esi
jmp check_block_width
count_next_line:
lodsb
cmp al,0Ah
je check_block_width
dec esi
check_block_width:
cmp edx,-1
je line_to_insert_ok
cmp edx,ecx
je line_to_insert_ok
cannot_insert:
pop esi
stc
retn
line_to_insert_ok:
mov edx,ecx
xor ecx,ecx
cmp byte [esi],0
jne count_line_characters
pop esi
block_to_insert_ok:
mov eax,[caret_line]
mov ecx,[caret_line_number]
mov edx,[caret_position]
mov [selection_line],eax
mov [selection_line_number],ecx
mov [selection_position],edx
mov ebx,esi
get_line_to_insert:
lodsb
or al,al
jz insert_full_line
cmp al,0Dh
je insert_full_line
cmp al,0Ah
je insert_full_line
cmp al,9
jne get_line_to_insert
push esi
dec esi
mov ecx,esi
sub ecx,ebx
mov esi,ebx
push ecx
call insert_into_line
pop ecx
add [caret_position],ecx
mov ecx,[caret_position]
and ecx,not 111b
sub ecx,[caret_position]
add ecx,8
xor esi,esi
push ecx
call insert_into_line
pop ecx
add [caret_position],ecx
pop esi
mov ebx,esi
jmp get_line_to_insert
insert_full_line:
dec esi
push esi
mov ecx,esi
sub ecx,ebx
mov esi,ebx
push ecx
call insert_into_line
pop ecx
add [caret_position],ecx
pop esi
lodsb
or al,al
jz last_line_inserted
cmp al,0Ah
je lf_first
lodsb
cmp al,0Ah
je next_line_to_insert
dec esi
jmp next_line_to_insert
lf_first:
lodsb
cmp al,0Dh
je next_line_to_insert
dec esi
next_line_to_insert:
mov ebx,[selection_position]
test [editor_mode],FEMODE_VERTICALSEL
jnz insert_in_next_line
test [editor_mode],FEMODE_OVERWRITE
jz insert_new_line
push esi
call clear_rest_of_line
pop esi
xor ebx,ebx
insert_in_next_line:
push esi ebx
mov esi,[caret_line]
call check_line_length
pop ebx
call go_to_next_line
pop esi
mov ebx,esi
jmp get_line_to_insert
last_line_inserted:
mov esi,[caret_line]
call check_line_length
clc
retn
insert_new_line:
push esi
push [caret_line]
push [caret_line_number]
xor ebx,ebx
call break_line
pop [caret_line_number]
pop ebx esi
push [caret_line]
mov [caret_line],ebx
go_to_end_of_first_line:
test byte [ebx],1
jz insert_full_lines
mov ebx,[ebx]
dec ebx
jmp go_to_end_of_first_line
insert_full_lines:
call allocate_segment
jc memory_shortage
call store_allocated_segment_for_undo
mov [ebx],eax
mov ebx,eax
mov eax,[caret_line]
mov [ebx+4],eax
mov [caret_line],ebx
inc [caret_line_number]
inc [lines_count]
call set_line
jc full_lines_inserted
jmp insert_full_lines
full_lines_inserted:
pop edi
mov eax,[caret_line]
mov [edi+4],eax
mov [ebx],edi
call cut_line_break
mov esi,[caret_line]
call check_line_length
clc
retn
set_line:
mov edi,ebx
add edi,SEGMENT_HEADER_LENGTH
mov ecx,SEGMENT_DATA_LENGTH
mov [caret_position],0
push ebx
copy_line:
lodsb
or al,al
jz last_line_set
cmp al,0Ah
je copy_lf
cmp al,0Dh
je copy_cr
cmp al,9
je copy_tab
set_character:
stosb
loop copy_line
extra_segment:
call allocate_segment
jc memory_shortage
call store_allocated_segment_for_undo
mov edi,eax
or eax,1
mov [ebx],eax
or ebx,1
mov [edi+4],ebx
mov ebx,edi
add edi,SEGMENT_HEADER_LENGTH
mov ecx,SEGMENT_DATA_LENGTH
add [caret_position],ecx
jmp copy_line
copy_tab:
mov al,20h
mov edx,SEGMENT_DATA_LENGTH
sub edx,ecx
add edx,[caret_position]
and edx,111b
cmp edx,111b
je set_character
dec esi
jmp set_character
copy_lf:
cmp byte [esi],0Dh
jne copy_new_line
inc esi
jmp copy_new_line
copy_cr:
cmp byte [esi],0Ah
jne copy_new_line
inc esi
copy_new_line:
pop edx
call finish_line
clc
retn
last_line_set:
pop edx
call finish_line
stc
retn
finish_line:
mov eax,SEGMENT_DATA_LENGTH
sub eax,ecx
add eax,[caret_position]
mov [caret_position],eax
mov [edx+8],eax
call register_length
mov al,20h
rep stosb
retn
delete_block:
test [editor_mode],FEMODE_VERTICALSEL
jnz delete_vertical_block
mov eax,[caret_line_number]
cmp eax,[selection_line_number]
je delete_vertical_block
mov esi,[caret_line]
mov ecx,[caret_line_number]
mov edx,[caret_position]
cmp ecx,[selection_line_number]
jbe position_for_deleting_ok
xchg esi,[selection_line]
xchg ecx,[selection_line_number]
xchg edx,[selection_position]
mov [caret_line],esi
mov [caret_line_number],ecx
mov [caret_position],edx
position_for_deleting_ok:
test [editor_mode],FEMODE_OVERWRITE
jnz clear_block
call get_caret_segment
cmp edx,SEGMENT_DATA_LENGTH
jb first_line_of_block
call attach_empty_segments
first_line_of_block:
mov ecx,[caret_position]
sub ecx,edx
skip_rest_of_first_line:
add ecx,SEGMENT_DATA_LENGTH
mov eax,[esi]
btr eax,0
jnc end_of_first_line
mov esi,eax
jmp skip_rest_of_first_line
end_of_first_line:
call store_segment_for_undo
mov edi,esi
mov esi,eax
remove_middle_lines:
cmp esi,[selection_line]
je middle_lines_removed
call store_freed_segment_for_undo
mov ebx,[esi]
call cancel_line
mov esi,ebx
btr esi,0
jnc remove_middle_lines
remove_middle_line_segments:
call store_freed_segment_for_undo
mov esi,[esi]
btr esi,0
jc remove_middle_line_segments
jmp remove_middle_lines
middle_lines_removed:
call store_segment_for_undo
mov eax,esi
or eax,1
mov [edi],eax
mov eax,edi
or eax,1
mov [esi+4],eax
call cancel_line
add ecx,[selection_position]
sub ecx,[caret_position]
call delete_from_line
mov esi,[caret_line]
find_following_line:
mov esi,[esi]
btr esi,0
jc find_following_line
or esi,esi
jz following_line_ok
call store_segment_for_undo
mov eax,[caret_line]
mov [esi+4],eax
following_line_ok:
mov esi,[caret_line]
call check_line_length
block_deleted:
retn
clear_block:
push [caret_line]
push [caret_position]
clear_lines:
call clear_rest_of_line
mov [caret_line],esi
mov [caret_position],0
cmp esi,[selection_line]
jne clear_lines
mov ecx,[selection_position]
call clear_in_line
pop [caret_position]
pop [caret_line]
retn
delete_vertical_block:
push [caret_line]
push [caret_line_number]
mov eax,[caret_position]
cmp eax,[selection_position]
jbe delete_vertical_block_line
xchg eax,[selection_position]
mov [caret_position],eax
delete_vertical_block_line:
mov ecx,[selection_position]
sub ecx,[caret_position]
call delete_from_line
mov esi,[caret_line]
call check_line_length
mov esi,[caret_line]
mov eax,[caret_line_number]
cmp eax,[selection_line_number]
je vertical_block_deleted
ja delete_in_previous_line
delete_in_next_line:
mov esi,[esi]
btr esi,0
jc delete_in_next_line
mov [caret_line],esi
inc [caret_line_number]
jmp delete_vertical_block_line
delete_in_previous_line:
mov esi,[esi+4]
mov [caret_line],esi
dec [caret_line_number]
jmp delete_vertical_block_line
vertical_block_deleted:
pop [caret_line_number]
pop [caret_line]
mov [selection_line],0
retn
get_block_length:
test [editor_mode],FEMODE_VERTICALSEL
jnz get_length_of_vertical_block
mov esi,[caret_line]
mov edx,[caret_position]
mov ebx,[selection_line]
mov ecx,[selection_position]
mov eax,[caret_line_number]
cmp eax,[selection_line_number]
je get_length_of_vertical_block
jb get_length_of_standard_block
xchg esi,ebx
xchg ecx,edx
get_length_of_standard_block:
push ecx
mov ecx,[esi+8]
sub ecx,edx
jae add_length_of_line
xor ecx,ecx
add_length_of_line:
add ecx,2
add [esp],ecx
skip_standard_block_line:
mov esi,[esi]
btr esi,0
jc skip_standard_block_line
cmp esi,ebx
je length_of_block_ok
mov ecx,[esi+8]
jmp add_length_of_line
length_of_block_ok:
pop ecx
retn
get_length_of_vertical_block:
mov edx,[caret_line_number]
sub edx,[selection_line_number]
jae vertical_dimension_ok
neg edx
vertical_dimension_ok:
mov eax,[caret_position]
sub eax,[selection_position]
jae horizontal_dimension_ok
neg eax
horizontal_dimension_ok:
mov ecx,eax
add eax,2
mul edx
add ecx,eax
retn
copy_block:
test [editor_mode],FEMODE_VERTICALSEL
jnz copy_vertical_block
mov esi,[caret_line]
mov edx,[caret_position]
mov ebx,[selection_line]
mov ecx,[selection_position]
mov eax,[caret_line_number]
cmp eax,[selection_line_number]
je copy_vertical_block
jb copy_standard_block
xchg esi,ebx
xchg ecx,edx
copy_standard_block:
push ecx
push ebx
mov ecx,[esi+8]
sub ecx,edx
jb after_line_end
call copy_from_line
jmp block_line_copied
after_line_end:
mov esi,[esi]
btr esi,0
jc after_line_end
block_line_copied:
pop ebx
copy_next_line:
mov ax,0A0Dh
stosw
cmp esi,ebx
je copy_from_last_line
push ebx
mov ecx,[esi+8]
xor edx,edx
call copy_from_line
pop ebx
jmp copy_next_line
copy_from_last_line:
pop ecx
xor edx,edx
call copy_from_line
xor al,al
stosb
retn
copy_vertical_block:
mov esi,[caret_line]
mov ebx,[selection_line]
mov edx,[caret_position]
mov ecx,[selection_position]
mov eax,[caret_line_number]
cmp eax,[selection_line_number]
jbe vertical_block_starting_line_ok
xchg esi,ebx
vertical_block_starting_line_ok:
cmp edx,ecx
jbe vertical_block_starting_position_ok
xchg edx,ecx
vertical_block_starting_position_ok:
sub ecx,edx
copy_line_from_vertical_block:
mov eax,ebx
sub eax,esi
push eax ebx ecx edx
call copy_from_line
pop edx ecx ebx eax
or eax,eax
jz vertical_block_copied
mov ax,0A0Dh
stosw
jmp copy_line_from_vertical_block
vertical_block_copied:
xor al,al
stosb
retn
copy_from_line:
mov ebx,ecx
find_copying_origin:
cmp edx,SEGMENT_DATA_LENGTH
jb copy_line_segment
mov esi,[esi]
btr esi,0
jnc line_data_ended
sub edx,SEGMENT_DATA_LENGTH
jmp find_copying_origin
copy_line_segment:
mov ecx,SEGMENT_DATA_LENGTH
sub ecx,edx
cmp ebx,ecx
jae line_segment_length_ok
mov ecx,ebx
line_segment_length_ok:
sub ebx,ecx
mov eax,[esi]
lea esi,[esi+SEGMENT_HEADER_LENGTH+edx]
rep movsb
mov esi,eax
btr esi,0
jnc line_data_ended
xor edx,edx
jmp copy_line_segment
line_data_ended:
or ebx,ebx
jz line_copy_done
mov ecx,ebx
mov al,20h
rep stosb
line_copy_done:
retn

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,467 @@
; flat assembler interface for Win32 IDE
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
flat_assembler:
mov [initial_definitions],0
mov edx,[esp+4]
invoke GetFullPathName,edx,1000h,path_buffer,param_buffer
or eax,eax
jz exit_program
mov esi,path_buffer
mov [input_file],esi
mov [symbols_file],0
test [command_flags],2
jz symbols_file_name_ok
mov edi,path_buffer+1000h
mov [symbols_file],edi
mov ecx,eax
rep movsb
mov ecx,eax
xor al,al
stosb
sub edi,2
mov ebx,edi
mov al,'.'
std
repne scasb
cld
je attach_fas_extension
mov edi,ebx
attach_fas_extension:
inc edi
mov eax,'.fas'
stosd
xor al,al
stosb
symbols_file_name_ok:
mov [hfile],0
invoke GlobalAlloc,GMEM_MOVEABLE,1
mov [hmem_display],eax
invoke GlobalLock,[hmem_display]
mov byte [eax],0
invoke GlobalUnlock,[hmem_display]
mov [display_size],1
mov [error_data_size],0
mov [allocated_memory],0
mov eax,[compiler_memory]
shl eax,10
jz out_of_memory
allocate_memory:
mov edx,eax
shr edx,2
mov ecx,eax
sub ecx,edx
mov [memory_end],ecx
mov [additional_memory_end],edx
invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE
or eax,eax
jnz memory_allocated
mov eax,[additional_memory_end]
shl eax,1
cmp eax,4000h
jb out_of_memory
jmp allocate_memory
memory_allocated:
mov [allocated_memory],eax
mov [memory_start],eax
mov [code_start],eax
add eax,[memory_end]
mov [memory_end],eax
mov [additional_memory],eax
add [additional_memory_end],eax
mov [tagged_blocks],0
mov eax,esp
and eax,not 0FFFh
add eax,1000h-10000h
mov [stack_limit],eax
invoke PostMessage,[hwnd_progress],PBM_SETPOS,0,0
invoke SetThreadPriority,[hthread],[compiler_priority]
invoke GetTickCount
mov [start_time],eax
mov [preprocessing_done],0
call preprocessor
invoke PostMessage,[hwnd_progress],PBM_SETPOS,1,0
or [preprocessing_done],-1
call parser
invoke PostMessage,[hwnd_progress],PBM_SETPOS,2,0
call assembler
invoke PostMessage,[hwnd_progress],PBM_SETPOS,3,0
call formatter
invoke PostMessage,[hwnd_progress],PBM_SETPOS,4,0
call show_display_buffer
invoke GetTickCount
sub eax,[start_time]
mov [total_time],eax
mov esi,[output_file]
mov edi,path_buffer
copy_executable_name:
lodsb
stosb
or al,al
jnz copy_executable_name
xor al,al
exit_program:
movzx eax,al
push eax
mov eax,[allocated_memory]
or eax,eax
jz memory_ok
invoke VirtualFree,eax,0,MEM_RELEASE
mov [allocated_memory],0
memory_ok:
mov eax,[hfile]
or eax,eax
jz handle_ok
invoke CloseHandle,eax
handle_ok:
invoke PostMessage,[hwnd_compiler],WM_COMMAND,IDOK,0
call [ExitThread]
get_environment_variable:
invoke GetEnvironmentVariable,esi,string_buffer,1000h
mov ecx,[memory_end]
sub ecx,edi
cmp ecx,1000h
jbe get_local_variable
mov ecx,1000h
get_local_variable:
invoke GetPrivateProfileString,_section_environment,esi,string_buffer,edi,ecx,ini_path
add edi,eax
cmp edi,[memory_end]
jae out_of_memory
retn
open:
mov ebx,edx
invoke WaitForSingleObject,[mutex],-1
invoke CreateFile,ebx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
cmp eax,-1
je file_error
mov [hfile],eax
mov ebx,eax
clc
retn
file_error:
stc
retn
create:
mov ebx,edx
invoke WaitForSingleObject,[mutex],-1
invoke CreateFile,ebx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
cmp eax,-1
je file_error
mov ebx,eax
clc
retn
write:
invoke WriteFile,ebx,edx,ecx,bytes_count,0
or eax,eax
jz file_error
clc
retn
read:
mov ebp,ecx
invoke ReadFile,ebx,edx,ecx,bytes_count,0
or eax,eax
jz file_error
cmp ebp,[bytes_count]
jne file_error
clc
retn
close:
cmp ebx,[hfile]
jne close_handle
mov [hfile],0
close_handle:
invoke CloseHandle,ebx
invoke ReleaseMutex,[mutex]
retn
lseek:
movzx eax,al
invoke SetFilePointer,ebx,edx,0,eax
cmp eax,-1
je file_error
clc
retn
display_block:
push edi
push ecx
add ecx,[display_size]
invoke GlobalReAlloc,[hmem_display],ecx,GMEM_MOVEABLE
or eax,eax
jz out_of_memory
mov [hmem_display],eax
invoke GlobalLock,[hmem_display]
add eax,[display_size]
lea edi,[eax-1]
pop ecx
add [display_size],ecx
rep movsb
xor al,al
stosb
invoke GlobalUnlock,[hmem_display]
pop edi
retn
fatal_error:
cmp [hthread],0
je error_outside_compiler
pop [error_message]
error_with_no_source:
mov al,0FFh
jmp exit_program
assembler_error:
cmp [hthread],0
je error_outside_compiler
call show_display_buffer
pop [error_message]
mov ebx,[current_line]
test ebx,ebx
jz error_with_no_source
xor ecx,ecx
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
test byte [ebx+7],80h
jz error_lines_ok
inc ecx
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
mov eax,[edx+4]
and eax,7FFFFFFFh
push eax
mov edx,[edx]
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
error_lines_ok:
inc ecx
mov eax,[ebx+4]
and eax,7FFFFFFFh
push eax
mov edx,[ebx]
push edx
mov ebx,ecx
inc ecx
shl ecx,3
mov [error_data_size],ecx
invoke GlobalAlloc,GMEM_MOVEABLE,ecx
mov [hmem_error_data],eax
invoke GlobalLock,[hmem_error_data]
mov [eax],ebx
invoke GlobalUnlock,[hmem_error_data]
xor ebx,ebx
store_error_lines:
pop edx
invoke GetFullPathName,edx,1000h,path_buffer,param_buffer
inc eax
mov esi,eax
add eax,[error_data_size]
invoke GlobalReAlloc,[hmem_error_data],eax,GMEM_MOVEABLE
invoke GlobalLock,[hmem_error_data]
mov edi,eax
add edi,[error_data_size]
mov ecx,esi
mov esi,path_buffer
rep movsb
pop edx
mov [eax+8+ebx*8+4],edx
sub edi,eax
xchg [error_data_size],edi
mov [eax+8+ebx*8],edi
mov esi,[eax]
invoke GlobalUnlock,[hmem_error_data]
inc ebx
cmp ebx,esi
jb store_error_lines
mov edi,[additional_memory]
cmp [preprocessing_done],0
jne error_in_preprocessed
xor al,al
stosb
jmp instruction_converted
error_in_preprocessed:
mov esi,[current_line]
add esi,16
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je ignore_preprocessor_symbols
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_instruction
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_instruction
ignore_preprocessor_symbols:
xor al,al
stosb
instruction_converted:
sub edi,[additional_memory]
mov ebx,[error_data_size]
lea eax,[ebx+edi]
invoke GlobalReAlloc,[hmem_error_data],eax,GMEM_MOVEABLE
invoke GlobalLock,[hmem_error_data]
mov ecx,edi
mov [eax+4],ebx
lea edi,[eax+ebx]
mov esi,[additional_memory]
rep movsb
invoke GlobalUnlock,[hmem_error_data]
mov al,2
jmp exit_program
error_outside_compiler:
mov esp,[resume_esp]
jmp [resume_eip]
make_timestamp:
invoke GetSystemTime,systime
movzx ecx,[systime.wYear]
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,[systime.wMonth]
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
jbe day_correction_ok
sub ebp,2
movzx ecx,word [systime.wYear]
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:
movzx eax,[systime.wDay]
dec eax
add eax,ebp
mov ebx,24
mul ebx
movzx ecx,[systime.wHour]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,[systime.wMinute]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,[systime.wSecond]
add eax,ecx
adc edx,0
retn
include '..\..\errors.inc'
include '..\..\symbdump.inc'
include '..\..\preproce.inc'
include '..\..\parser.inc'
include '..\..\exprpars.inc'
include '..\..\assemble.inc'
include '..\..\exprcalc.inc'
include '..\..\formats.inc'
include '..\..\x86_64.inc'
include '..\..\avx.inc'
include '..\..\tables.inc'
include '..\..\messages.inc'
section '.bss' readable writeable
include '..\..\variable.inc'
allocated_memory dd ?
start_time dd ?
total_time dd ?
display_size dd ?
error_message dd ?
error_data_size dd ?
preprocessing_done db ?

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
; flat editor mode flags
FEMODE_OVERWRITE = 1
FEMODE_VERTICALSEL = 2
FEMODE_NOUNDO = 4
FEMODE_READONLY = 8
; flat editor search flags
FEFIND_CASESENSITIVE = 1
FEFIND_WHOLEWORDS = 2
FEFIND_BACKWARD = 4
FEFIND_INWHOLETEXT = 8
; flat editor styles
FES_AUTOINDENT = 0001h
FES_AUTOBRACKETS = 0002h
FES_SMARTTABS = 0004h
FES_SECURESEL = 0008h
FES_OPTIMALFILL = 0010h
FES_CONSOLECARET = 0020h
FES_REVIVEDEADKEYS = 0040h
FES_TIMESCROLL = 0080h
; flat editor messages
FEM_SETMODE = WM_USER + 0
FEM_GETMODE = WM_USER + 1
FEM_SETPOS = WM_USER + 2
FEM_GETPOS = WM_USER + 3
FEM_SETSYNTAXHIGHLIGHT = WM_USER + 4
FEM_SETRIGHTCLICKMENU = WM_USER + 5
FEM_SETTEXTCOLOR = WM_USER + 6
FEM_SETSELCOLOR = WM_USER + 7
FEM_FINDFIRST = WM_USER + 8
FEM_FINDNEXT = WM_USER + 9
FEM_CANFINDNEXT = WM_USER + 10
FEM_GETLINELENGTH = WM_USER + 11
FEM_GETLINE = WM_USER + 12
FEM_GETWORDATCARET = WM_USER + 13
FEM_BEGINOPERATION = WM_USER + 14
FEM_ENDOPERATION = WM_USER + 15
FEM_MARKUNMODIFIED = WM_USER + 16
FEM_ISUNMODIFIED = WM_USER + 17
FEM_GETSEARCHTEXT = WM_USER + 18
FEM_GETSEARCHFLAGS = WM_USER + 19
FEM_RELEASESEARCH = WM_USER + 20
FEM_REDO = WM_USER + 84
FEM_CANREDO = WM_USER + 85
; flat editor notifications
FEN_SETFOCUS = 01h
FEN_KILLFOCUS = 02h
FEN_TEXTCHANGE = 03h
FEN_POSCHANGE = 04h
FEN_MODECHANGE = 05h
FEN_OUTOFMEMORY = 0Fh
; flat editor position structure
struct FEPOS
selectionPosition dd ?
selectionLine dd ?
caretPosition dd ?
caretLine dd ?
ends

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@ -0,0 +1,199 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
init_editor_memory:
mov ecx,BLOCK_LENGTH
call get_memory
or eax,eax
jz memory_error
mov [editor_memory],eax
mov dword [eax],0
mov dword [eax+4],0
mov dword [eax+8],ebx
lea ebx,[eax+SEGMENT_LENGTH]
mov [unallocated_segments],ebx
mov [memory_search_segment],ebx
add eax,BLOCK_LENGTH
mov [unallocated_segments_end],eax
mov [memory_search_block],eax
mov [released_segments],0
call allocate_segment
mov [first_line],eax
mov [lines_count],1
mov [peak_line_length],0
mov [caret_line],eax
mov [caret_line_number],1
mov [window_line],eax
mov [window_line_number],1
mov edi,eax
xor eax,eax
mov ecx,SEGMENT_HEADER_LENGTH shr 2
rep stosd
mov eax,20202020h
mov ecx,SEGMENT_DATA_LENGTH shr 2
rep stosd
call allocate_segment
jc memory_shortage
mov [lengths_table],eax
mov edi,eax
xor eax,eax
mov ecx,SEGMENT_LENGTH shr 2
rep stosd
mov [caret_position],eax
mov [window_position],eax
mov [selection_line],eax
mov [undo_data],eax
mov [redo_data],eax
mov [search_data],eax
mov [editor_mode],eax
mov [unmodified_state],eax
clc
retn
memory_error:
stc
retn
reset_editor_memory:
mov esi,[editor_memory]
lea eax,[esi+SEGMENT_LENGTH]
mov [unallocated_segments],eax
mov [memory_search_segment],eax
lea eax,[esi+BLOCK_LENGTH]
mov [unallocated_segments_end],eax
mov [memory_search_block],eax
mov [released_segments],0
mov ebx,[esi]
release_blocks:
or ebx,ebx
jz release_done
push dword [ebx]
mov ebx,[ebx+8]
call release_memory
pop ebx
jmp release_blocks
release_done:
mov ebx,[editor_memory]
xor eax,eax
mov [ebx],eax
mov [undo_data],eax
mov [redo_data],eax
mov [search_data],eax
call allocate_segment
jc memory_shortage
mov [first_line],eax
mov [window_line],eax
mov [caret_line],eax
mov edi,eax
xor eax,eax
mov ecx,SEGMENT_HEADER_LENGTH shr 2
rep stosd
mov eax,20202020h
mov ecx,SEGMENT_DATA_LENGTH shr 2
rep stosd
xor eax,eax
mov [selection_line],eax
mov [peak_line_length],eax
mov [window_position],eax
inc eax
mov [window_line_number],eax
mov [caret_line_number],eax
mov [lines_count],eax
call allocate_segment
jc memory_shortage
mov [lengths_table],eax
mov edi,eax
xor eax,eax
mov ecx,SEGMENT_LENGTH shr 2
rep stosd
retn
release_editor_memory:
mov esi,[editor_memory]
release:
push dword [esi]
mov ebx,[esi+8]
call release_memory
pop esi
or esi,esi
jnz release
mov [editor_memory],0
retn
allocate_segment:
mov eax,[unallocated_segments]
cmp eax,[unallocated_segments_end]
je simple_allocation_failed
add [unallocated_segments],SEGMENT_LENGTH
clc
retn
simple_allocation_failed:
push ebx esi
mov ebx,[memory_search_block]
mov esi,[memory_search_segment]
cmp [released_segments],16
jb add_new_block
find_free_segment:
cmp esi,ebx
je find_in_next_block
cmp dword [esi],-1
je reuse_segment
add esi,SEGMENT_LENGTH
cmp esi,[memory_search_segment]
jne find_free_segment
add_new_block:
sub ebx,BLOCK_LENGTH
find_last_memory_block:
cmp dword [ebx],0
je allocate_more_memory
mov ebx,[ebx]
jmp find_last_memory_block
allocate_more_memory:
mov ecx,BLOCK_LENGTH
push ebx
call get_memory
pop esi
or eax,eax
jz allocation_failed
mov [esi],eax
mov dword [eax],0
mov [eax+4],esi
mov [eax+8],ebx
lea ebx,[eax+BLOCK_LENGTH]
mov [unallocated_segments_end],ebx
add eax,SEGMENT_LENGTH
lea ebx,[eax+SEGMENT_LENGTH]
mov [unallocated_segments],ebx
mov [released_segments],0
pop esi ebx
clc
retn
allocation_failed:
xor eax,eax
pop esi ebx
stc
retn
reuse_segment:
mov eax,esi
mov [memory_search_block],ebx
add esi,SEGMENT_LENGTH
mov [memory_search_segment],esi
dec [released_segments]
pop esi ebx
clc
retn
find_in_next_block:
sub ebx,BLOCK_LENGTH
mov esi,[ebx]
lea ebx,[esi+BLOCK_LENGTH]
or esi,esi
jnz find_free_segment
mov ebx,[editor_memory]
mov esi,ebx
add ebx,BLOCK_LENGTH
jmp find_free_segment
memory_shortage:
call undo_changes
jmp not_enough_memory

View File

@ -0,0 +1,511 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
find_line:
mov esi,[first_line]
mov ecx,1
mov edx,[window_line_number]
cmp eax,edx
jae forward_from_window
sub edx,eax
cmp edx,eax
jb backward_from_window
jmp find_forward
forward_from_window:
mov esi,[window_line]
mov ecx,edx
find_forward:
cmp ecx,eax
je line_found
cmp dword [esi],0
je line_found
mov ebx,esi
forward_skip_line:
mov ebx,[ebx]
btr ebx,0
jc forward_skip_line
or ebx,ebx
jz line_found
mov esi,ebx
inc ecx
jmp find_forward
backward_from_window:
mov esi,[window_line]
mov ecx,[window_line_number]
find_backward:
cmp ecx,eax
je line_found
cmp dword [esi+4],0
je line_found
mov esi,[esi+4]
dec ecx
jmp find_backward
line_found:
retn
get_caret_segment:
mov edx,[caret_position]
mov esi,[caret_line]
find_segment:
cmp edx,SEGMENT_DATA_LENGTH
jb segment_found
test byte [esi],1
jz segment_found
mov esi,[esi]
dec esi
sub edx,SEGMENT_DATA_LENGTH
jmp find_segment
segment_found:
retn
check_line_length:
xor edx,edx
mov ebx,esi
count_line_segments:
test byte [esi],1
jz last_line_segment
mov esi,[esi]
dec esi
add edx,SEGMENT_DATA_LENGTH
jmp count_line_segments
last_line_segment:
lea edi,[esi+SEGMENT_LENGTH-1]
mov al,20h
mov ecx,SEGMENT_DATA_LENGTH
std
repe scasb
cld
setne al
movzx eax,al
add ecx,eax
jnz line_segments_ok
or edx,edx
jz line_segments_ok
call store_freed_segment_for_undo
mov eax,[esi]
mov esi,[esi+4]
dec esi
call store_segment_for_undo
mov [esi],eax
sub edx,SEGMENT_DATA_LENGTH
jmp last_line_segment
line_segments_ok:
add ecx,edx
mov edx,ecx
cmp edx,[ebx+8]
je line_length_checked
mov esi,ebx
call store_segment_for_undo
xchg [ebx+8],edx
push edx
mov eax,[ebx+8]
call register_length
pop eax
call unregister_length
line_length_checked:
retn
register_length:
cmp eax,[peak_line_length]
jbe peak_length_ok
mov [peak_line_length],eax
peak_length_ok:
or eax,eax
jz ignore_zero_length
push ebx
call find_lengths_segment
inc dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
pop ebx
ignore_zero_length:
retn
find_lengths_segment:
mov ebx,[lengths_table]
try_lengths_segment:
cmp eax,SEGMENT_DATA_LENGTH/4
jb length_entry_ok
sub eax,SEGMENT_DATA_LENGTH/4
cmp dword [ebx],0
je add_lengths_segment
mov ebx,[ebx]
jmp try_lengths_segment
add_lengths_segment:
push eax ecx edi
call allocate_segment
jc memory_shortage
call store_allocated_segment_for_undo
mov [ebx],eax
mov edi,eax
xor eax,eax
stosd
mov eax,ebx
stosd
mov eax,[ebx+8]
add eax,SEGMENT_DATA_LENGTH/4
stosd
add edi,SEGMENT_HEADER_LENGTH-12
mov ecx,SEGMENT_DATA_LENGTH shr 2
xor eax,eax
rep stosd
lea ebx,[edi-SEGMENT_LENGTH]
pop edi ecx eax
jmp try_lengths_segment
length_entry_ok:
retn
unregister_length:
or eax,eax
jz ignore_zero_length
push ebx
cmp eax,[peak_line_length]
je unregister_peak_length
call find_lengths_segment
dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
length_unregistered:
pop ebx
retn
unregister_peak_length:
call find_lengths_segment
dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
jnz length_unregistered
find_reduced_peak:
or eax,eax
jz try_earlier_lengths_segment
dec eax
cmp dword [ebx+SEGMENT_HEADER_LENGTH+eax*4],0
je find_reduced_peak
add eax,[ebx+8]
mov [peak_line_length],eax
jmp length_unregistered
try_earlier_lengths_segment:
mov ebx,[ebx+4]
mov eax,SEGMENT_DATA_LENGTH/4
or ebx,ebx
jnz find_reduced_peak
mov [peak_line_length],ebx
jmp length_unregistered
update_window:
mov edx,[window_line_number]
cmp edx,1
je window_vertical_position_ok
add edx,[window_height]
dec edx
cmp edx,[lines_count]
jle window_vertical_position_ok
sub edx,[lines_count]
window_vertical_correction:
mov esi,[window_line]
mov esi,[esi+4]
or esi,esi
jz window_vertical_position_ok
mov [window_line],esi
dec [window_line_number]
dec edx
jnz window_vertical_correction
window_vertical_position_ok:
mov ecx,[peak_line_length]
cmp ecx,[caret_position]
jae caret_position_ok
mov ecx,[caret_position]
caret_position_ok:
cmp [selection_line],0
je selection_position_ok
cmp ecx,[selection_position]
jae selection_position_ok
mov ecx,[selection_position]
selection_position_ok:
mov eax,[window_width]
dec eax
cmp ecx,eax
jae edit_space_width_ok
mov ecx,eax
edit_space_width_ok:
mov [maximum_position],ecx
mov edx,[window_position]
or edx,edx
jz window_horizontal_position_ok
add edx,[window_width]
inc ecx
cmp edx,ecx
jbe window_horizontal_position_ok
sub edx,ecx
sub [window_position],edx
jnc window_horizontal_position_ok
mov [window_position],0
window_horizontal_position_ok:
retn
let_caret_appear:
mov eax,[caret_position]
cmp eax,[window_position]
jl horizontal_correction
mov ecx,[window_width]
jecxz last_position_ok
dec ecx
last_position_ok:
add ecx,[window_position]
mov eax,[caret_position]
sub eax,ecx
jbe horizontal_ok
add eax,[window_position]
horizontal_correction:
mov [window_position],eax
horizontal_ok:
mov esi,[caret_line]
mov ecx,[caret_line_number]
cmp ecx,[window_line_number]
jl vertical_correction
mov eax,[window_height]
or eax,eax
jz vertical_check
dec eax
vertical_check:
neg eax
add eax,[caret_line_number]
cmp [window_line_number],eax
jge vertical_ok
mov esi,[window_line]
mov ecx,[window_line_number]
vertical_find:
mov esi,[esi]
btr esi,0
jc vertical_find
inc ecx
cmp ecx,eax
jl vertical_find
vertical_correction:
mov [window_line],esi
mov [window_line_number],ecx
vertical_ok:
retn
move_line_up:
mov esi,[caret_line]
mov eax,[esi+4]
or eax,eax
jz cannot_move
mov [caret_line],eax
dec [caret_line_number]
clc
retn
cannot_move:
stc
retn
move_line_down:
mov esi,[caret_line]
find_next_line:
mov eax,[esi]
or eax,eax
jz cannot_move
btr eax,0
jnc down_ok
mov esi,eax
jmp find_next_line
down_ok:
mov [caret_line],eax
inc [caret_line_number]
clc
retn
move_page_up:
mov eax,[caret_line_number]
sub eax,[window_height]
ja pgup_caret_ok
mov eax,1
pgup_caret_ok:
call find_line
mov [caret_line],esi
mov [caret_line_number],ecx
mov eax,[window_line_number]
sub eax,[window_height]
ja pgup_window_ok
mov eax,1
cmp [window_line_number],eax
je moved_ok
pgup_window_ok:
call find_line
mov [window_line],esi
mov [window_line_number],ecx
retn
move_page_down:
mov eax,[caret_line_number]
add eax,[window_height]
call find_line
mov [caret_line],esi
mov [caret_line_number],ecx
mov eax,[window_line_number]
mov ecx,[window_height]
add eax,ecx
mov ebx,[lines_count]
sub ebx,ecx
jbe moved_ok
inc ebx
cmp eax,ebx
jb pgdn_window_ok
mov eax,ebx
cmp [window_line_number],eax
je moved_ok
pgdn_window_ok:
call find_line
mov [window_line],esi
mov [window_line_number],ecx
moved_ok:
retn
move_to_previous_word:
call get_caret_segment
mov ecx,[caret_position]
sub ecx,edx
cmp edx,SEGMENT_DATA_LENGTH
jbe find_word_to_the_left
mov edx,SEGMENT_DATA_LENGTH
find_word_to_the_left:
sub edx,1
jc word_in_previous_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc find_word_start
jmp find_word_to_the_left
word_in_previous_segment:
mov eax,[esi+4]
or eax,eax
jz previous_word_ok
mov esi,eax
btr esi,0
jnc word_in_previous_line
mov edx,SEGMENT_DATA_LENGTH
sub ecx,edx
jmp find_word_to_the_left
word_in_previous_line:
mov [caret_line],esi
dec [caret_line_number]
mov edx,SEGMENT_DATA_LENGTH
xor ecx,ecx
find_last_segment:
test byte [esi],1
jz find_word_to_the_left
mov esi,[esi]
dec esi
add ecx,SEGMENT_DATA_LENGTH
jmp find_last_segment
find_word_start:
sub edx,1
jc word_on_segment_edge
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc previous_word_ok
jmp find_word_start
word_on_segment_edge:
mov esi,[esi+4]
btr esi,0
jnc previous_word_ok
mov edx,SEGMENT_DATA_LENGTH
sub ecx,edx
jmp find_word_start
previous_word_ok:
add ecx,edx
inc ecx
mov [caret_position],ecx
retn
move_to_next_word:
mov ecx,[caret_position]
sub ecx,edx
find_word_end:
cmp edx,SEGMENT_DATA_LENGTH
jae word_wraps_segment_edge
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc find_word_to_the_right
add edx,1
jmp find_word_end
word_wraps_segment_edge:
mov esi,[esi]
or esi,esi
jz move_to_line_end
btr esi,0
jnc word_in_next_line
add ecx,SEGMENT_DATA_LENGTH
sub edx,SEGMENT_DATA_LENGTH
jmp find_word_end
find_word_to_the_right:
cmp edx,SEGMENT_DATA_LENGTH
jae word_in_next_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc next_word_ok
add edx,1
jmp find_word_to_the_right
word_in_next_segment:
mov esi,[esi]
or esi,esi
jz move_to_line_end
btr esi,0
jnc word_in_next_line
add ecx,SEGMENT_DATA_LENGTH
sub edx,SEGMENT_DATA_LENGTH
jmp find_word_to_the_right
word_in_next_line:
mov [caret_line],esi
inc [caret_line_number]
xor ecx,ecx
xor edx,edx
jmp find_word_to_the_right
next_word_ok:
add ecx,edx
mov [caret_position],ecx
retn
move_to_line_end:
mov esi,[caret_line]
mov eax,[esi+8]
mov [caret_position],eax
retn
get_word_at_caret:
call get_caret_segment
mov ebx,[caret_position]
sub ebx,edx
find_left_edge:
or edx,edx
jz left_edge_in_previous_segment
cmp edx,SEGMENT_DATA_LENGTH
ja left_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx-1]
call recognize_character
jc left_edge_ok
dec edx
jmp find_left_edge
left_edge_in_previous_segment:
mov esi,[esi+4]
btr esi,0
jnc left_edge_ok
mov edx,SEGMENT_DATA_LENGTH
sub ebx,edx
jmp find_left_edge
left_edge_ok:
add ebx,edx
call get_caret_segment
mov ecx,[caret_position]
sub ecx,edx
find_right_edge:
cmp edx,SEGMENT_DATA_LENGTH
jae right_edge_in_next_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc right_edge_ok
inc edx
jmp find_right_edge
right_edge_in_next_segment:
mov esi,[esi]
btr esi,0
jnc right_edge_ok
xor edx,edx
add ecx,SEGMENT_DATA_LENGTH
jmp find_right_edge
right_edge_ok:
add ecx,edx
sub ecx,ebx
mov edx,ebx
retn

View File

@ -0,0 +1,529 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
find_first:
mov [search_flags],eax
call release_search_data
or esi,esi
jz nothing_to_search_for
mov edi,esi
xor al,al
xor ecx,ecx
sub ecx,edi
repne scasb
lea ebx,[edi-1]
sub ebx,esi
jz nothing_to_search_for
lea ecx,[(256+ebx)*4+ebx]
push ebx
call get_memory
or eax,eax
jz not_enough_memory
mov [search_data],eax
mov [search_handle],ebx
pop ebx
mov edi,eax
lea ecx,[256+ebx]
mov eax,ebx
rep stosd
mov ecx,ebx
mov ebx,[search_data]
mov edx,ecx
test [search_flags],FEFIND_BACKWARD
jnz text_for_backward_search
test [search_flags],FEFIND_CASESENSITIVE
jnz copy_search_text
push ebx
mov ebx,upper_case_table
convert_search_text:
lodsb
xlatb
stosb
loop convert_search_text
pop ebx
jmp make_character_shifts_table
copy_search_text:
rep movsb
jmp make_character_shifts_table
text_for_backward_search:
add edi,ecx
mov edx,ecx
push ebx
mov ebx,upper_case_table
reverse_search_text:
lodsb
test [search_flags],FEFIND_CASESENSITIVE
jnz reverse_store_character
xlatb
reverse_store_character:
dec edi
mov [edi],al
dec ecx
jnz reverse_search_text
pop ebx
add edi,edx
xor ecx,ecx
make_character_shifts_table:
cmp edx,ecx
je character_shifts_table_ok
dec edi
jecxz character_shift_ok
mov al,[edi]
cmp [ebx+eax*4],edx
jne character_shift_ok
mov [ebx+eax*4],ecx
character_shift_ok:
inc ecx
jmp make_character_shifts_table
character_shifts_table_ok:
lea edi,[ebx+(256+ecx)*4]
push edi
lea edi,[edi+ecx-2]
movzx eax,byte [edi+1]
mov edx,[ebx+eax*4]
mov [ebx+256*4],edx
cmp ecx,1
je suffix_match_shifts_table_done
mov ecx,2
mov esi,edi
sub esi,edx
make_suffix_match_shifts_table:
cmp esi,[esp]
jb store_suffix_match_shift
mov al,[esi]
cmp al,[edi]
je store_suffix_match_shift
find_suffix_match:
dec esi
inc edx
cmp esi,[esp]
jb match_part_of_suffix
push ecx esi edi
repe cmpsb
pop edi esi ecx
jne find_suffix_match
jmp store_suffix_match_shift
match_part_of_suffix:
mov eax,[esp]
push ecx esi edi
xchg eax,esi
sub eax,esi
add ecx,eax
repe cmpsb
pop edi esi ecx
jne suffix_match_shifts_table_done
store_suffix_match_shift:
mov [ebx+256*4+(ecx-1)*4],edx
dec esi
dec edi
inc ecx
cmp ecx,[ebx]
jbe make_suffix_match_shifts_table
suffix_match_shifts_table_done:
pop eax
find_next:
mov edi,[search_data]
or edi,edi
jz nothing_to_search_for
push [caret_line]
push [caret_line_number]
push [caret_position]
push [selection_position]
test [search_flags],FEFIND_BACKWARD
jnz search_backward
test [search_flags],FEFIND_INWHOLETEXT
jz search_for_text
mov eax,[first_line]
mov [caret_line],eax
xor eax,eax
mov [caret_position],eax
inc eax
mov [caret_line_number],eax
search_for_text:
mov ecx,[edi]
dec ecx
add ecx,[caret_position]
mov esi,[caret_line]
cmp ecx,[peak_line_length]
jae text_not_in_this_line
mov [caret_position],ecx
call get_caret_segment
mov edi,[search_data]
mov eax,[edi]
lea ebx,[edi+(256+eax)*4]
mov ah,[ebx+eax-1]
mov ebx,upper_case_table
search_in_line:
cmp edx,SEGMENT_DATA_LENGTH
jae text_not_in_this_line
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
test [search_flags],FEFIND_CASESENSITIVE
jnz compare_last_character
xlatb
compare_last_character:
cmp al,ah
je partial_match
mismatch_shift:
movzx ecx,al
mov ecx,[edi+ecx*4]
shift_search_position:
add edx,ecx
add ecx,[caret_position]
cmp ecx,[peak_line_length]
jae text_not_in_this_line
mov [caret_position],ecx
check_search_position:
cmp edx,SEGMENT_DATA_LENGTH
jb search_in_line
mov ecx,[esi]
btr ecx,0
jnc search_in_line
sub edx,SEGMENT_DATA_LENGTH
mov esi,ecx
jmp check_search_position
partial_match:
mov ecx,[edi]
dec ecx
jz text_found
push edi
lea edi,[edi+(256+ecx+1)*4]
lea edi,[edi+ecx]
compare_text:
sub edx,1
jc compare_in_previous_segment
dec edi
mov al,20h
cmp edx,SEGMENT_DATA_LENGTH
jae compare_character
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
test [search_flags],FEFIND_CASESENSITIVE
jnz compare_character
xlatb
compare_character:
cmp al,[edi]
loope compare_text
pop edi
je text_found
neg ecx
add ecx,[edi]
dec ecx
add edx,ecx
mov ecx,[edi+(256+ecx-1)*4]
jmp shift_search_position
compare_in_previous_segment:
mov esi,[esi+4]
and esi,not 1
mov edx,SEGMENT_DATA_LENGTH
jmp compare_text
text_not_in_this_line:
mov esi,[esi]
or esi,esi
jz text_not_found
btr esi,0
jc text_not_in_this_line
search_in_next_line:
mov [caret_line],esi
inc [caret_line_number]
mov [caret_position],0
mov edi,[search_data]
jmp search_for_text
text_found:
mov eax,[caret_position]
inc eax
mov [selection_position],eax
sub eax,[edi]
mov [caret_position],eax
jz left_text_edge_ok
test [search_flags],FEFIND_WHOLEWORDS
jz left_text_edge_ok
mov edi,[search_data]
mov ecx,[edi]
mov al,[edi+(256+ecx)*4]
call recognize_character
jc left_text_edge_ok
dec [caret_position]
call get_caret_segment
inc [caret_position]
cmp edx,SEGMENT_DATA_LENGTH
jae left_text_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc found_not_acceptable
left_text_edge_ok:
mov eax,[caret_position]
xchg eax,[selection_position]
mov [caret_position],eax
mov edi,[search_data]
mov ecx,[edi]
lea edi,[edi+(256+ecx)*4]
mov al,[edi+ecx-1]
cmp al,20h
je right_text_edge_blank
test [search_flags],FEFIND_WHOLEWORDS
jz right_text_edge_ok
call recognize_character
jc right_text_edge_ok
call get_caret_segment
cmp edx,SEGMENT_DATA_LENGTH
jae right_text_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc right_text_edge_ok
mov eax,[selection_position]
mov [caret_position],eax
found_not_acceptable:
mov edi,[search_data]
mov ecx,[edi]
mov eax,[edi+(256+ecx-1)*4]
add [caret_position],eax
jmp search_for_text
right_text_edge_blank:
call get_caret_segment
check_for_blank_end:
mov ecx,SEGMENT_DATA_LENGTH
sub ecx,edx
jz blank_end_next_segment
push edi
mov al,20h
lea edi,[esi+SEGMENT_HEADER_LENGTH+edx]
repe scasb
pop edi
jne right_text_edge_ok
blank_end_next_segment:
mov esi,[esi]
or esi,esi
jz text_not_found
btr esi,0
jnc search_in_next_line
xor edx,edx
jmp check_for_blank_end
right_text_edge_ok:
mov eax,[caret_line]
mov ecx,[caret_line_number]
mov [selection_line],eax
mov [selection_line_number],ecx
and [search_flags],not FEFIND_INWHOLETEXT
add esp,16
clc
retn
text_not_found:
pop [selection_position]
pop [caret_position]
pop [caret_line_number]
pop [caret_line]
nothing_to_search_for:
stc
retn
search_backward:
test [search_flags],FEFIND_INWHOLETEXT
jz backward_search_for_text
or eax,-1
call find_line
mov [caret_line],esi
mov [caret_line_number],ecx
call move_to_line_end
backward_search_for_text:
mov ecx,[caret_position]
sub ecx,1
jc backward_text_not_in_this_line
mov [caret_position],ecx
mov edi,[search_data]
mov eax,[edi]
mov al,[edi+(256+eax)*4]
cmp al,20h
jne backward_search_starting_position_ok
mov esi,[caret_line]
mov ecx,[esi+8]
mov edi,[search_data]
mov eax,[edi]
sub ecx,eax
jc backward_text_not_in_this_line
cmp ecx,[caret_position]
jae backward_search_starting_position_ok
mov [caret_position],ecx
backward_search_starting_position_ok:
call get_caret_segment
mov edi,[search_data]
mov eax,[edi]
lea ebx,[edi+(256+eax)*4]
mov ah,[ebx+eax-1]
mov ebx,upper_case_table
cmp edx,SEGMENT_DATA_LENGTH
jb backward_search_in_line
mov ecx,edx
sub ecx,SEGMENT_DATA_LENGTH-1
sub edx,ecx
sub [caret_position],ecx
backward_search_in_line:
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
test [search_flags],FEFIND_CASESENSITIVE
jnz compare_first_character
xlatb
compare_first_character:
cmp al,ah
je backward_partial_match
backward_mismatch_shift:
movzx ecx,al
mov ecx,[edi+ecx*4]
shift_backward_search_position:
sub edx,ecx
sub [caret_position],ecx
jc backward_text_not_in_this_line
check_backward_search_position:
cmp edx,0
jge backward_search_in_line
mov esi,[esi+4]
and esi,not 1
add edx,SEGMENT_DATA_LENGTH
jmp check_backward_search_position
backward_partial_match:
mov ecx,[edi]
dec ecx
jz backward_text_found
push edi
lea edi,[edi+(256+ecx+1)*4]
lea edi,[edi+ecx]
backward_compare_text:
inc edx
cmp edx,SEGMENT_DATA_LENGTH
jae compare_in_next_segment
dec edi
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
test [search_flags],FEFIND_CASESENSITIVE
jnz backward_compare_character
xlatb
backward_compare_character:
cmp al,[edi]
loope backward_compare_text
pop edi
je backward_text_found
neg ecx
add ecx,[edi]
dec ecx
sub edx,ecx
mov ecx,[edi+(256+ecx)*4]
jmp shift_backward_search_position
compare_in_next_segment:
sub edx,SEGMENT_DATA_LENGTH
mov esi,[esi]
btr esi,0
jnc compare_blank_space
dec edx
jmp backward_compare_text
compare_blank_space:
pop edi
cmp ecx,[edi]
jbe backward_text_found
backward_text_not_in_this_line:
mov esi,[caret_line]
mov esi,[esi+4]
or esi,esi
jz text_not_found
mov [caret_line],esi
dec [caret_line_number]
mov ecx,[peak_line_length]
mov [caret_position],ecx
jmp backward_search_for_text
backward_text_found:
test [search_flags],FEFIND_WHOLEWORDS
jz backward_left_text_edge_ok
cmp [caret_position],0
je backward_left_text_edge_ok
mov edi,[search_data]
mov ecx,[edi]
lea edi,[edi+(256+ecx)*4]
mov al,[edi+ecx-1]
call recognize_character
jc backward_left_text_edge_ok
dec [caret_position]
call get_caret_segment
inc [caret_position]
cmp edx,SEGMENT_DATA_LENGTH
jae backward_left_text_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc backward_found_not_acceptable
backward_left_text_edge_ok:
mov eax,[caret_position]
mov [selection_position],eax
mov edi,[search_data]
mov ecx,[edi]
add eax,ecx
mov [caret_position],eax
test [search_flags],FEFIND_WHOLEWORDS
jz backward_right_text_edge_ok
mov al,[edi+(256+ecx)*4]
call recognize_character
jc backward_right_text_edge_ok
call get_caret_segment
cmp edx,SEGMENT_DATA_LENGTH
jae backward_right_text_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc backward_right_text_edge_ok
mov eax,[selection_position]
mov [caret_position],eax
backward_found_not_acceptable:
mov edi,[search_data]
mov ecx,[edi]
mov eax,[edi+(256+ecx-1)*4]
sub [caret_position],eax
jbe backward_text_not_in_this_line
jmp backward_search_for_text
backward_right_text_edge_ok:
mov eax,[caret_position]
xchg eax,[selection_position]
mov [caret_position],eax
mov eax,[caret_line]
mov ecx,[caret_line_number]
mov [selection_line],eax
mov [selection_line_number],ecx
and [search_flags],not FEFIND_INWHOLETEXT
add esp,16
clc
retn
get_search_text_length:
mov ecx,[search_data]
test ecx,ecx
jz no_search_text
mov ecx,[ecx]
clc
retn
get_search_text:
mov esi,[search_data]
test esi,esi
jz no_search_text
mov ecx,[esi]
lea esi,[esi+(256+ecx)*4]
test [search_flags],FEFIND_BACKWARD
jnz copy_inverted_text
rep movsb
xor al,al
stosb
clc
retn
copy_inverted_text:
mov al,[esi+ecx-1]
stosb
loop copy_inverted_text
xor al,al
stosb
clc
retn
no_search_text:
stc
retn
release_search_data:
mov edi,[search_data]
test edi,edi
jz search_data_released
mov ebx,[search_handle]
call release_memory
mov [search_data],0
search_data_released:
retn

View File

@ -0,0 +1,339 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
store_status_for_undo:
pusha
test [editor_mode],FEMODE_NOUNDO
jnz undo_disabled
call clear_redo_data
call allocate_segment
jc not_enough_memory
mov dword [eax],0
mov edi,eax
xchg eax,[undo_data]
push eax edi
call allocate_segment
pop edi
jnc store_editor_status
xor eax,eax
stosd
jmp not_enough_memory
store_editor_status:
mov dword [eax],0
mov dword [eax+4],0
stosd
pop eax
stosd
lea esi,[editor_status]
mov ecx,editor_status_size shr 2
rep movsd
mov esi,[lengths_table]
store_lengths_table:
call store_segment_for_undo
mov esi,[esi]
or esi,esi
jnz store_lengths_table
popa
store_status_for_undo_ok:
retn
undo_disabled:
call clear_redo_data
call clear_undo_data
or [unmodified_state],-1
popa
retn
store_segment_for_undo:
pusha
or esi,esi
jz segment_for_undo_done
call clear_redo_data
mov esi,[undo_data]
or esi,esi
jz segment_for_undo_done
mov ebx,[esi]
mov eax,[esp+4]
call prepare_slot_for_undo_storage
jc segment_for_undo_done
push edi
call allocate_segment
pop edi
mov ebx,eax
stosd
mov eax,[esp+4]
stosd
jc memory_shortage
mov esi,eax
mov edi,ebx
mov ecx,SEGMENT_LENGTH shr 2
rep movsd
segment_for_undo_done:
popa
store_segment_for_undo_ok:
retn
prepare_slot_for_undo_storage:
mov esi,[undo_data]
mov esi,[esi]
mov ecx,[esi+4]
lea edi,[esi+8]
repne scasd
jne get_free_slot
stc
retn
get_free_slot:
mov ecx,[esi+4]
lea edi,[esi+8+ecx*8]
inc ecx
cmp ecx,SEGMENT_DATA_LENGTH/8
jbe slot_ok
push esi
call allocate_segment
jc memory_shortage
mov esi,eax
mov ebx,[undo_data]
mov [ebx],esi
pop dword [esi]
mov ecx,1
lea edi,[esi+8]
slot_ok:
mov [esi+4],ecx
clc
retn
store_allocated_segment_for_undo:
pusha
call clear_redo_data
mov eax,[esp+1Ch]
xor edx,edx
mov [eax],edx
mov esi,[undo_data]
or esi,esi
jz segment_for_undo_done
call prepare_slot_for_undo_storage
jc segment_for_undo_done
xor eax,eax
stosd
mov eax,[esp+1Ch]
stosd
popa
retn
store_freed_segment_for_undo:
pusha
call clear_redo_data
mov esi,[undo_data]
or esi,esi
jz segment_for_undo_done
call prepare_slot_for_undo_storage
jc segment_for_undo_done
mov eax,[esp+4]
stosd
xor eax,eax
stosd
popa
retn
undo_changes:
mov esi,[undo_data]
or esi,esi
jz undo_ok
mov ebx,[esi]
mov eax,[redo_data]
xchg eax,[esi+4]
mov [undo_data],eax
mov [redo_data],esi
add esi,8
lea edi,[editor_status]
mov ecx,editor_status_size shr 2
call exchange_data
xor edx,edx
segments_block:
or ebx,ebx
jz undo_finished
mov esi,ebx
xchg ebx,edx
xchg ebx,[esi]
add esi,4
lodsd
mov ecx,eax
jecxz undo_finished
lea esi,[esi+ecx*8]
restore_segments:
sub esi,8
push esi ecx
mov edi,[esi+4]
mov esi,[esi]
or edi,edi
jz restore_next
or esi,esi
jz restore_next
mov ecx,SEGMENT_LENGTH shr 2
call exchange_data
restore_next:
pop ecx esi
loop restore_segments
jmp segments_block
undo_finished:
mov esi,[redo_data]
mov [esi],edx
undo_ok:
retn
exchange_data:
mov eax,[esi]
xchg eax,[edi]
mov [esi],eax
add esi,4
add edi,4
loop exchange_data
retn
redo_changes:
mov esi,[redo_data]
or esi,esi
jz redo_ok
mov ebx,[esi]
mov eax,[undo_data]
xchg eax,[esi+4]
mov [redo_data],eax
mov [undo_data],esi
add esi,8
lea edi,[editor_status]
mov ecx,editor_status_size shr 2
call exchange_data
xor edx,edx
redo_segments_block:
or ebx,ebx
jz redo_finished
mov esi,ebx
xchg ebx,edx
xchg ebx,[esi]
add esi,4
lodsd
mov ecx,eax
jecxz redo_finished
redo_segments:
push esi ecx
mov edi,[esi+4]
mov esi,[esi]
or edi,edi
jz redo_next
or esi,esi
jz redo_next
mov ecx,SEGMENT_LENGTH shr 2
call exchange_data
redo_next:
pop ecx esi
add esi,8
loop redo_segments
jmp redo_segments_block
redo_finished:
mov esi,[undo_data]
mov [esi],edx
redo_ok:
retn
clear_redo_data:
mov esi,[redo_data]
or esi,esi
jz redo_data_ok
clear_redo_block:
or ebx,-1
xchg ebx,[esi]
inc [released_segments]
mov eax,[esi+4]
mov [redo_data],eax
clear_redo_segments:
or ebx,ebx
jz next_redo_block
mov esi,ebx
or ebx,-1
xchg ebx,[esi]
inc [released_segments]
add esi,4
lodsd
mov ecx,eax
jecxz next_redo_block
release_redo_segments:
push esi ecx
mov edi,[esi+4]
mov esi,[esi]
or edi,edi
jz release_next_segment
or eax,-1
or esi,esi
jnz release_data
xchg eax,[edi]
jmp data_released
release_data:
xchg eax,[esi]
data_released:
cmp eax,-1
je release_next_segment
inc [released_segments]
release_next_segment:
pop ecx esi
add esi,8
loop release_redo_segments
jmp clear_redo_segments
next_redo_block:
mov esi,[redo_data]
or esi,esi
je redo_data_ok
cmp esi,[unmodified_state]
jne clear_redo_block
mov [unmodified_state],-1
jmp clear_redo_block
redo_data_ok:
retn
clear_undo_data:
mov esi,[undo_data]
push esi
clear_undo_block:
or esi,esi
jz undo_data_ok
or ebx,-1
xchg ebx,[esi]
inc [released_segments]
add esi,4
lodsd
mov [undo_data],eax
clear_undo_segments:
or ebx,ebx
jz next_undo_block
mov esi,ebx
or ebx,-1
xchg ebx,[esi]
inc [released_segments]
add esi,4
lodsd
mov ecx,eax
jecxz next_undo_block
lea esi,[esi+ecx*8]
release_segments:
sub esi,8
mov edx,[esi]
or edx,edx
jz release_next
or eax,-1
xchg [edx],eax
cmp eax,-1
je release_next
inc [released_segments]
release_next:
loop release_segments
next_undo_block:
mov esi,[undo_data]
cmp esi,[unmodified_state]
jne clear_undo_block
or [unmodified_state],-1
jmp clear_undo_block
undo_data_ok:
pop esi
cmp esi,[unmodified_state]
jne unmodified_ok
mov [unmodified_state],0
unmodified_ok:
retn

View File

@ -0,0 +1,40 @@
; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
editor_memory dd ?
label editor_status
first_line dd ?
lines_count dd ?
peak_line_length dd ?
maximum_position dd ?
window_line dd ?
window_position dd ?
window_line_number dd ?
caret_line dd ?
caret_position dd ?
caret_line_number dd ?
selection_line dd ?
selection_position dd ?
selection_line_number dd ?
editor_mode dd ?
editor_status_size = $ - editor_status
window_width dd ?
window_height dd ?
unallocated_segments dd ?
unallocated_segments_end dd ?
released_segments dd ?
memory_search_block dd ?
memory_search_segment dd ?
lengths_table dd ?
undo_data dd ?
redo_data dd ?
search_data dd ?
search_flags dd ?
search_handle dd ?
unmodified_state dd ?

View File

@ -0,0 +1,39 @@
; flat editor version 3.12
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
;
; This programs is free for commercial and non-commercial use as long as
; the following conditions are adhered to.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are
; met:
;
; 1. Redistributions of source code must retain the above copyright notice,
; this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; The licence and distribution terms for any publically available
; version or derivative of this code cannot be changed. i.e. this code
; cannot simply be copied and put under another distribution licence
; (including the GNU Public Licence).
FEDIT_VERSION_STRING equ "3.12"
FEDIT_VERSION_MAJOR = 3
FEDIT_VERSION_MINOR = 12

View File

@ -0,0 +1,362 @@
; flat assembler interface for Unix/libc
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
format ELF
public main
macro ccall proc,[arg]
{ common
local size
size = 0
mov ebp,esp
if ~ arg eq
forward
size = size + 4
common
sub esp,size
end if
and esp,-16
if ~ arg eq
add esp,size
reverse
pushd arg
common
end if
call proc
mov esp,ebp }
extrn gettimeofday
section '.text' executable align 16
main:
mov ecx,[esp+4]
mov [argc],ecx
mov ebx,[esp+8]
mov [argv],ebx
push ebp
mov [stack_frame],esp
mov [con_handle],1
mov esi,_logo
call display_string
call get_params
jc information
call init_memory
mov esi,_memory_prefix
call display_string
mov eax,[memory_end]
sub eax,[memory_start]
add eax,[additional_memory_end]
sub eax,[additional_memory]
shr eax,10
call display_number
mov esi,_memory_suffix
call display_string
ccall gettimeofday,buffer,0
mov eax,dword [buffer]
mov ecx,1000
mul ecx
mov ebx,eax
mov eax,dword [buffer+4]
div ecx
add eax,ebx
mov [start_time],eax
and [preprocessing_done],0
call preprocessor
or [preprocessing_done],-1
call parser
call assembler
call formatter
call display_user_messages
movzx eax,[current_pass]
inc eax
call display_number
mov esi,_passes_suffix
call display_string
ccall gettimeofday,buffer,0
mov eax,dword [buffer]
mov ecx,1000
mul ecx
mov ebx,eax
mov eax,dword [buffer+4]
div ecx
add eax,ebx
sub eax,[start_time]
jnc time_ok
add eax,3600000
time_ok:
xor edx,edx
mov ebx,100
div ebx
or eax,eax
jz display_bytes_count
xor edx,edx
mov ebx,10
div ebx
push edx
call display_number
mov dl,'.'
call display_character
pop eax
call display_number
mov esi,_seconds_suffix
call display_string
display_bytes_count:
mov eax,[written_size]
call display_number
mov esi,_bytes_suffix
call display_string
xor al,al
jmp exit_program
information:
mov esi,_usage
call display_string
mov al,1
jmp exit_program
get_params:
mov [input_file],0
mov [output_file],0
mov [symbols_file],0
mov [memory_setting],0
mov [passes_limit],100
mov ecx,[argc]
mov ebx,[argv]
add ebx,4
dec ecx
jz bad_params
mov [definitions_pointer],predefinitions
get_param:
mov esi,[ebx]
mov al,[esi]
cmp al,'-'
je option_param
cmp [input_file],0
jne get_output_file
mov [input_file],esi
jmp next_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],esi
jmp next_param
option_param:
inc esi
lodsb
cmp al,'m'
je memory_option
cmp al,'M'
je memory_option
cmp al,'p'
je passes_option
cmp al,'P'
je passes_option
cmp al,'d'
je definition_option
cmp al,'D'
je definition_option
cmp al,'s'
je symbols_option
cmp al,'S'
je symbols_option
bad_params:
stc
ret
memory_option:
cmp byte [esi],0
jne get_memory_setting
dec ecx
jz bad_params
add ebx,4
mov esi,[ebx]
get_memory_setting:
call get_option_value
or edx,edx
jz bad_params
cmp edx,1 shl (32-10)
jae bad_params
mov [memory_setting],edx
jmp next_param
passes_option:
cmp byte [esi],0
jne get_passes_setting
dec ecx
jz bad_params
add ebx,4
mov esi,[ebx]
get_passes_setting:
call get_option_value
or edx,edx
jz bad_params
cmp edx,10000h
ja bad_params
mov [passes_limit],dx
next_param:
add ebx,4
dec ecx
jnz get_param
cmp [input_file],0
je bad_params
mov eax,[definitions_pointer]
mov byte [eax],0
mov [initial_definitions],predefinitions
clc
ret
definition_option:
cmp byte [esi],0
jne get_definition
dec ecx
jz bad_params
add ebx,4
mov esi,[ebx]
get_definition:
push edi
mov edi,[definitions_pointer]
call convert_definition_option
mov [definitions_pointer],edi
pop edi
jc bad_params
jmp next_param
symbols_option:
cmp byte [esi],0
jne get_symbols_setting
dec ecx
jz bad_params
add ebx,4
mov esi,[ebx]
get_symbols_setting:
mov [symbols_file],esi
jmp next_param
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc invalid_option_value
cmp al,9
ja invalid_option_value
imul edx,10
jo invalid_option_value
add edx,eax
jc invalid_option_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
invalid_option_value:
stc
ret
convert_definition_option:
mov edx,edi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
copy_definition_name:
lodsb
cmp al,'='
je copy_definition_value
cmp al,20h
je bad_definition_option
or al,al
jz bad_definition_option
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
inc byte [edx]
jnz copy_definition_name
bad_definition_option:
stc
ret
copy_definition_value:
lodsb
cmp al,20h
je definition_value_end
or al,al
jz definition_value_end
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
jmp copy_definition_value
definition_value_end:
dec esi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
clc
ret
include 'system.inc'
include '..\version.inc'
_copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0xA,0
_logo db 'flat assembler version ',VERSION_STRING,0
_usage db 0xA
db 'usage: fasm <source> [output]',0xA
db 'optional settings:',0xA
db ' -m <limit> set the limit in kilobytes for the available memory',0xA
db ' -p <limit> set the maximum allowed number of passes',0xA
db ' -d <name>=<value> define symbolic variable',0xA
db ' -s <file> dump symbolic information for debugging',0xA
db 0
_memory_prefix db ' (',0
_memory_suffix db ' kilobytes memory)',0xA,0
_passes_suffix db ' passes, ',0
_seconds_suffix db ' seconds, ',0
_bytes_suffix db ' bytes.',0xA,0
include '..\errors.inc'
include '..\symbdump.inc'
include '..\preproce.inc'
include '..\parser.inc'
include '..\exprpars.inc'
include '..\assemble.inc'
include '..\exprcalc.inc'
include '..\formats.inc'
include '..\x86_64.inc'
include '..\avx.inc'
include '..\tables.inc'
include '..\messages.inc'
section '.bss' writeable align 4
include '..\variable.inc'
argc dd ?
argv dd ?
stack_frame dd ?
memory_setting dd ?
definitions_pointer dd ?
start_time dd ?
timestamp dq ?
con_handle dd ?
displayed_count dd ?
last_displayed db ?
character db ?
preprocessing_done db ?
predefinitions rb 1000h
buffer rb 1000h

View File

@ -0,0 +1,410 @@
; flat assembler interface for Unix/libc
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
extrn malloc
extrn free
extrn getenv
extrn fopen
extrn fclose
extrn fread
extrn fwrite
extrn fseek
extrn ftell
extrn time
extrn exit
extrn 'write' as libc_write
init_memory:
mov eax,esp
and eax,not 0FFFh
add eax,1000h-10000h
mov [stack_limit],eax
mov ecx,[memory_setting]
shl ecx,10
jnz allocate_memory
mov ecx,1000000h
allocate_memory:
mov [memory_setting],ecx
ccall malloc,ecx
or eax,eax
jz out_of_memory
mov [additional_memory],eax
add eax,[memory_setting]
mov [memory_end],eax
mov eax,[memory_setting]
shr eax,2
add eax,[additional_memory]
mov [additional_memory_end],eax
mov [memory_start],eax
ret
exit_program:
movzx eax,al
push eax
ccall free,[additional_memory]
pop eax
ccall exit,eax
mov esp,[stack_frame]
pop ebp
ret
get_environment_variable:
ccall getenv,esi
mov esi,eax
or eax,eax
jz no_environment_variable
copy_variable_value:
lodsb
cmp edi,[memory_end]
jae out_of_memory
stosb
or al,al
jnz copy_variable_value
dec edi
ret
no_environment_variable:
stosb
dec edi
ret
open:
push esi edi ebp
call adapt_path
ccall fopen,buffer,open_mode
pop ebp edi esi
or eax,eax
jz file_error
mov ebx,eax
clc
ret
adapt_path:
mov esi,edx
mov edi,buffer
copy_path:
lods byte [esi]
cmp al,'\'
jne path_char_ok
mov al,'/'
path_char_ok:
stos byte [edi]
or al,al
jnz copy_path
cmp edi,buffer+1000h
ja out_of_memory
ret
create:
push esi edi ebp
call adapt_path
ccall fopen,buffer,create_mode
pop ebp edi esi
or eax,eax
jz file_error
mov ebx,eax
clc
ret
close:
ccall fclose,ebx
ret
read:
push ebx ecx edx esi edi ebp
ccall fread,edx,1,ecx,ebx
pop ebp edi esi edx ecx ebx
cmp eax,ecx
jne file_error
clc
ret
file_error:
stc
ret
write:
push ebx ecx edx esi edi ebp
ccall fwrite,edx,1,ecx,ebx
pop ebp edi esi edx ecx ebx
cmp eax,ecx
jne file_error
clc
ret
lseek:
push ebx
movzx eax,al
ccall fseek,ebx,edx,eax
test eax,eax
jnz lseek_error
mov ebx,[esp]
ccall ftell,ebx
pop ebx
clc
ret
lseek_error:
pop ebx
stc
ret
display_string:
lodsb
or al,al
jz string_displayed
mov dl,al
call display_character
jmp display_string
string_displayed:
ret
display_character:
mov [character],dl
ccall libc_write,[con_handle],character,1
ret
display_number:
push ebx
mov ecx,1000000000
xor edx,edx
xor bl,bl
display_loop:
div ecx
push edx
cmp ecx,1
je display_digit
or bl,bl
jnz display_digit
or al,al
jz digit_ok
not bl
display_digit:
mov dl,al
add dl,30h
push ebx ecx
call display_character
pop ecx ebx
digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
pop eax
or ecx,ecx
jnz display_loop
pop ebx
ret
display_user_messages:
mov [displayed_count],0
call show_display_buffer
cmp [displayed_count],0
je line_break_ok
cmp [last_displayed],0Ah
je line_break_ok
mov dl,0Ah
call display_character
line_break_ok:
ret
display_block:
jecxz block_displayed
add [displayed_count],ecx
mov al,[esi+ecx-1]
mov [last_displayed],al
display_characters:
lodsb
mov dl,al
push ecx esi
call display_character
pop esi ecx
loop display_characters
block_displayed:
ret
fatal_error:
mov [con_handle],2
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,0FFh
jmp exit_program
assembler_error:
mov [con_handle],2
call display_user_messages
mov ebx,[current_line]
test ebx,ebx
jz display_error_message
push dword 0
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
push ebx
test byte [ebx+7],80h
jz display_error_line
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
display_error_line:
mov esi,[ebx]
call display_string
mov esi,line_number_start
call display_string
mov eax,[ebx+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
pop esi
cmp ebx,esi
je line_number_ok
mov dl,20h
call display_character
push esi
mov esi,[esi]
movzx ecx,byte [esi]
inc esi
call display_block
mov esi,line_number_start
call display_string
pop esi
mov eax,[esi+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
line_number_ok:
mov esi,line_data_start
call display_string
mov esi,ebx
mov edx,[esi]
call open
mov al,2
xor edx,edx
call lseek
mov edx,[esi+8]
sub eax,edx
jz line_data_displayed
push eax
xor al,al
call lseek
mov ecx,[esp]
mov edx,[additional_memory]
lea eax,[edx+ecx]
cmp eax,[additional_memory_end]
ja out_of_memory
call read
call close
pop ecx
mov esi,[additional_memory]
get_line_data:
mov al,[esi]
cmp al,0Ah
je display_line_data
cmp al,0Dh
je display_line_data
cmp al,1Ah
je display_line_data
or al,al
jz display_line_data
inc esi
loop get_line_data
display_line_data:
mov ecx,esi
mov esi,[additional_memory]
sub ecx,esi
call display_block
line_data_displayed:
mov esi,lf
call display_string
pop ebx
or ebx,ebx
jnz display_error_line
cmp [preprocessing_done],0
je display_error_message
mov esi,preprocessed_instruction_prefix
call display_string
mov esi,[current_line]
add esi,16
mov edi,[additional_memory]
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je instruction_converted
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_instruction
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_instruction
instruction_converted:
xor al,al
stosb
mov esi,[additional_memory]
call display_string
mov esi,lf
call display_string
display_error_message:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,2
jmp exit_program
make_timestamp:
ccall time,timestamp
mov eax,dword [timestamp]
mov edx,dword [timestamp+4]
ret
open_mode db 'r',0
create_mode db 'w',0
error_prefix db 'error: ',0
error_suffix db '.'
lf db 0xA,0
line_number_start db ' [',0
line_data_start db ':',0xA,0
preprocessed_instruction_prefix db 'processed: ',0

View File

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

View File

@ -0,0 +1,470 @@
; flat assembler interface for Linux
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
O_ACCMODE = 0003o
O_RDONLY = 0000o
O_WRONLY = 0001o
O_RDWR = 0002o
O_CREAT = 0100o
O_EXCL = 0200o
O_NOCTTY = 0400o
O_TRUNC = 1000o
O_APPEND = 2000o
O_NONBLOCK = 4000o
S_ISUID = 4000o
S_ISGID = 2000o
S_ISVTX = 1000o
S_IRUSR = 0400o
S_IWUSR = 0200o
S_IXUSR = 0100o
S_IRGRP = 0040o
S_IWGRP = 0020o
S_IXGRP = 0010o
S_IROTH = 0004o
S_IWOTH = 0002o
S_IXOTH = 0001o
init_memory:
mov eax,esp
and eax,not 0FFFh
add eax,1000h-10000h
mov [stack_limit],eax
xor ebx,ebx
mov eax,45
int 0x80
mov [additional_memory],eax
mov ecx,[memory_setting]
shl ecx,10
jnz allocate_memory
mov ecx,1000000h
allocate_memory:
mov ebx,[additional_memory]
add ebx,ecx
mov eax,45
int 0x80
mov [memory_end],eax
sub eax,[additional_memory]
shr eax,2
add eax,[additional_memory]
mov [additional_memory_end],eax
mov [memory_start],eax
ret
exit_program:
movzx ebx,al
mov eax,1
int 0x80
get_environment_variable:
mov ecx,esi
mov ebx,[environment]
next_variable:
mov esi,[ebx]
test esi,esi
jz no_environment_variable
add ebx,4
compare_variable_names:
mov edx,ecx
compare_character:
lodsb
mov ah,[edx]
inc edx
cmp al,'='
je end_of_variable_name
or ah,ah
jz next_variable
sub ah,al
jz compare_character
cmp ah,20h
jne next_variable
cmp al,41h
jb next_variable
cmp al,5Ah
jna compare_character
jmp next_variable
no_environment_variable:
ret
end_of_variable_name:
or ah,ah
jnz next_variable
copy_variable_value:
lodsb
cmp edi,[memory_end]
jae out_of_memory
stosb
or al,al
jnz copy_variable_value
dec edi
ret
open:
push esi edi ebp
call adapt_path
mov eax,5
mov ebx,buffer
mov ecx,O_RDONLY
xor edx,edx
int 0x80
pop ebp edi esi
test eax,eax
js file_error
mov ebx,eax
clc
ret
adapt_path:
mov esi,edx
mov edi,buffer
copy_path:
lods byte [esi]
cmp al,'\'
jne path_char_ok
mov al,'/'
path_char_ok:
stos byte [edi]
or al,al
jnz copy_path
cmp edi,buffer+1000h
ja out_of_memory
ret
create:
push esi edi ebp edx
call adapt_path
mov ebx,buffer
mov ecx,O_CREAT+O_TRUNC+O_WRONLY
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
pop eax
cmp eax,[output_file]
jne do_create
cmp [output_format],5
jne do_create
bt [format_flags],0
jnc do_create
or edx,S_IXUSR+S_IXGRP+S_IXOTH
do_create:
mov eax,5
int 0x80
pop ebp edi esi
test eax,eax
js file_error
mov ebx,eax
clc
ret
close:
mov eax,6
int 0x80
ret
read:
push ecx edx esi edi ebp
mov eax,3
xchg ecx,edx
int 0x80
pop ebp edi esi edx ecx
test eax,eax
js file_error
cmp eax,ecx
jne file_error
clc
ret
file_error:
stc
ret
write:
push edx esi edi ebp
mov eax,4
xchg ecx,edx
int 0x80
pop ebp edi esi edx
test eax,eax
js file_error
clc
ret
lseek:
mov ecx,edx
xor edx,edx
mov dl,al
mov eax,19
int 0x80
cmp eax,-1
je file_error
clc
ret
display_string:
push ebx
mov edi,esi
mov edx,esi
or ecx,-1
xor al,al
repne scasb
neg ecx
sub ecx,2
mov eax,4
mov ebx,[con_handle]
xchg ecx,edx
int 0x80
pop ebx
ret
display_character:
push ebx
mov [character],dl
mov eax,4
mov ebx,[con_handle]
mov ecx,character
mov edx,1
int 0x80
pop ebx
ret
display_number:
push ebx
mov ecx,1000000000
xor edx,edx
xor bl,bl
display_loop:
div ecx
push edx
cmp ecx,1
je display_digit
or bl,bl
jnz display_digit
or al,al
jz digit_ok
not bl
display_digit:
mov dl,al
add dl,30h
push ebx ecx
call display_character
pop ecx ebx
digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
pop eax
or ecx,ecx
jnz display_loop
pop ebx
ret
display_user_messages:
mov [displayed_count],0
call show_display_buffer
cmp [displayed_count],0
je line_break_ok
cmp [last_displayed],0Ah
je line_break_ok
mov dl,0Ah
call display_character
line_break_ok:
ret
display_block:
jecxz block_displayed
add [displayed_count],ecx
mov al,[esi+ecx-1]
mov [last_displayed],al
push ebx
mov eax,4
mov ebx,[con_handle]
mov edx,ecx
mov ecx,esi
int 0x80
pop ebx
block_displayed:
ret
fatal_error:
mov [con_handle],2
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,0FFh
jmp exit_program
assembler_error:
mov [con_handle],2
call display_user_messages
mov ebx,[current_line]
test ebx,ebx
jz display_error_message
pushd 0
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
push ebx
test byte [ebx+7],80h
jz display_error_line
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
display_error_line:
mov esi,[ebx]
call display_string
mov esi,line_number_start
call display_string
mov eax,[ebx+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
pop esi
cmp ebx,esi
je line_number_ok
mov dl,20h
call display_character
push esi
mov esi,[esi]
movzx ecx,byte [esi]
inc esi
call display_block
mov esi,line_number_start
call display_string
pop esi
mov eax,[esi+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
line_number_ok:
mov esi,line_data_start
call display_string
mov esi,ebx
mov edx,[esi]
call open
mov al,2
xor edx,edx
call lseek
mov edx,[esi+8]
sub eax,edx
jz line_data_displayed
push eax
xor al,al
call lseek
mov ecx,[esp]
mov edx,[additional_memory]
lea eax,[edx+ecx]
cmp eax,[additional_memory_end]
ja out_of_memory
call read
call close
pop ecx
mov esi,[additional_memory]
get_line_data:
mov al,[esi]
cmp al,0Ah
je display_line_data
cmp al,0Dh
je display_line_data
cmp al,1Ah
je display_line_data
or al,al
jz display_line_data
inc esi
loop get_line_data
display_line_data:
mov ecx,esi
mov esi,[additional_memory]
sub ecx,esi
call display_block
line_data_displayed:
mov esi,lf
call display_string
pop ebx
or ebx,ebx
jnz display_error_line
cmp [preprocessing_done],0
je display_error_message
mov esi,preprocessed_instruction_prefix
call display_string
mov esi,[current_line]
add esi,16
mov edi,[additional_memory]
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je instruction_converted
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_instruction
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_instruction
instruction_converted:
xor al,al
stosb
mov esi,[additional_memory]
call display_string
mov esi,lf
call display_string
display_error_message:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,2
jmp exit_program
make_timestamp:
mov eax,13
mov ebx,timestamp
int 0x80
mov eax,dword [timestamp]
mov edx,dword [timestamp+4]
ret
error_prefix db 'error: ',0
error_suffix db '.'
lf db 0xA,0
line_number_start db ' [',0
line_data_start db ':',0xA,0
preprocessed_instruction_prefix db 'processed: ',0

View File

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

View File

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

View File

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

View File

@ -0,0 +1,51 @@
; flat assembler core
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
_out_of_memory db 'out of memory',0
_stack_overflow db 'out of stack space',0
_main_file_not_found db 'source file not found',0
_code_cannot_be_generated db 'code cannot be generated',0
_format_limitations_exceeded db 'format limitations exceeded',0
_invalid_definition db 'invalid definition provided',0
_write_failed db 'write failed',0
_file_not_found db 'file not found',0
_error_reading_file db 'error reading file',0
_invalid_file_format db 'invalid file format',0
_invalid_macro_arguments db 'invalid macro arguments',0
_incomplete_macro db 'incomplete macro',0
_unexpected_characters db 'unexpected characters',0
_invalid_argument db 'invalid argument',0
_illegal_instruction db 'illegal instruction',0
_invalid_operand db 'invalid operand',0
_invalid_operand_size db 'invalid size of operand',0
_operand_size_not_specified db 'operand size not specified',0
_operand_sizes_do_not_match db 'operand sizes do not match',0
_invalid_address_size db 'invalid size of address value',0
_address_sizes_do_not_agree db 'address sizes do not agree',0
_disallowed_combination_of_registers db 'disallowed combination of registers',0
_long_immediate_not_encodable db 'not encodable with long immediate',0
_relative_jump_out_of_range db 'relative jump out of range',0
_invalid_expression db 'invalid expression',0
_invalid_address db 'invalid address',0
_invalid_value db 'invalid value',0
_value_out_of_range db 'value out of range',0
_undefined_symbol db 'undefined symbol',0
_symbol_out_of_scope_1 db 'symbol',0
_symbol_out_of_scope_2 db 'out of scope',0
_invalid_use_of_symbol db 'invalid use of symbol',0
_name_too_long db 'name too long',0
_invalid_name db 'invalid name',0
_reserved_word_used_as_symbol db 'reserved word used as symbol',0
_symbol_already_defined db 'symbol already defined',0
_missing_end_quote db 'missing end quote',0
_missing_end_directive db 'missing end directive',0
_unexpected_instruction db 'unexpected instruction',0
_extra_characters_on_line db 'extra characters on line',0
_section_not_aligned_enough db 'section is not aligned enough',0
_setting_already_specified db 'setting already specified',0
_data_already_defined db 'data already defined',0
_too_many_repeats db 'too many repeats',0
_invoked_error db 'error directive encountered in source file',0
_assertion_failed db 'assertion failed',0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,450 @@
; flat assembler core
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
dump_symbols:
mov edi,[code_start]
call setup_dump_header
mov esi,[input_file]
call copy_asciiz
cmp edi,[tagged_blocks]
jae out_of_memory
mov eax,edi
sub eax,ebx
mov [ebx-40h+0Ch],eax
mov esi,[output_file]
call copy_asciiz
cmp edi,[tagged_blocks]
jae out_of_memory
mov edx,[symbols_stream]
mov ebp,[free_additional_memory]
and [number_of_sections],0
cmp [output_format],4
je prepare_strings_table
cmp [output_format],5
jne strings_table_ready
bt [format_flags],0
jc strings_table_ready
prepare_strings_table:
cmp edx,ebp
je strings_table_ready
mov al,[edx]
test al,al
jz prepare_string
cmp al,80h
je prepare_string
add edx,0Ch
cmp al,0C0h
jb prepare_strings_table
add edx,4
jmp prepare_strings_table
prepare_string:
mov esi,edi
sub esi,ebx
xchg esi,[edx+4]
test al,al
jz prepare_section_string
or dword [edx+4],1 shl 31
add edx,0Ch
prepare_external_string:
mov ecx,[esi]
add esi,4
rep movs byte [edi],[esi]
mov byte [edi],0
inc edi
cmp edi,[tagged_blocks]
jae out_of_memory
jmp prepare_strings_table
prepare_section_string:
mov ecx,[number_of_sections]
mov eax,ecx
inc eax
mov [number_of_sections],eax
xchg eax,[edx+4]
shl ecx,2
add ecx,[free_additional_memory]
mov [ecx],eax
add edx,20h
test esi,esi
jz prepare_default_section_string
cmp [output_format],5
jne prepare_external_string
bt [format_flags],0
jc prepare_external_string
mov esi,[esi]
add esi,[resource_data]
copy_elf_section_name:
lods byte [esi]
cmp edi,[tagged_blocks]
jae out_of_memory
stos byte [edi]
test al,al
jnz copy_elf_section_name
jmp prepare_strings_table
prepare_default_section_string:
mov eax,'.fla'
stos dword [edi]
mov ax,'t'
stos word [edi]
cmp edi,[tagged_blocks]
jae out_of_memory
jmp prepare_strings_table
strings_table_ready:
mov edx,[tagged_blocks]
mov ebp,[memory_end]
sub ebp,[labels_list]
add ebp,edx
prepare_labels_dump:
cmp edx,ebp
je labels_dump_ok
mov eax,[edx+24]
test eax,eax
jz label_dump_name_ok
cmp eax,[memory_start]
jb label_name_outside_source
cmp eax,[source_start]
ja label_name_outside_source
sub eax,[memory_start]
dec eax
mov [edx+24],eax
jmp label_dump_name_ok
label_name_outside_source:
mov esi,eax
mov eax,edi
sub eax,ebx
or eax,1 shl 31
mov [edx+24],eax
movzx ecx,byte [esi-1]
lea eax,[edi+ecx+1]
cmp edi,[tagged_blocks]
jae out_of_memory
rep movsb
xor al,al
stosb
label_dump_name_ok:
mov eax,[edx+28]
test eax,eax
jz label_dump_line_ok
sub eax,[memory_start]
mov [edx+28],eax
label_dump_line_ok:
test byte [edx+9],4
jz convert_base_symbol_for_label
xor eax,eax
mov [edx],eax
mov [edx+4],eax
jmp base_symbol_for_label_ok
convert_base_symbol_for_label:
mov eax,[edx+20]
test eax,eax
jz base_symbol_for_label_ok
cmp eax,[symbols_stream]
mov eax,[eax+4]
jae base_symbol_for_label_ok
xor eax,eax
base_symbol_for_label_ok:
mov [edx+20],eax
mov ax,[current_pass]
cmp ax,[edx+16]
je label_defined_flag_ok
and byte [edx+8],not 1
label_defined_flag_ok:
cmp ax,[edx+18]
je label_used_flag_ok
and byte [edx+8],not 8
label_used_flag_ok:
add edx,LABEL_STRUCTURE_SIZE
jmp prepare_labels_dump
labels_dump_ok:
mov eax,edi
sub eax,ebx
mov [ebx-40h+14h],eax
add eax,40h
mov [ebx-40h+18h],eax
mov ecx,[memory_end]
sub ecx,[labels_list]
mov [ebx-40h+1Ch],ecx
add eax,ecx
mov [ebx-40h+20h],eax
mov ecx,[source_start]
sub ecx,[memory_start]
mov [ebx-40h+24h],ecx
add eax,ecx
mov [ebx-40h+28h],eax
mov eax,[number_of_sections]
shl eax,2
mov [ebx-40h+34h],eax
call prepare_preprocessed_source
mov esi,[labels_list]
mov ebp,edi
make_lines_dump:
cmp esi,[tagged_blocks]
je lines_dump_ok
mov eax,[esi-4]
mov ecx,[esi-8]
sub esi,8
sub esi,ecx
cmp eax,1
je process_line_dump
cmp eax,2
jne make_lines_dump
add dword [ebx-40h+3Ch],8
jmp make_lines_dump
process_line_dump:
push ebx
mov ebx,[esi+8]
mov eax,[esi+4]
sub eax,[code_start]
add eax,[headers_size]
test byte [ebx+0Ah],1
jz store_offset
xor eax,eax
store_offset:
stos dword [edi]
mov eax,[esi]
sub eax,[memory_start]
stos dword [edi]
mov eax,[esi+4]
xor edx,edx
xor cl,cl
sub eax,[ebx]
sbb edx,[ebx+4]
sbb cl,[ebx+8]
stos dword [edi]
mov eax,edx
stos dword [edi]
mov eax,[ebx+10h]
stos dword [edi]
mov eax,[ebx+14h]
test eax,eax
jz base_symbol_for_line_ok
cmp eax,[symbols_stream]
mov eax,[eax+4]
jae base_symbol_for_line_ok
xor eax,eax
base_symbol_for_line_ok:
stos dword [edi]
mov al,[ebx+9]
stos byte [edi]
mov al,[esi+10h]
stos byte [edi]
mov al,[ebx+0Ah]
and al,1
stos byte [edi]
mov al,cl
stos byte [edi]
pop ebx
cmp edi,[tagged_blocks]
jae out_of_memory
mov eax,edi
sub eax,1Ch
sub eax,ebp
mov [esi],eax
jmp make_lines_dump
lines_dump_ok:
mov edx,edi
mov eax,[current_offset]
sub eax,[code_start]
add eax,[headers_size]
stos dword [edi]
mov ecx,edi
sub ecx,ebx
sub ecx,[ebx-40h+14h]
mov [ebx-40h+2Ch],ecx
add ecx,[ebx-40h+28h]
mov [ebx-40h+30h],ecx
add ecx,[ebx-40h+34h]
mov [ebx-40h+38h],ecx
find_inexisting_offsets:
sub edx,1Ch
cmp edx,ebp
jb write_symbols
test byte [edx+1Ah],1
jnz find_inexisting_offsets
cmp eax,[edx]
jb correct_inexisting_offset
mov eax,[edx]
jmp find_inexisting_offsets
correct_inexisting_offset:
and dword [edx],0
or byte [edx+1Ah],2
jmp find_inexisting_offsets
write_symbols:
mov edx,[symbols_file]
call create
jc write_failed
mov edx,[code_start]
mov ecx,[edx+14h]
add ecx,40h
call write
jc write_failed
mov edx,[tagged_blocks]
mov ecx,[memory_end]
sub ecx,[labels_list]
call write
jc write_failed
mov edx,[memory_start]
mov ecx,[source_start]
sub ecx,edx
call write
jc write_failed
mov edx,ebp
mov ecx,edi
sub ecx,edx
call write
jc write_failed
mov edx,[free_additional_memory]
mov ecx,[number_of_sections]
shl ecx,2
call write
jc write_failed
mov esi,[labels_list]
mov edi,[memory_start]
make_references_dump:
cmp esi,[tagged_blocks]
je references_dump_ok
mov eax,[esi-4]
mov ecx,[esi-8]
sub esi,8
sub esi,ecx
cmp eax,2
je dump_reference
cmp eax,1
jne make_references_dump
mov edx,[esi]
jmp make_references_dump
dump_reference:
mov eax,[memory_end]
sub eax,[esi]
sub eax,LABEL_STRUCTURE_SIZE
stosd
mov eax,edx
stosd
cmp edi,[tagged_blocks]
jb make_references_dump
jmp out_of_memory
references_dump_ok:
mov edx,[memory_start]
mov ecx,edi
sub ecx,edx
call write
jc write_failed
call close
ret
setup_dump_header:
xor eax,eax
mov ecx,40h shr 2
rep stos dword [edi]
mov ebx,edi
mov dword [ebx-40h],'fas'+1Ah shl 24
mov dword [ebx-40h+4],VERSION_MAJOR + VERSION_MINOR shl 8 + 40h shl 16
mov dword [ebx-40h+10h],40h
ret
prepare_preprocessed_source:
mov esi,[memory_start]
mov ebp,[source_start]
test ebp,ebp
jnz prepare_preprocessed_line
mov ebp,[current_line]
inc ebp
prepare_preprocessed_line:
cmp esi,ebp
jae preprocessed_source_ok
mov eax,[memory_start]
mov edx,[input_file]
cmp [esi],edx
jne line_not_from_main_input
mov [esi],eax
line_not_from_main_input:
sub [esi],eax
test byte [esi+7],1 shl 7
jz prepare_next_preprocessed_line
sub [esi+8],eax
sub [esi+12],eax
prepare_next_preprocessed_line:
call skip_preprocessed_line
jmp prepare_preprocessed_line
preprocessed_source_ok:
ret
skip_preprocessed_line:
add esi,16
skip_preprocessed_line_content:
lods byte [esi]
cmp al,1Ah
je skip_preprocessed_symbol
cmp al,3Bh
je skip_preprocessed_symbol
cmp al,22h
je skip_preprocessed_string
or al,al
jnz skip_preprocessed_line_content
ret
skip_preprocessed_string:
lods dword [esi]
add esi,eax
jmp skip_preprocessed_line_content
skip_preprocessed_symbol:
lods byte [esi]
movzx eax,al
add esi,eax
jmp skip_preprocessed_line_content
restore_preprocessed_source:
mov esi,[memory_start]
mov ebp,[source_start]
test ebp,ebp
jnz restore_preprocessed_line
mov ebp,[current_line]
inc ebp
restore_preprocessed_line:
cmp esi,ebp
jae preprocessed_source_restored
mov eax,[memory_start]
add [esi],eax
cmp [esi],eax
jne preprocessed_line_source_restored
mov edx,[input_file]
mov [esi],edx
preprocessed_line_source_restored:
test byte [esi+7],1 shl 7
jz restore_next_preprocessed_line
add [esi+8],eax
add [esi+12],eax
restore_next_preprocessed_line:
call skip_preprocessed_line
jmp restore_preprocessed_line
preprocessed_source_restored:
ret
dump_preprocessed_source:
mov edi,[free_additional_memory]
call setup_dump_header
mov esi,[input_file]
call copy_asciiz
cmp edi,[additional_memory_end]
jae out_of_memory
mov eax,edi
sub eax,ebx
dec eax
mov [ebx-40h+0Ch],eax
mov eax,edi
sub eax,ebx
mov [ebx-40h+14h],eax
add eax,40h
mov [ebx-40h+20h],eax
call prepare_preprocessed_source
sub esi,[memory_start]
mov [ebx-40h+24h],esi
mov edx,[symbols_file]
call create
jc write_failed
mov edx,[free_additional_memory]
mov ecx,[edx+14h]
add ecx,40h
call write
jc write_failed
mov edx,[memory_start]
mov ecx,esi
call write
jc write_failed
call close
ret

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,155 @@
; flat assembler core variables
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
; Variables which have to be set up by interface:
memory_start dd ?
memory_end dd ?
additional_memory dd ?
additional_memory_end dd ?
stack_limit dd ?
initial_definitions dd ?
input_file dd ?
output_file dd ?
symbols_file dd ?
passes_limit dw ?
; Internal core variables:
current_pass dw ?
include_paths dd ?
free_additional_memory dd ?
source_start dd ?
code_start dd ?
code_size dd ?
real_code_size dd ?
written_size dd ?
headers_size dd ?
current_line dd ?
macro_line dd ?
macro_block dd ?
macro_block_line dd ?
macro_block_line_number dd ?
macro_symbols dd ?
struc_name dd ?
struc_label dd ?
instant_macro_start dd ?
parameters_end dd ?
default_argument_value dd ?
locals_counter rb 8
current_locals_prefix dd ?
anonymous_reverse dd ?
anonymous_forward dd ?
labels_list dd ?
label_hash dd ?
label_leaf dd ?
hash_tree dd ?
addressing_space dd ?
undefined_data_start dd ?
undefined_data_end dd ?
counter dd ?
counter_limit dd ?
error_info dd ?
error_line dd ?
error dd ?
tagged_blocks dd ?
structures_buffer dd ?
number_start dd ?
current_offset dd ?
value dq ?
fp_value rd 8
adjustment dq ?
symbol_identifier dd ?
address_symbol dd ?
address_high dd ?
uncompressed_displacement dd ?
format_flags dd ?
resolver_flags dd ?
symbols_stream dd ?
number_of_relocations dd ?
number_of_sections dd ?
stub_size dd ?
stub_file dd ?
current_section dd ?
machine dw ?
subsystem dw ?
subsystem_version dd ?
image_base dd ?
image_base_high dd ?
merge_segment dd ?
resource_data dd ?
resource_size dd ?
actual_fixups_size dd ?
reserved_fixups dd ?
reserved_fixups_size dd ?
last_fixup_base dd ?
last_fixup_header dd ?
parenthesis_stack dd ?
blocks_stack dd ?
parsed_lines dd ?
logical_value_parentheses dd ?
file_extension dd ?
operand_size db ?
operand_flags db ?
operand_prefix db ?
rex_prefix db ?
opcode_prefix db ?
vex_required db ?
vex_register db ?
immediate_size db ?
mask_register db ?
broadcast_size db ?
rounding_mode db ?
base_code db ?
extended_code db ?
supplemental_code db ?
postbyte_register db ?
segment_register db ?
xop_opcode_map db ?
mmx_size db ?
jump_type db ?
push_size db ?
value_size db ?
address_size db ?
label_size db ?
size_declared db ?
address_size_declared db ?
displacement_compression db ?
value_undefined db ?
value_constant db ?
value_type db ?
value_sign db ?
fp_sign db ?
fp_format db ?
address_sign db ?
address_register db ?
compare_type db ?
logical_value_wrapping db ?
next_pass_needed db ?
output_format db ?
code_type db ?
adjustment_sign db ?
evex_mode db ?
macro_status db ?
skip_default_argument_value db ?
prefix_flags db ?
formatter_symbols_allowed db ?
decorator_symbols_allowed db ?
free_address_range db ?
characters rb 100h
converted rb 100h
message rb 180h

View File

@ -0,0 +1,39 @@
; flat assembler version 1.73
; Copyright (c) 1999-2024, Tomasz Grysztar.
; All rights reserved.
;
; This programs is free for commercial and non-commercial use as long as
; the following conditions are adhered to.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are
; met:
;
; 1. Redistributions of source code must retain the above copyright notice,
; this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; The licence and distribution terms for any publically available
; version or derivative of this code cannot be changed. i.e. this code
; cannot simply be copied and put under another distribution licence
; (including the GNU Public Licence).
VERSION_STRING equ "1.73.32"
VERSION_MAJOR = 1
VERSION_MINOR = 73

View File

@ -0,0 +1,436 @@
; flat assembler interface for Win32
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
format PE console
section '.text' code readable executable
start:
mov [con_handle],STD_OUTPUT_HANDLE
mov esi,_logo
call display_string
call get_params
jc information
call init_memory
mov esi,_memory_prefix
call display_string
mov eax,[memory_end]
sub eax,[memory_start]
add eax,[additional_memory_end]
sub eax,[additional_memory]
shr eax,10
call display_number
mov esi,_memory_suffix
call display_string
call [GetTickCount]
mov [start_time],eax
and [preprocessing_done],0
call preprocessor
or [preprocessing_done],-1
call parser
call assembler
call formatter
call display_user_messages
movzx eax,[current_pass]
inc eax
call display_number
mov esi,_passes_suffix
call display_string
call [GetTickCount]
sub eax,[start_time]
xor edx,edx
mov ebx,100
div ebx
or eax,eax
jz display_bytes_count
xor edx,edx
mov ebx,10
div ebx
push edx
call display_number
mov dl,'.'
call display_character
pop eax
call display_number
mov esi,_seconds_suffix
call display_string
display_bytes_count:
mov eax,[written_size]
call display_number
mov esi,_bytes_suffix
call display_string
xor al,al
jmp exit_program
information:
mov esi,_usage
call display_string
mov al,1
jmp exit_program
get_params:
mov [input_file],0
mov [output_file],0
mov [symbols_file],0
mov [memory_setting],0
mov [passes_limit],100
call [GetCommandLine]
mov [definitions_pointer],predefinitions
mov esi,eax
mov edi,params
find_command_start:
lodsb
cmp al,20h
je find_command_start
cmp al,22h
je skip_quoted_name
skip_name:
lodsb
cmp al,20h
je find_param
or al,al
jz all_params
jmp skip_name
skip_quoted_name:
lodsb
cmp al,22h
je find_param
or al,al
jz all_params
jmp skip_quoted_name
find_param:
lodsb
cmp al,20h
je find_param
cmp al,'-'
je option_param
cmp al,0Dh
je all_params
or al,al
jz all_params
cmp [input_file],0
jne get_output_file
mov [input_file],edi
jmp process_param
get_output_file:
cmp [output_file],0
jne bad_params
mov [output_file],edi
process_param:
cmp al,22h
je string_param
copy_param:
cmp edi,params+1000h
jae bad_params
stosb
lodsb
cmp al,20h
je param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
jmp copy_param
string_param:
lodsb
cmp al,22h
je string_param_end
cmp al,0Dh
je param_end
or al,al
jz param_end
cmp edi,params+1000h
jae bad_params
stosb
jmp string_param
option_param:
lodsb
cmp al,'m'
je memory_option
cmp al,'M'
je memory_option
cmp al,'p'
je passes_option
cmp al,'P'
je passes_option
cmp al,'d'
je definition_option
cmp al,'D'
je definition_option
cmp al,'s'
je symbols_option
cmp al,'S'
je symbols_option
bad_params:
stc
ret
get_option_value:
xor eax,eax
mov edx,eax
get_option_digit:
lodsb
cmp al,20h
je option_value_ok
cmp al,0Dh
je option_value_ok
or al,al
jz option_value_ok
sub al,30h
jc invalid_option_value
cmp al,9
ja invalid_option_value
imul edx,10
jo invalid_option_value
add edx,eax
jc invalid_option_value
jmp get_option_digit
option_value_ok:
dec esi
clc
ret
invalid_option_value:
stc
ret
memory_option:
lodsb
cmp al,20h
je memory_option
cmp al,0Dh
je bad_params
or al,al
jz bad_params
dec esi
call get_option_value
or edx,edx
jz bad_params
cmp edx,1 shl (32-10)
jae bad_params
mov [memory_setting],edx
jmp find_param
passes_option:
lodsb
cmp al,20h
je passes_option
cmp al,0Dh
je bad_params
or al,al
jz bad_params
dec esi
call get_option_value
or edx,edx
jz bad_params
cmp edx,10000h
ja bad_params
mov [passes_limit],dx
jmp find_param
definition_option:
lodsb
cmp al,20h
je definition_option
cmp al,0Dh
je bad_params
or al,al
jz bad_params
dec esi
push edi
mov edi,[definitions_pointer]
call convert_definition_option
mov [definitions_pointer],edi
pop edi
jc bad_params
jmp find_param
symbols_option:
mov [symbols_file],edi
find_symbols_file_name:
lodsb
cmp al,20h
jne process_param
jmp find_symbols_file_name
param_end:
dec esi
string_param_end:
cmp edi,params+1000h
jae bad_params
xor al,al
stosb
jmp find_param
all_params:
cmp [input_file],0
je bad_params
mov eax,[definitions_pointer]
mov byte [eax],0
mov [initial_definitions],predefinitions
clc
ret
convert_definition_option:
mov ecx,edi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
copy_definition_name:
lodsb
cmp al,'='
je copy_definition_value
cmp al,20h
je bad_definition_option
cmp al,0Dh
je bad_definition_option
or al,al
jz bad_definition_option
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
inc byte [ecx]
jnz copy_definition_name
bad_definition_option:
stc
ret
copy_definition_value:
lodsb
cmp al,20h
je definition_value_end
cmp al,0Dh
je definition_value_end
or al,al
jz definition_value_end
cmp al,'\'
jne definition_value_character
cmp byte [esi],20h
jne definition_value_character
lodsb
definition_value_character:
cmp edi,predefinitions+1000h
jae bad_definition_option
stosb
jmp copy_definition_value
definition_value_end:
dec esi
cmp edi,predefinitions+1000h
jae bad_definition_option
xor al,al
stosb
clc
ret
include 'system.inc'
include '..\errors.inc'
include '..\symbdump.inc'
include '..\preproce.inc'
include '..\parser.inc'
include '..\exprpars.inc'
include '..\assemble.inc'
include '..\exprcalc.inc'
include '..\formats.inc'
include '..\x86_64.inc'
include '..\avx.inc'
include '..\tables.inc'
include '..\messages.inc'
section '.data' data readable writeable
include '..\version.inc'
_copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0Dh,0Ah,0
_logo db 'flat assembler version ',VERSION_STRING,0
_usage db 0Dh,0Ah
db 'usage: fasm <source> [output]',0Dh,0Ah
db 'optional settings:',0Dh,0Ah
db ' -m <limit> set the limit in kilobytes for the available memory',0Dh,0Ah
db ' -p <limit> set the maximum allowed number of passes',0Dh,0Ah
db ' -d <name>=<value> define symbolic variable',0Dh,0Ah
db ' -s <file> dump symbolic information for debugging',0Dh,0Ah
db 0
_memory_prefix db ' (',0
_memory_suffix db ' kilobytes memory)',0Dh,0Ah,0
_passes_suffix db ' passes, ',0
_seconds_suffix db ' seconds, ',0
_bytes_suffix db ' bytes.',0Dh,0Ah,0
align 4
include '..\variable.inc'
con_handle dd ?
memory_setting dd ?
start_time dd ?
definitions_pointer dd ?
bytes_count dd ?
displayed_count dd ?
character db ?
last_displayed rb 2
preprocessing_done db ?
params rb 1000h
options rb 1000h
predefinitions rb 1000h
buffer rb 4000h
stack 10000h
section '.idata' import data readable writeable
dd 0,0,0,rva kernel_name,rva kernel_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dd rva _ExitProcess
CreateFile dd rva _CreateFileA
ReadFile dd rva _ReadFile
WriteFile dd rva _WriteFile
CloseHandle dd rva _CloseHandle
SetFilePointer dd rva _SetFilePointer
GetCommandLine dd rva _GetCommandLineA
GetEnvironmentVariable dd rva _GetEnvironmentVariable
GetStdHandle dd rva _GetStdHandle
VirtualAlloc dd rva _VirtualAlloc
VirtualFree dd rva _VirtualFree
GetTickCount dd rva _GetTickCount
GetSystemTime dd rva _GetSystemTime
GlobalMemoryStatus dd rva _GlobalMemoryStatus
dd 0
kernel_name db 'KERNEL32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_CreateFileA dw 0
db 'CreateFileA',0
_ReadFile dw 0
db 'ReadFile',0
_WriteFile dw 0
db 'WriteFile',0
_CloseHandle dw 0
db 'CloseHandle',0
_SetFilePointer dw 0
db 'SetFilePointer',0
_GetCommandLineA dw 0
db 'GetCommandLineA',0
_GetEnvironmentVariable dw 0
db 'GetEnvironmentVariableA',0
_GetStdHandle dw 0
db 'GetStdHandle',0
_VirtualAlloc dw 0
db 'VirtualAlloc',0
_VirtualFree dw 0
db 'VirtualFree',0
_GetTickCount dw 0
db 'GetTickCount',0
_GetSystemTime dw 0
db 'GetSystemTime',0
_GlobalMemoryStatus dw 0
db 'GlobalMemoryStatus',0
section '.reloc' fixups data readable discardable

View File

@ -0,0 +1,570 @@
; flat assembler interface for Win32
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
FILE_SHARE_DELETE = 4
GENERIC_READ = 80000000h
GENERIC_WRITE = 40000000h
STD_INPUT_HANDLE = 0FFFFFFF6h
STD_OUTPUT_HANDLE = 0FFFFFFF5h
STD_ERROR_HANDLE = 0FFFFFFF4h
MEM_COMMIT = 1000h
MEM_RESERVE = 2000h
MEM_DECOMMIT = 4000h
MEM_RELEASE = 8000h
MEM_FREE = 10000h
MEM_PRIVATE = 20000h
MEM_MAPPED = 40000h
MEM_RESET = 80000h
MEM_TOP_DOWN = 100000h
PAGE_NOACCESS = 1
PAGE_READONLY = 2
PAGE_READWRITE = 4
PAGE_WRITECOPY = 8
PAGE_EXECUTE = 10h
PAGE_EXECUTE_READ = 20h
PAGE_EXECUTE_READWRITE = 40h
PAGE_EXECUTE_WRITECOPY = 80h
PAGE_GUARD = 100h
PAGE_NOCACHE = 200h
init_memory:
xor eax,eax
mov [memory_start],eax
mov eax,esp
and eax,not 0FFFh
add eax,1000h-10000h
mov [stack_limit],eax
mov eax,[memory_setting]
shl eax,10
jnz allocate_memory
push buffer
call [GlobalMemoryStatus]
mov eax,dword [buffer+20]
mov edx,dword [buffer+12]
cmp eax,0
jl large_memory
cmp edx,0
jl large_memory
shr eax,2
add eax,edx
jmp allocate_memory
large_memory:
mov eax,80000000h
allocate_memory:
mov edx,eax
shr edx,2
mov ecx,eax
sub ecx,edx
mov [memory_end],ecx
mov [additional_memory_end],edx
push PAGE_READWRITE
push MEM_COMMIT
push eax
push 0
call [VirtualAlloc]
or eax,eax
jz not_enough_memory
mov [memory_start],eax
add eax,[memory_end]
mov [memory_end],eax
mov [additional_memory],eax
add [additional_memory_end],eax
ret
not_enough_memory:
mov eax,[additional_memory_end]
shl eax,1
cmp eax,4000h
jb out_of_memory
jmp allocate_memory
exit_program:
movzx eax,al
push eax
mov eax,[memory_start]
test eax,eax
jz do_exit
push MEM_RELEASE
push 0
push eax
call [VirtualFree]
do_exit:
call [ExitProcess]
get_environment_variable:
mov ecx,[memory_end]
sub ecx,edi
cmp ecx,4000h
jbe buffer_for_variable_ok
mov ecx,4000h
buffer_for_variable_ok:
push ecx
push edi
push esi
call [GetEnvironmentVariable]
add edi,eax
cmp edi,[memory_end]
jae out_of_memory
ret
open:
push 0
push 0
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
push edx
call [CreateFile]
cmp eax,-1
je file_error
mov ebx,eax
clc
ret
file_error:
stc
ret
create:
push 0
push 0
push CREATE_ALWAYS
push 0
push FILE_SHARE_READ
push GENERIC_WRITE
push edx
call [CreateFile]
cmp eax,-1
je file_error
mov ebx,eax
clc
ret
write:
push 0
push bytes_count
push ecx
push edx
push ebx
call [WriteFile]
or eax,eax
jz file_error
clc
ret
read:
mov ebp,ecx
push 0
push bytes_count
push ecx
push edx
push ebx
call [ReadFile]
or eax,eax
jz file_error
cmp ebp,[bytes_count]
jne file_error
clc
ret
close:
push ebx
call [CloseHandle]
ret
lseek:
movzx eax,al
push eax
push 0
push edx
push ebx
call [SetFilePointer]
cmp eax,-1
je file_error
clc
ret
display_string:
push [con_handle]
call [GetStdHandle]
mov ebp,eax
mov edi,esi
or ecx,-1
xor al,al
repne scasb
neg ecx
sub ecx,2
push 0
push bytes_count
push ecx
push esi
push ebp
call [WriteFile]
ret
display_character:
push ebx
mov [character],dl
push [con_handle]
call [GetStdHandle]
mov ebx,eax
push 0
push bytes_count
push 1
push character
push ebx
call [WriteFile]
pop ebx
ret
display_number:
push ebx
mov ecx,1000000000
xor edx,edx
xor bl,bl
display_loop:
div ecx
push edx
cmp ecx,1
je display_digit
or bl,bl
jnz display_digit
or al,al
jz digit_ok
not bl
display_digit:
mov dl,al
add dl,30h
push ecx
call display_character
pop ecx
digit_ok:
mov eax,ecx
xor edx,edx
mov ecx,10
div ecx
mov ecx,eax
pop eax
or ecx,ecx
jnz display_loop
pop ebx
ret
display_user_messages:
mov [displayed_count],0
call show_display_buffer
cmp [displayed_count],1
jb line_break_ok
je make_line_break
mov ax,word [last_displayed]
cmp ax,0A0Dh
je line_break_ok
cmp ax,0D0Ah
je line_break_ok
make_line_break:
mov word [buffer],0A0Dh
push [con_handle]
call [GetStdHandle]
push 0
push bytes_count
push 2
push buffer
push eax
call [WriteFile]
line_break_ok:
ret
display_block:
add [displayed_count],ecx
cmp ecx,1
ja take_last_two_characters
jb block_displayed
mov al,[last_displayed+1]
mov ah,[esi]
mov word [last_displayed],ax
jmp block_ok
take_last_two_characters:
mov ax,[esi+ecx-2]
mov word [last_displayed],ax
block_ok:
push ecx
push [con_handle]
call [GetStdHandle]
pop ecx
push 0
push bytes_count
push ecx
push esi
push eax
call [WriteFile]
block_displayed:
ret
fatal_error:
mov [con_handle],STD_ERROR_HANDLE
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,0FFh
jmp exit_program
assembler_error:
mov [con_handle],STD_ERROR_HANDLE
call display_user_messages
mov ebx,[current_line]
test ebx,ebx
jz display_error_message
push dword 0
get_error_lines:
mov eax,[ebx]
cmp byte [eax],0
je get_next_error_line
push ebx
test byte [ebx+7],80h
jz display_error_line
mov edx,ebx
find_definition_origin:
mov edx,[edx+12]
test byte [edx+7],80h
jnz find_definition_origin
push edx
get_next_error_line:
mov ebx,[ebx+8]
jmp get_error_lines
display_error_line:
mov esi,[ebx]
call display_string
mov esi,line_number_start
call display_string
mov eax,[ebx+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
pop esi
cmp ebx,esi
je line_number_ok
mov dl,20h
call display_character
push esi
mov esi,[esi]
movzx ecx,byte [esi]
inc esi
call display_block
mov esi,line_number_start
call display_string
pop esi
mov eax,[esi+4]
and eax,7FFFFFFFh
call display_number
mov dl,']'
call display_character
line_number_ok:
mov esi,line_data_start
call display_string
mov esi,ebx
mov edx,[esi]
call open
mov al,2
xor edx,edx
call lseek
mov edx,[esi+8]
sub eax,edx
jz line_data_displayed
push eax
xor al,al
call lseek
mov ecx,[esp]
mov edx,[additional_memory]
lea eax,[edx+ecx]
cmp eax,[additional_memory_end]
ja out_of_memory
call read
call close
pop ecx
mov esi,[additional_memory]
get_line_data:
mov al,[esi]
cmp al,0Ah
je display_line_data
cmp al,0Dh
je display_line_data
cmp al,1Ah
je display_line_data
or al,al
jz display_line_data
inc esi
loop get_line_data
display_line_data:
mov ecx,esi
mov esi,[additional_memory]
sub ecx,esi
call display_block
line_data_displayed:
mov esi,cr_lf
call display_string
pop ebx
or ebx,ebx
jnz display_error_line
cmp [preprocessing_done],0
je display_error_message
mov esi,preprocessed_instruction_prefix
call display_string
mov esi,[current_line]
add esi,16
mov edi,[additional_memory]
xor dl,dl
convert_instruction:
lodsb
cmp al,1Ah
je copy_symbol
cmp al,22h
je copy_symbol
cmp al,3Bh
je instruction_converted
stosb
or al,al
jz instruction_converted
xor dl,dl
jmp convert_instruction
copy_symbol:
or dl,dl
jz space_ok
mov byte [edi],20h
inc edi
space_ok:
cmp al,22h
je quoted
lodsb
movzx ecx,al
rep movsb
or dl,-1
jmp convert_instruction
quoted:
mov al,27h
stosb
lodsd
mov ecx,eax
jecxz quoted_copied
copy_quoted:
lodsb
stosb
cmp al,27h
jne quote_ok
stosb
quote_ok:
loop copy_quoted
quoted_copied:
mov al,27h
stosb
or dl,-1
jmp convert_instruction
instruction_converted:
xor al,al
stosb
mov esi,[additional_memory]
call display_string
mov esi,cr_lf
call display_string
display_error_message:
mov esi,error_prefix
call display_string
pop esi
call display_string
mov esi,error_suffix
call display_string
mov al,2
jmp exit_program
make_timestamp:
push buffer
call [GetSystemTime]
movzx ecx,word [buffer]
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,word [buffer+2]
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
jbe day_correction_ok
sub ebp,2
movzx ecx,word [buffer]
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:
movzx eax,word [buffer+6]
dec eax
add eax,ebp
mov ebx,24
mul ebx
movzx ecx,word [buffer+8]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,word [buffer+10]
add eax,ecx
mov ebx,60
mul ebx
movzx ecx,word [buffer+12]
add eax,ecx
adc edx,0
ret
error_prefix db 'error: ',0
error_suffix db '.'
cr_lf db 0Dh,0Ah,0
line_number_start db ' [',0
line_data_start db ':',0Dh,0Ah,0
preprocessed_instruction_prefix db 'processed: ',0

File diff suppressed because it is too large Load Diff