287 lines
5.2 KiB
PHP
287 lines
5.2 KiB
PHP
|
|
||
|
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||
|
|
||
|
LINE_FEED = 0Ah
|
||
|
|
||
|
system_init:
|
||
|
ccall libc.time,timestamp
|
||
|
or [local_heap_available],1
|
||
|
retn
|
||
|
|
||
|
system_shutdown:
|
||
|
retn
|
||
|
|
||
|
open:
|
||
|
; in: edx - path to file
|
||
|
; out: ebx = file handle, cf set on error
|
||
|
; preserves: esi, edi
|
||
|
push rsi rdi
|
||
|
call adapt_path
|
||
|
ccall libc.fopen,rbx,_open_mode
|
||
|
put_file_entry:
|
||
|
pop rdi rsi
|
||
|
test rax,rax
|
||
|
jz interface_error
|
||
|
push rax
|
||
|
mov eax,[files]
|
||
|
mov ecx,[files_count]
|
||
|
mov ebx,ecx
|
||
|
inc ecx
|
||
|
mov [files_count],ecx
|
||
|
cmp ecx,[files_maximum_count]
|
||
|
ja grow_files_buffer
|
||
|
store_file_entry:
|
||
|
pop rdx
|
||
|
mov [eax+ebx*8],rdx
|
||
|
clc
|
||
|
retn
|
||
|
interface_error:
|
||
|
stc
|
||
|
retn
|
||
|
grow_files_buffer:
|
||
|
shl ecx,4
|
||
|
test eax,eax
|
||
|
jz allocate_files_buffer
|
||
|
call realloc
|
||
|
jmp allocated_files_buffer
|
||
|
allocate_files_buffer:
|
||
|
call malloc
|
||
|
allocated_files_buffer:
|
||
|
mov [files],eax
|
||
|
shr ecx,3
|
||
|
mov [files_maximum_count],ecx
|
||
|
jmp store_file_entry
|
||
|
adapt_path:
|
||
|
xor ecx,ecx
|
||
|
mov ebx,path_buffer
|
||
|
copy_path:
|
||
|
mov al,[edx+ecx]
|
||
|
cmp al,'\'
|
||
|
jne path_char_ok
|
||
|
mov al,'/'
|
||
|
path_char_ok:
|
||
|
cmp ecx,1000h
|
||
|
jae out_of_memory
|
||
|
mov [ebx+ecx],al
|
||
|
inc ecx
|
||
|
test al,al
|
||
|
jnz copy_path
|
||
|
retn
|
||
|
create:
|
||
|
; in: edx - path to file
|
||
|
; out: ebx = file handle, cf set on error
|
||
|
; preserves: esi, edi
|
||
|
push rsi rdi
|
||
|
call adapt_path
|
||
|
ccall libc.fopen,rbx,_create_mode
|
||
|
jmp put_file_entry
|
||
|
write:
|
||
|
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||
|
; out: cf set on error
|
||
|
; preserves: ebx, esi, edi
|
||
|
push rbx rcx rsi rdi
|
||
|
mov eax,[files]
|
||
|
mov rax,[eax+ebx*8]
|
||
|
ccall libc.fwrite,rdx,1,rcx,rax
|
||
|
pop rdi rsi rcx rbx
|
||
|
cmp eax,ecx
|
||
|
jne interface_error
|
||
|
clc
|
||
|
ret
|
||
|
read:
|
||
|
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||
|
; out: cf set on error
|
||
|
; preserves: ebx, esi, edi
|
||
|
push rbx rcx rsi rdi
|
||
|
mov eax,[files]
|
||
|
mov rax,[eax+ebx*8]
|
||
|
ccall libc.fread,rdx,1,rcx,rax
|
||
|
pop rdi rsi rcx rbx
|
||
|
cmp eax,ecx
|
||
|
jne interface_error
|
||
|
clc
|
||
|
ret
|
||
|
close:
|
||
|
; in: ebx = file handle
|
||
|
; preserves: ebx, esi, edi
|
||
|
push rsi rdi
|
||
|
mov edi,[files]
|
||
|
mov rdi,[edi+ebx*8]
|
||
|
ccall libc.fclose,rdi
|
||
|
pop rdi rsi
|
||
|
ret
|
||
|
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
|
||
|
push rsi rdi rbx
|
||
|
shl rdx,32
|
||
|
or rax,rdx
|
||
|
movzx ecx,cl
|
||
|
mov edi,[files]
|
||
|
mov rdi,[edi+ebx*8]
|
||
|
push rdi
|
||
|
ccall libc.fseek,rdi,rax,rcx
|
||
|
test eax,eax
|
||
|
jnz lseek_error
|
||
|
pop rdi
|
||
|
ccall libc.ftell,rdi
|
||
|
cmp rax,-1
|
||
|
je lseek_error
|
||
|
mov rdx,rax
|
||
|
shr rdx,32
|
||
|
mov eax,eax
|
||
|
pop rbx rdi rsi
|
||
|
clc
|
||
|
ret
|
||
|
lseek_error:
|
||
|
pop rbx rdi rsi
|
||
|
stc
|
||
|
ret
|
||
|
|
||
|
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 rbx rsi
|
||
|
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:
|
||
|
ccall libc.write,1,rsi,rcx
|
||
|
pop rsi rbx
|
||
|
retn
|
||
|
|
||
|
display_error_string:
|
||
|
; in:
|
||
|
; esi - string
|
||
|
; ecx = string length, zero for ASCIIZ string
|
||
|
; preserves: ebx, esi
|
||
|
push rbx rsi
|
||
|
test ecx,ecx
|
||
|
jnz write_string_to_stderr
|
||
|
xor al,al
|
||
|
mov edi,esi
|
||
|
or ecx,-1
|
||
|
repne scasb
|
||
|
neg ecx
|
||
|
sub ecx,2
|
||
|
write_string_to_stderr:
|
||
|
ccall libc.write,2,rsi,rcx
|
||
|
pop rsi rbx
|
||
|
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 rbx rcx rsi rdi
|
||
|
ccall getenv,rsi
|
||
|
pop rdi rsi rcx rbx
|
||
|
test rax,rax
|
||
|
jz no_environment_variable
|
||
|
push rsi
|
||
|
mov rsi,rax
|
||
|
xor eax,eax
|
||
|
copy_environment_variable:
|
||
|
mov dl,[rsi+rax]
|
||
|
cmp eax,ecx
|
||
|
jae next_environment_variable_character
|
||
|
mov [edi+eax],dl
|
||
|
next_environment_variable_character:
|
||
|
inc eax
|
||
|
test dl,dl
|
||
|
jnz copy_environment_variable
|
||
|
pop rsi
|
||
|
environment_variable_ok:
|
||
|
ret
|
||
|
no_environment_variable:
|
||
|
mov eax,1
|
||
|
jecxz environment_variable_ok
|
||
|
and byte [edi],0
|
||
|
ret
|
||
|
|
||
|
VALLOC_MINIMUM_SIZE = 100000h
|
||
|
|
||
|
valloc:
|
||
|
; in: ecx = requested minimum size
|
||
|
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||
|
; preserves: ebx, esi, edi
|
||
|
cmp ecx,VALLOC_MINIMUM_SIZE
|
||
|
jbe valloc_size_minimum
|
||
|
dec ecx
|
||
|
and ecx,(-1) shl 12
|
||
|
add ecx,1 shl 12
|
||
|
jmp valloc_size_ready
|
||
|
valloc_size_minimum:
|
||
|
mov ecx,VALLOC_MINIMUM_SIZE
|
||
|
valloc_size_ready:
|
||
|
push rbx rsi rdi
|
||
|
cmp [local_heap_available],0
|
||
|
je valloc_mmap
|
||
|
cmp ecx,LOCAL_HEAP_SIZE
|
||
|
ja valloc_mmap
|
||
|
and [local_heap_available],0
|
||
|
mov eax,local_heap
|
||
|
mov ecx,LOCAL_HEAP_SIZE
|
||
|
jmp valloc_ok
|
||
|
valloc_mmap:
|
||
|
push rcx
|
||
|
ccall mmap,0,rcx, \
|
||
|
3, \ ; PROT_READ + PROT_WRITE
|
||
|
9002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT
|
||
|
-1,0
|
||
|
pop rsi
|
||
|
cmp eax,-1
|
||
|
je valloc_mmap_with_hint
|
||
|
mov ecx,eax
|
||
|
cmp rcx,rax
|
||
|
jne valloc_mmap_unusable
|
||
|
add ecx,esi
|
||
|
jnc mmap_ok
|
||
|
valloc_mmap_unusable:
|
||
|
ccall munmap,rax,rsi
|
||
|
valloc_mmap_with_hint:
|
||
|
push rsi
|
||
|
mov edi,[mmap_hint]
|
||
|
ccall mmap,rdi,rsi, \
|
||
|
3, \ ; PROT_READ + PROT_WRITE
|
||
|
1002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS
|
||
|
-1,0
|
||
|
pop rsi
|
||
|
cmp eax,-1
|
||
|
je valloc_failed
|
||
|
mov ecx,eax
|
||
|
cmp rcx,rax
|
||
|
jne valloc_failed
|
||
|
add ecx,esi
|
||
|
jc valloc_failed
|
||
|
mmap_ok:
|
||
|
sub ecx,eax
|
||
|
valloc_ok:
|
||
|
lea edx,[eax+ecx]
|
||
|
mov [mmap_hint],edx
|
||
|
pop rdi rsi rbx
|
||
|
retn
|
||
|
valloc_failed:
|
||
|
xor ecx,ecx
|
||
|
pop rdi rsi rbx
|
||
|
retn
|