add flat assembler toolchain
This commit is contained in:
254
toolchain/fasmg.kl0e/source/windows/dll/fasmg.asm
Normal file
254
toolchain/fasmg.kl0e/source/windows/dll/fasmg.asm
Normal file
@ -0,0 +1,254 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include 'win32a.inc'
|
||||
include 'localptr.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format PE large NX DLL
|
||||
entry DllEntryPoint
|
||||
|
||||
include '../../version.inc'
|
||||
|
||||
struct MEMORY_REGION
|
||||
address dd ?
|
||||
size dd ?
|
||||
ends
|
||||
|
||||
section '.text' code executable
|
||||
|
||||
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'
|
||||
|
||||
DllEntryPoint:
|
||||
mov eax,1
|
||||
retn 12
|
||||
|
||||
fasmg_GetVersion:
|
||||
mov eax,version_string
|
||||
retn
|
||||
|
||||
fasmg_Assemble:
|
||||
|
||||
virtual at ebp - LOCAL_VARIABLES_SIZE
|
||||
|
||||
LocalVariables:
|
||||
|
||||
include '../../variables.inc'
|
||||
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
timestamp dq ?
|
||||
systemtime SYSTEMTIME
|
||||
filetime FILETIME
|
||||
|
||||
memory dd ?
|
||||
systmp dd ?
|
||||
|
||||
rb (LocalVariables - $) and 11b
|
||||
|
||||
LOCAL_VARIABLES_SIZE = $ - LocalVariables
|
||||
|
||||
assert $ - ebp = 0
|
||||
|
||||
previous_frame dd ?
|
||||
stored_edi dd ?
|
||||
stored_esi dd ?
|
||||
stored_ebx dd ?
|
||||
return_address dd ?
|
||||
|
||||
FunctionParameters:
|
||||
|
||||
source_string dd ?
|
||||
source_path dd ?
|
||||
output_region dd ?
|
||||
output_path dd ?
|
||||
stdout dd ?
|
||||
stderr dd ?
|
||||
|
||||
FUNCTION_PARAMETERS_SIZE = $ - FunctionParameters
|
||||
|
||||
end virtual
|
||||
|
||||
push ebx esi edi
|
||||
enter LOCAL_VARIABLES_SIZE,0
|
||||
|
||||
call system_init
|
||||
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1000
|
||||
mov [maximum_depth_of_stack],10000
|
||||
|
||||
xor al,al
|
||||
call assembly_init
|
||||
|
||||
assemble:
|
||||
mov esi,[source_string]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-2
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
mov esi,[output_region]
|
||||
test esi,esi
|
||||
jz output_copied
|
||||
call get_output_length
|
||||
test edx,edx
|
||||
jnz out_of_memory
|
||||
mov [value_length],eax
|
||||
xchg eax,[esi+MEMORY_REGION.size]
|
||||
cmp [esi+MEMORY_REGION.address],0
|
||||
je new_region_for_output
|
||||
cmp eax,[value_length]
|
||||
jae copy_output
|
||||
invoke VirtualAlloc,[esi+MEMORY_REGION.address],[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE
|
||||
test eax,eax
|
||||
jnz copy_output
|
||||
invoke VirtualFree,[esi+MEMORY_REGION.address],0,MEM_RELEASE
|
||||
new_region_for_output:
|
||||
invoke VirtualAlloc,0,[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
mov [esi+MEMORY_REGION.address],eax
|
||||
copy_output:
|
||||
mov edi,[esi+MEMORY_REGION.address]
|
||||
xor eax,eax
|
||||
mov dword [file_offset],eax
|
||||
mov dword [file_offset+4],eax
|
||||
call read_from_output
|
||||
output_copied:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
mov eax,ebx
|
||||
or eax,edi
|
||||
jz output_written
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
output_written:
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
xor eax,eax
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
assembly_failed:
|
||||
mov eax,[first_error]
|
||||
xor ecx,ecx
|
||||
count_errors:
|
||||
inc ecx
|
||||
mov eax,[eax+Error.next]
|
||||
test eax,eax
|
||||
jnz count_errors
|
||||
push ecx
|
||||
call show_errors
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
pop eax
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
write_failed:
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-3
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
out_of_memory:
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-1
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
section '.rdata' data readable
|
||||
|
||||
data import
|
||||
|
||||
library kernel32,'KERNEL32.DLL'
|
||||
|
||||
import kernel32,\
|
||||
CloseHandle,'CloseHandle',\
|
||||
CreateFile,'CreateFileA',\
|
||||
ExitProcess,'ExitProcess',\
|
||||
GetCommandLine,'GetCommandLineA',\
|
||||
GetEnvironmentVariable,'GetEnvironmentVariableA',\
|
||||
GetStdHandle,'GetStdHandle',\
|
||||
GetSystemTime,'GetSystemTime',\
|
||||
GetTickCount,'GetTickCount',\
|
||||
HeapAlloc,'HeapAlloc',\
|
||||
HeapCreate,'HeapCreate',\
|
||||
HeapDestroy,'HeapDestroy',\
|
||||
HeapFree,'HeapFree',\
|
||||
HeapReAlloc,'HeapReAlloc',\
|
||||
HeapSize,'HeapSize',\
|
||||
VirtualAlloc,'VirtualAlloc',\
|
||||
VirtualFree,'VirtualFree',\
|
||||
ReadFile,'ReadFile',\
|
||||
SetFilePointer,'SetFilePointer',\
|
||||
SystemTimeToFileTime,'SystemTimeToFileTime',\
|
||||
WriteFile,'WriteFile',\
|
||||
GetLastError,'GetLastError'
|
||||
|
||||
end data
|
||||
|
||||
align 4
|
||||
|
||||
data export
|
||||
|
||||
export 'FASMG.DLL',\
|
||||
fasmg_GetVersion,'fasmg_GetVersion',\
|
||||
fasmg_Assemble,'fasmg_Assemble'
|
||||
|
||||
end data
|
||||
|
||||
include '../../tables.inc'
|
||||
include '../../messages.inc'
|
||||
|
||||
version_string db VERSION,0
|
||||
|
||||
section '.reloc' fixups data readable discardable
|
||||
|
28
toolchain/fasmg.kl0e/source/windows/dll/localptr.inc
Normal file
28
toolchain/fasmg.kl0e/source/windows/dll/localptr.inc
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
macro pushd arg
|
||||
{
|
||||
if arg eqtype +ebp & arg relativeto ebp
|
||||
if arg - ebp
|
||||
push eax
|
||||
lea eax,[arg]
|
||||
xchg eax,[esp]
|
||||
else
|
||||
push ebp
|
||||
end if
|
||||
else if ~ arg eq
|
||||
pushd arg
|
||||
end if
|
||||
}
|
||||
|
||||
macro mov dest,src
|
||||
{
|
||||
if src eqtype +ebp & src relativeto ebp
|
||||
if src - ebp
|
||||
lea dest,[src]
|
||||
else
|
||||
mov dest,ebp
|
||||
end if
|
||||
else
|
||||
mov dest,src
|
||||
end if
|
||||
}
|
266
toolchain/fasmg.kl0e/source/windows/dll/selfhost.inc
Normal file
266
toolchain/fasmg.kl0e/source/windows/dll/selfhost.inc
Normal file
@ -0,0 +1,266 @@
|
||||
|
||||
include '../../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.PE? settings
|
||||
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||
PE.Settings.DllCharacteristics = 0
|
||||
PE.Settings.Stamp = +VERSION
|
||||
PE.Settings.LegacyHeaders = 0
|
||||
local seq
|
||||
define seq settings:
|
||||
while 1
|
||||
match :, seq
|
||||
break
|
||||
else match =DLL? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
|
||||
redefine seq more
|
||||
else match =large? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE
|
||||
redefine seq more
|
||||
else match =WDM? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
|
||||
redefine seq more
|
||||
else match =NX? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
redefine seq more
|
||||
else match =at? base =on? stub :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else match =at? base :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
break
|
||||
else match =on? stub :, seq
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else
|
||||
match =GUI? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
redefine seq more
|
||||
else match =console? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
redefine seq more
|
||||
else match =native? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
|
||||
PE.Settings.SectionAlignment = 32
|
||||
PE.Settings.FileAlignment = 32
|
||||
redefine seq more
|
||||
else match =EFI? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
|
||||
redefine seq more
|
||||
else match =EFIboot? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
|
||||
redefine seq more
|
||||
else match =EFIruntime? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
|
||||
redefine seq more
|
||||
else
|
||||
err 'invalid argument'
|
||||
break
|
||||
end match
|
||||
match V.v more, seq
|
||||
PE.Settings.MajorSubsystemVersion = V
|
||||
PE.Settings.MinorSubsystemVersion = v
|
||||
redefine seq more
|
||||
end match
|
||||
end match
|
||||
end while
|
||||
if PE.Settings.Characteristics and IMAGE_FILE_DLL
|
||||
format binary as 'dll'
|
||||
else
|
||||
format binary as 'exe'
|
||||
end if
|
||||
include '../../../examples/x86/include/format/pe.inc'
|
||||
use32
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
calminstruction invoke? proc*,args&
|
||||
local tmp, tmpst, stack
|
||||
match , args
|
||||
jyes go
|
||||
collect:
|
||||
match tmpst=,args, args
|
||||
take stack, tmpst
|
||||
jyes collect
|
||||
push:
|
||||
match tmp], args
|
||||
jyes regular
|
||||
check args relativeto ebp & args - ebp
|
||||
jno regular
|
||||
arrange tmp, =push =eax
|
||||
assemble tmp
|
||||
arrange tmp, =lea =eax,[args]
|
||||
assemble tmp
|
||||
arrange tmp, =xchg =eax,[=esp]
|
||||
assemble tmp
|
||||
jump next
|
||||
regular:
|
||||
arrange tmp, =pushd args
|
||||
assemble tmp
|
||||
next:
|
||||
take args, stack
|
||||
jyes push
|
||||
go:
|
||||
arrange tmp, =call [proc]
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
|
||||
calminstruction mov? dest*,src*
|
||||
local tmp
|
||||
match tmp], src
|
||||
jyes regular
|
||||
check src relativeto ebp & src - ebp
|
||||
jno regular
|
||||
arrange tmp, =lea dest,[src]
|
||||
assemble tmp
|
||||
exit
|
||||
regular:
|
||||
arrange tmp, =mov dest,src
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 4
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dd RVA name.label
|
||||
else
|
||||
dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dd 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dd RVA name.label
|
||||
else
|
||||
label dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dd 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro export dllname,exports&
|
||||
iterate <label,string>, exports
|
||||
|
||||
local module,addresses,names,ordinal,count
|
||||
count = %%
|
||||
dd 0,0,0,RVA module,1
|
||||
dd count,count,RVA addresses,RVA names,RVA ordinal
|
||||
addresses:
|
||||
repeat count
|
||||
indx %
|
||||
dd RVA label
|
||||
end repeat
|
||||
names:
|
||||
repeat count
|
||||
dd RVA names.name#%
|
||||
end repeat
|
||||
ordinal:
|
||||
repeat count
|
||||
dw %-1
|
||||
end repeat
|
||||
module db dllname,0
|
||||
repeat count
|
||||
indx %
|
||||
names.name#% db string,0
|
||||
end repeat
|
||||
|
||||
local x,y,z,str1,str2,v1,v2
|
||||
x = count shr 1
|
||||
while x > 0
|
||||
y = x
|
||||
while y < count
|
||||
z = y
|
||||
while z-x >= 0
|
||||
load v1:dword from names+z*4
|
||||
str1 = ($-(RVA $))+v1
|
||||
load v2:dword from names+(z-x)*4
|
||||
str2 = ($-(RVA $))+v2
|
||||
while v1 > 0
|
||||
load v1:byte from str1+%-1
|
||||
load v2:byte from str2+%-1
|
||||
if v1 <> v2
|
||||
break
|
||||
end if
|
||||
end while
|
||||
if v1 < v2
|
||||
load v1:dword from names+z*4
|
||||
load v2:dword from names+(z-x)*4
|
||||
store v1:dword at names+(z-x)*4
|
||||
store v2:dword at names+z*4
|
||||
load v1:word from ordinal+z*2
|
||||
load v2:word from ordinal+(z-x)*2
|
||||
store v1:word at ordinal+(z-x)*2
|
||||
store v2:word at ordinal+z*2
|
||||
else
|
||||
break
|
||||
end if
|
||||
z = z-x
|
||||
end while
|
||||
y = y+1
|
||||
end while
|
||||
x = x shr 1
|
||||
end while
|
||||
|
||||
break
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
include '../kernel32.inc'
|
214
toolchain/fasmg.kl0e/source/windows/dll/system.inc
Normal file
214
toolchain/fasmg.kl0e/source/windows/dll/system.inc
Normal file
@ -0,0 +1,214 @@
|
||||
|
||||
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
|
||||
invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push 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
|
||||
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
|
||||
mov ebx,[stderr]
|
||||
write_string:
|
||||
test ebx,ebx
|
||||
jz hidden_display
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov edx,esi
|
||||
write_portion_to_stdout:
|
||||
mov eax,51200
|
||||
cmp ecx,eax
|
||||
jbe final_write_to_stdout
|
||||
sub ecx,eax
|
||||
add eax,edx
|
||||
push eax ecx
|
||||
invoke WriteFile,ebx,edx,51200,systmp,0
|
||||
pop ecx edx
|
||||
jmp write_portion_to_stdout
|
||||
final_write_to_stdout:
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
hidden_display:
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke GetEnvironmentVariable,esi,edi,ecx
|
||||
pop ecx
|
||||
cmp eax,ecx
|
||||
jae environment_variable_ready
|
||||
mov byte [edi+eax],0
|
||||
environment_variable_ready:
|
||||
inc eax
|
||||
retn
|
529
toolchain/fasmg.kl0e/source/windows/fasmg.asm
Normal file
529
toolchain/fasmg.kl0e/source/windows/fasmg.asm
Normal file
@ -0,0 +1,529 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include 'win32a.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
|
||||
format PE large NX console 4.0
|
||||
entry start
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
section '.text' code executable
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
start:
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
movzx ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
invoke GetTickCount
|
||||
mov [timer],eax
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
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_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[timer]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],al
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
invoke GetCommandLine
|
||||
mov esi,eax
|
||||
mov edi,eax
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
sub edi,esi
|
||||
mov ecx,edi
|
||||
call malloc
|
||||
mov edi,eax
|
||||
get_argument:
|
||||
xor ah,ah
|
||||
read_character:
|
||||
lodsb
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,22h
|
||||
je switch_quote
|
||||
cmp ax,20h
|
||||
je end_argument
|
||||
stosb
|
||||
jmp read_character
|
||||
end_argument:
|
||||
xor al,al
|
||||
stosb
|
||||
find_next_argument:
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,20h
|
||||
jne next_argument_found
|
||||
inc esi
|
||||
jmp find_next_argument
|
||||
switch_quote:
|
||||
xor ah,1
|
||||
jmp read_character
|
||||
next_argument_found:
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp al,'/'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
je get_source_path
|
||||
cmp [output_path],0
|
||||
je get_output_path
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
retn
|
||||
get_source_path:
|
||||
mov [source_path],edi
|
||||
jmp get_argument
|
||||
get_output_path:
|
||||
mov [output_path],edi
|
||||
jmp get_argument
|
||||
no_more_arguments:
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
stosb
|
||||
retn
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
mov al,[esi]
|
||||
cmp al,20h
|
||||
je find_next_argument
|
||||
test al,al
|
||||
jnz error_in_arguments
|
||||
jmp find_next_argument
|
||||
set_verbose_mode:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],dl
|
||||
jmp find_next_argument
|
||||
set_errors_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp find_next_argument
|
||||
set_recursion_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp find_next_argument
|
||||
set_passes_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
jmp find_next_argument
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je option_value_ok
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
push edi
|
||||
find_command_segment:
|
||||
cmp byte [esi],20h
|
||||
jne command_segment_found
|
||||
inc esi
|
||||
jmp find_command_segment
|
||||
command_segment_found:
|
||||
xor ah,ah
|
||||
cmp byte [esi],22h
|
||||
jne measure_command_segment
|
||||
inc esi
|
||||
inc ah
|
||||
measure_command_segment:
|
||||
mov ebx,esi
|
||||
scan_command_segment:
|
||||
mov ecx,esi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz command_segment_measured
|
||||
cmp ax,20h
|
||||
je command_segment_measured
|
||||
cmp ax,22h
|
||||
je command_segment_measured
|
||||
inc esi
|
||||
cmp al,22h
|
||||
jne scan_command_segment
|
||||
command_segment_measured:
|
||||
sub ecx,ebx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
xchg esi,ebx
|
||||
rep movsb
|
||||
mov esi,ebx
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz initial_command_ready
|
||||
cmp al,20h
|
||||
jne command_segment_found
|
||||
initial_command_ready:
|
||||
mov edi,[initial_commands]
|
||||
add edi,[initial_commands_length]
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
inc [initial_commands_length]
|
||||
pop edi
|
||||
jmp find_next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include '../symbols.inc'
|
||||
include '../assembler.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 '.bss' readable writeable
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
stdout dd ?
|
||||
stderr dd ?
|
||||
memory dd ?
|
||||
timestamp dq ?
|
||||
systemtime SYSTEMTIME
|
||||
filetime FILETIME
|
||||
systmp dd ?
|
||||
|
||||
timer dd ?
|
||||
verbosity_level db ?
|
||||
no_logo db ?
|
||||
|
||||
section '.rdata' data readable
|
||||
|
||||
data import
|
||||
|
||||
library kernel32,'KERNEL32.DLL'
|
||||
|
||||
import kernel32,\
|
||||
CloseHandle,'CloseHandle',\
|
||||
CreateFile,'CreateFileA',\
|
||||
ExitProcess,'ExitProcess',\
|
||||
GetCommandLine,'GetCommandLineA',\
|
||||
GetEnvironmentVariable,'GetEnvironmentVariableA',\
|
||||
GetStdHandle,'GetStdHandle',\
|
||||
GetSystemTime,'GetSystemTime',\
|
||||
GetTickCount,'GetTickCount',\
|
||||
HeapAlloc,'HeapAlloc',\
|
||||
HeapCreate,'HeapCreate',\
|
||||
HeapDestroy,'HeapDestroy',\
|
||||
HeapFree,'HeapFree',\
|
||||
HeapReAlloc,'HeapReAlloc',\
|
||||
HeapSize,'HeapSize',\
|
||||
ReadFile,'ReadFile',\
|
||||
SetFilePointer,'SetFilePointer',\
|
||||
SystemTimeToFileTime,'SystemTimeToFileTime',\
|
||||
WriteFile,'WriteFile',\
|
||||
GetLastError,'GetLastError'
|
||||
|
||||
end data
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,13,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',13,10
|
||||
db 'Optional settings:',13,10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',13,10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',13,10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',13,10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
96
toolchain/fasmg.kl0e/source/windows/kernel32.inc
Normal file
96
toolchain/fasmg.kl0e/source/windows/kernel32.inc
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
struct FILETIME
|
||||
dwLowDateTime dd ?
|
||||
dwHighDateTime dd ?
|
||||
ends
|
||||
|
||||
struct SYSTEMTIME
|
||||
wYear dw ?
|
||||
wMonth dw ?
|
||||
wDayOfWeek dw ?
|
||||
wDay dw ?
|
||||
wHour dw ?
|
||||
wMinute dw ?
|
||||
wSecond dw ?
|
||||
wMilliseconds dw ?
|
||||
ends
|
||||
|
||||
; Page access flags
|
||||
|
||||
PAGE_NOACCESS = 001h
|
||||
PAGE_READONLY = 002h
|
||||
PAGE_READWRITE = 004h
|
||||
PAGE_WRITECOPY = 008h
|
||||
PAGE_EXECUTE = 010h
|
||||
PAGE_EXECUTE_READ = 020h
|
||||
PAGE_EXECUTE_READWRITE = 040h
|
||||
PAGE_EXECUTE_WRITECOPY = 080h
|
||||
PAGE_GUARD = 100h
|
||||
PAGE_NOCACHE = 200h
|
||||
|
||||
; Memory allocation flags
|
||||
|
||||
MEM_COMMIT = 001000h
|
||||
MEM_RESERVE = 002000h
|
||||
MEM_DECOMMIT = 004000h
|
||||
MEM_RELEASE = 008000h
|
||||
MEM_FREE = 010000h
|
||||
MEM_PRIVATE = 020000h
|
||||
MEM_MAPPED = 040000h
|
||||
MEM_RESET = 080000h
|
||||
MEM_TOP_DOWN = 100000h
|
||||
|
||||
; Heap allocation flags
|
||||
|
||||
HEAP_NO_SERIALIZE = 1
|
||||
HEAP_GENERATE_EXCEPTIONS = 4
|
||||
HEAP_ZERO_MEMORY = 8
|
||||
|
||||
; Device handles
|
||||
|
||||
INVALID_HANDLE_VALUE = -1
|
||||
STD_INPUT_HANDLE = -10
|
||||
STD_OUTPUT_HANDLE = -11
|
||||
STD_ERROR_HANDLE = -12
|
||||
|
||||
; Access rights
|
||||
|
||||
DELETE_RIGHT = 00010000h
|
||||
READ_CONTROL = 00020000h
|
||||
WRITE_DAC = 00040000h
|
||||
WRITE_OWNER = 00080000h
|
||||
SYNCHRONIZE = 00100000h
|
||||
STANDARD_RIGHTS_READ = READ_CONTROL
|
||||
STANDARD_RIGHTS_WRITE = READ_CONTROL
|
||||
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
|
||||
STANDARD_RIGHTS_REQUIRED = 000F0000h
|
||||
STANDARD_RIGHTS_ALL = 001F0000h
|
||||
SPECIFIC_RIGHTS_ALL = 0000FFFFh
|
||||
ACCESS_SYSTEM_SECURITY = 01000000h
|
||||
MAXIMUM_ALLOWED = 02000000h
|
||||
GENERIC_READ = 80000000h
|
||||
GENERIC_WRITE = 40000000h
|
||||
GENERIC_EXECUTE = 20000000h
|
||||
GENERIC_ALL = 10000000h
|
||||
PROCESS_TERMINATE = 00000001h
|
||||
PROCESS_CREATE_THREAD = 00000002h
|
||||
PROCESS_VM_OPERATION = 00000008h
|
||||
PROCESS_VM_READ = 00000010h
|
||||
PROCESS_VM_WRITE = 00000020h
|
||||
PROCESS_DUP_HANDLE = 00000040h
|
||||
PROCESS_CREATE_PROCESS = 00000080h
|
||||
PROCESS_SET_QUOTA = 00000100h
|
||||
PROCESS_SET_INFORMATION = 00000200h
|
||||
PROCESS_QUERY_INFORMATION = 00000400h
|
||||
PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 0FFFh
|
||||
FILE_SHARE_READ = 00000001h
|
||||
FILE_SHARE_WRITE = 00000002h
|
||||
FILE_SHARE_DELETE = 00000004h
|
||||
|
||||
; CreateFile actions
|
||||
|
||||
CREATE_NEW = 1
|
||||
CREATE_ALWAYS = 2
|
||||
OPEN_EXISTING = 3
|
||||
OPEN_ALWAYS = 4
|
||||
TRUNCATE_EXISTING = 5
|
171
toolchain/fasmg.kl0e/source/windows/selfhost.inc
Normal file
171
toolchain/fasmg.kl0e/source/windows/selfhost.inc
Normal file
@ -0,0 +1,171 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.PE? settings
|
||||
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||
PE.Settings.DllCharacteristics = 0
|
||||
PE.Settings.Stamp = +VERSION
|
||||
local seq
|
||||
define seq settings:
|
||||
while 1
|
||||
match :, seq
|
||||
break
|
||||
else match =DLL? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
|
||||
redefine seq more
|
||||
else match =large? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE
|
||||
redefine seq more
|
||||
else match =WDM? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
|
||||
redefine seq more
|
||||
else match =NX? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
redefine seq more
|
||||
else match =at? base =on? stub :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else match =at? base :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
break
|
||||
else match =on? stub :, seq
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else
|
||||
match =GUI? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
redefine seq more
|
||||
else match =console? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
redefine seq more
|
||||
else match =native? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
|
||||
PE.Settings.SectionAlignment = 32
|
||||
PE.Settings.FileAlignment = 32
|
||||
redefine seq more
|
||||
else match =EFI? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
|
||||
redefine seq more
|
||||
else match =EFIboot? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
|
||||
redefine seq more
|
||||
else match =EFIruntime? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
|
||||
redefine seq more
|
||||
else
|
||||
err 'invalid argument'
|
||||
break
|
||||
end match
|
||||
match V.v more, seq
|
||||
PE.Settings.MajorSubsystemVersion = V
|
||||
PE.Settings.MinorSubsystemVersion = v
|
||||
redefine seq more
|
||||
end match
|
||||
end match
|
||||
end while
|
||||
if PE.Settings.Characteristics and IMAGE_FILE_DLL
|
||||
format binary as 'dll'
|
||||
else
|
||||
format binary as 'exe'
|
||||
end if
|
||||
include '../../examples/x86/include/format/pe.inc'
|
||||
use32
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
calminstruction invoke? proc*,args&
|
||||
local tmp, stack
|
||||
match , args
|
||||
jyes go
|
||||
collect:
|
||||
match tmp=,args, args
|
||||
take stack, tmp
|
||||
jyes collect
|
||||
push:
|
||||
arrange args, =pushd args
|
||||
assemble args
|
||||
take args, stack
|
||||
jyes push
|
||||
go:
|
||||
arrange proc, =call [proc]
|
||||
assemble proc
|
||||
end calminstruction
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 4
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dd RVA name.label
|
||||
else
|
||||
dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dd 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dd RVA name.label
|
||||
else
|
||||
label dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dd 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
||||
|
||||
include 'kernel32.inc'
|
218
toolchain/fasmg.kl0e/source/windows/system.inc
Normal file
218
toolchain/fasmg.kl0e/source/windows/system.inc
Normal file
@ -0,0 +1,218 @@
|
||||
|
||||
LINE_FEED equ 13,10
|
||||
|
||||
system_init:
|
||||
invoke GetStdHandle,STD_OUTPUT_HANDLE
|
||||
mov [stdout],eax
|
||||
invoke GetStdHandle,STD_ERROR_HANDLE
|
||||
mov [stderr],eax
|
||||
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:
|
||||
invoke CloseHandle,[stdout]
|
||||
invoke CloseHandle,[stderr]
|
||||
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
|
||||
invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push 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
|
||||
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
|
||||
mov ebx,[stderr]
|
||||
write_string:
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov edx,esi
|
||||
write_portion_to_stdout:
|
||||
mov eax,51200
|
||||
cmp ecx,eax
|
||||
jbe final_write_to_stdout
|
||||
sub ecx,eax
|
||||
add eax,edx
|
||||
push eax ecx
|
||||
invoke WriteFile,ebx,edx,51200,systmp,0
|
||||
pop ecx edx
|
||||
jmp write_portion_to_stdout
|
||||
final_write_to_stdout:
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke GetEnvironmentVariable,esi,edi,ecx
|
||||
pop ecx
|
||||
cmp eax,ecx
|
||||
jae environment_variable_ready
|
||||
mov byte [edi+eax],0
|
||||
environment_variable_ready:
|
||||
inc eax
|
||||
retn
|
||||
|
Reference in New Issue
Block a user