add flat assembler toolchain
This commit is contained in:
108
toolchain/fasmw17332/SOURCE/DOS/DPMI.INC
Normal file
108
toolchain/fasmw17332/SOURCE/DOS/DPMI.INC
Normal 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
|
435
toolchain/fasmw17332/SOURCE/DOS/FASM.ASM
Normal file
435
toolchain/fasmw17332/SOURCE/DOS/FASM.ASM
Normal 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
|
539
toolchain/fasmw17332/SOURCE/DOS/MODES.INC
Normal file
539
toolchain/fasmw17332/SOURCE/DOS/MODES.INC
Normal 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
|
600
toolchain/fasmw17332/SOURCE/DOS/SYSTEM.INC
Normal file
600
toolchain/fasmw17332/SOURCE/DOS/SYSTEM.INC
Normal 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
|
Reference in New Issue
Block a user