571 lines
9.1 KiB
Plaintext
571 lines
9.1 KiB
Plaintext
|
|
; 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
|