asm_dip/toolchain/fasm2/source/ide/windows/fasmg.inc
2024-11-25 00:04:53 -05:00

505 lines
10 KiB
PHP

; flat assembler g interface for Windows IDE
; Copyright (c) 2014-2024, Tomasz Grysztar.
; All rights reserved.
flat_assembler:
mov esi,[esp+4]
mov [source_path],esi
mov [maximum_number_of_errors],MAX_ERRORS
xor al,al
call assembly_init
mov eax,[maximum_number_of_passes]
shl eax,16
invoke PostMessage,[hwnd_progress],PBM_SETRANGE,0,eax
invoke PostMessage,[hwnd_progress],PBM_SETPOS,0,0
invoke GetTickCount
mov [timer],eax
assemble:
mov esi,source_header
mov edx,[source_path]
call assembly_pass
jc assembly_done
mov ebx,[current_pass]
invoke PostMessage,[hwnd_progress],PBM_SETPOS,ebx,0
cmp ebx,[maximum_number_of_passes]
jb assemble
call show_display_data
cmp [first_error],0
jne assembly_failed
call assembly_shutdown
mov esi,_code_cannot_be_generated
jmp fatal_error
assembly_done:
call show_display_data
cmp [first_error],0
jne assembly_failed
mov [executable_path],0
mov ebx,[source_path]
mov edi,[output_path]
call write_output_file
jc write_failed
mov eax,[current_pass]
xor edx,edx
call itoa
call display_error_string
mov esi,_passes
cmp [current_pass],1
jne display_passes_suffix
mov esi,_pass
display_passes_suffix:
xor ecx,ecx
call display_error_string
invoke GetTickCount
sub eax,[timer]
xor edx,edx
add eax,50
mov ecx,1000
div ecx
mov ebx,eax
mov eax,edx
xor edx,edx
mov ecx,100
div ecx
mov [timer],eax
xchg eax,ebx
or ebx,eax
jz display_output_length
xor edx,edx
call itoa
call display_error_string
mov esi,_message_suffix
mov ecx,1
call display_error_string
mov eax,[timer]
xor edx,edx
call itoa
call display_error_string
mov esi,_seconds
xor ecx,ecx
call display_error_string
display_output_length:
call get_output_length
push eax edx
call itoa
call display_error_string
pop edx eax
mov esi,_bytes
cmp eax,1
jne display_bytes_suffix
test edx,edx
jnz display_bytes_suffix
mov esi,_byte
display_bytes_suffix:
xor ecx,ecx
call display_error_string
mov esi,_new_line
xor ecx,ecx
call display_error_string
summary_done:
call assembly_shutdown
xor eax,eax
jmp shutdown
assembly_failed:
mov ebx,[first_error]
collect_error:
call show_error_message
xor esi,esi
mov ecx,1
call display_error_string
mov esi,[ebx+Error.preprocessed_data]
mov ecx,[ebx+Error.preprocessed_length]
push ebx
call show_preprocessed_line
pop ebx
xor esi,esi
mov ecx,1
call display_error_string
mov eax,[ebx+sizeof.Error+SourceContext.number_of_entries]
test eax,eax
jz display_error_message
lea esi,[ebx+sizeof.Error+sizeof.SourceContext]
dec eax
imul eax,sizeof.SourceEntry
lea edi,[esi+eax]
push esi edi
lea esi,[edi+SourceEntry.type]
mov ecx,1
call display_error_string
pop edi esi
find_file_source:
cmp [edi+SourceEntry.type],SOURCE_FILE
jne try_next_source_entry
cmp [edi+SourceEntry.line_number],0
jne file_source_found
try_next_source_entry:
cmp edi,esi
je no_file_source
sub edi,sizeof.SourceEntry
jmp find_file_source
file_source_found:
lea esi,[edi+SourceEntry.line_number]
mov ecx,4
push edi
call display_error_string
pop edi
mov esi,[edi+SourceEntry.name]
call display_error_string
jmp error_collected
no_file_source:
xor esi,esi
mov ecx,4
call display_error_string
error_collected:
xor esi,esi
mov ecx,1
call display_error_string
mov ebx,[ebx+Error.next]
test ebx,ebx
jnz collect_error
call assembly_shutdown
mov eax,2
jmp shutdown
write_failed:
call assembly_shutdown
mov esi,_write_failed
jmp fatal_error
out_of_memory:
call assembly_shutdown
mov esi,_out_of_memory
fatal_error:
xor ecx,ecx
call display_error_string
mov eax,1
shutdown:
push eax
invoke PostMessage,[hwnd_compiler],WM_COMMAND,IDOK,0
call [ExitThread]
LINE_FEED equ 13,10
system_init:
invoke HeapCreate,0,20000h,0
mov [memory],eax
test eax,eax
jz out_of_memory
invoke GetSystemTime,systemtime
invoke SystemTimeToFileTime,systemtime,filetime
mov ebx,[filetime.dwLowDateTime]
mov eax,[filetime.dwHighDateTime]
sub ebx,116444736000000000 and 0FFFFFFFFh
sbb eax,116444736000000000 shr 32
xor edx,edx
mov ecx,10000000
div ecx
mov dword [timestamp+4],eax
mov eax,ebx
div ecx
mov dword [timestamp],eax
retn
system_shutdown:
cmp [memory],0
je memory_released
invoke HeapDestroy,[memory]
memory_released:
retn
malloc:
malloc_fixed:
malloc_growable:
; in: ecx = requested size
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
; preserves: ebx, esi, edi
; note:
; use of malloc_fixed hints that block will be kept as is until the end of assembly
; use of malloc_growable hints that block is likely to be resized
invoke HeapAlloc,[memory],0,ecx
test eax,eax
jz out_of_memory
memory_allocated:
push eax
invoke HeapSize,[memory],0,eax
mov ecx,eax
pop eax
cmp ecx,-1
je out_of_memory
retn
realloc:
; in: eax - memory block, ecx = requested size
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
; preserves: ebx, esi, edi
invoke HeapReAlloc,[memory],0,eax,ecx
test eax,eax
jnz memory_allocated
jmp out_of_memory
mfree:
; in: eax - memory block
; out: cf set on error
; preserves: ebx, esi, edi
; note: eax may have value 0 or -1, it should be treated as invalid input then
test eax,eax
jz interface_error
cmp eax,-1
je interface_error
invoke HeapFree,[memory],0,eax
test eax,eax
jz interface_error
clc
retn
interface_error:
stc
retn
open:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
mov ebx,edx
invoke WaitForSingleObject,[mutex],-1
invoke CreateFile,ebx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
cmp eax,-1
je release_mutex
mov ebx,eax
clc
retn
create:
; in: edx - path to file
; out: ebx = file handle, cf set on error
; preserves: esi, edi
cmp [executable_path],0
jne path_catching_done
push esi edi
mov esi,edx
mov edi,executable_path
catch_path:
lodsb
stosb
test al,al
jnz catch_path
pop edi esi
path_catching_done:
mov ebx,edx
invoke WaitForSingleObject,[mutex],-1
invoke CreateFile,ebx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
cmp eax,-1
je release_mutex
mov ebx,eax
clc
retn
write:
; in: ebx = file handle, edx - data, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push ecx
invoke WriteFile,ebx,edx,ecx,systmp,0
pop ecx
test eax,eax
jz interface_error
cmp ecx,[systmp]
jne interface_error
clc
retn
read:
; in: ebx = file handle, edx - buffer, ecx = number of bytes
; out: cf set on error
; preserves: ebx, esi, edi
push ecx
invoke ReadFile,ebx,edx,ecx,systmp,0
pop ecx
test eax,eax
jz interface_error
cmp ecx,[systmp]
jne interface_error
clc
retn
close:
; in: ebx = file handle
; preserves: ebx, esi, edi
invoke CloseHandle,ebx
release_mutex:
invoke ReleaseMutex,[mutex] ; this relies on the fact that engine never opens more than one file at once
stc
retn
lseek:
; in: ebx = file handle, cl = method, edx:eax = offset
; out: edx:eax = new offset from the beginning of file, cf set on error
; preserves: ebx, esi, edi
movzx ecx,cl
mov [systmp],edx
invoke SetFilePointer,ebx,eax,systmp,ecx
cmp eax,-1
jne lseek_ok
invoke GetLastError
test eax,eax
jnz interface_error
not eax
lseek_ok:
mov edx,[systmp]
clc
retn
get_timestamp:
; out: edx:eax = timestamp
; preserves: ebx, ecx, esi, edi
; note: during the passes of a single assembly this function should always return the same value
mov eax,dword [timestamp]
mov edx,dword [timestamp+4]
retn
display_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx
mov ebx,stdout
jmp write_string
display_error_string:
; in:
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, esi
push ebx esi
mov ebx,stderr
write_string:
test ecx,ecx
jnz write_string_to_buffer
xor al,al
mov edi,esi
or ecx,-1
repne scasb
neg ecx
sub ecx,2
write_string_to_buffer:
mov edi,[ebx]
push ecx
invoke HeapSize,[hheap],0,dword [ebx]
mov edx,eax
sub eax,4
sub eax,[edi]
mov ecx,[esp]
sub ecx,eax
jb string_buffer_ready ; do not fit tight, leave room for terminating zero
add edx,ecx
inc edx
invoke HeapReAlloc,[hheap],0,dword [ebx],edx
test eax,eax
jz shutdown
mov [ebx],eax
mov edi,eax
string_buffer_ready:
pop ecx
mov eax,[edi]
add [edi],ecx
lea edi,[edi+4+eax]
xor al,al
test esi,esi
jz zero_string
rep movsb
stosb
pop esi ebx
retn
zero_string:
rep stosb
pop esi ebx
retn
get_environment_variable:
; in:
; esi - name
; edi - buffer for value
; ecx = size of buffer
; out:
; eax = length of value
; preserves: ebx, esi, edi
push ecx
invoke GetEnvironmentVariable,esi,string_buffer,1000h
invoke GetPrivateProfileString,_section_environment,esi,string_buffer,string_buffer,1000h,ini_path
mov ecx,[esp]
push esi edi
mov esi,string_buffer
copy_env_val:
lodsb
jecxz next_env_char
mov [edi],al
dec ecx
next_env_char:
inc edi
test al,al
jnz copy_env_val
mov eax,edi
pop edi esi ecx
sub eax,edi
retn
include '../../assembler.inc'
include '../../symbols.inc'
include '../../expressions.inc'
include '../../conditions.inc'
include '../../floats.inc'
include '../../directives.inc'
include '../../calm.inc'
include '../../errors.inc'
include '../../map.inc'
include '../../reader.inc'
include '../../output.inc'
include '../../console.inc'
section '.rdata' data readable
include '../../tables.inc'
include '../../messages.inc'
_pass db ' pass, ',0
_passes db ' passes, ',0
_dot db '.'
_seconds db ' seconds, ',0
_byte db ' byte.',0
_bytes db ' bytes.',0
_write_failed db 'Failed to write the output file.',0
_out_of_memory db 'Not enough memory to complete the assembly.',0
_code_cannot_be_generated db 'Could not generate code within the allowed number of passes.',0
version_string db VERSION,0
section '.bss' readable writeable
include '../../variables.inc'
source_string dd ?
source_path dd ?
output_path dd ?
maximum_number_of_passes dd ?
timestamp dq ?
systemtime SYSTEMTIME
filetime FILETIME
memory dd ?
systmp dd ?
timer dd ?
stdout dd ?
stderr dd ?