Skip to content

Instantly share code, notes, and snippets.

@joseph39
Last active December 3, 2021 14:45
Show Gist options
  • Save joseph39/9799895 to your computer and use it in GitHub Desktop.
Save joseph39/9799895 to your computer and use it in GitHub Desktop.
Runtime.s for Mac OS X and Windows

Runtime.s for Mac OS X and Windows

These versions of runtime.s works by simulating the break region that is not present in either operating system. The region that it initially allocates is 4MB in size and can be increased by modifying the brk_region_size value. In case where it does run out of memory, it will jump to __exception and consequently terminate the process.

Mac OS X

runtime.s for Mac OS X does not have any library dependencies.

Windows

runtime.s for Windows needs to be linked against Kernel32.lib as it requires some of the functions exported by the kernel32 DLL.

section .text
kernel_entry:
int 0x80
ret
; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
global __malloc
__malloc:
push eax ; back-up the size to be allocated
mov eax, [brk_region] ; load the current brk region
test eax, eax ; if it's not been initialized yet, then
je initialize_brk ; initialize it
brk_initialized: ; eax now contains the region
pop ebx ; pop size to be allocated to ebx
push eax ; back it up
add eax, ebx ; adjust the pointer
mov [brk_region], eax ; store the adjusted pointer
mov eax, [brk_region_size] ; get the remaining region size
cmp eax, ebx ; if it less than the size we want to allocate
jb __exception ; goto exception
sub eax, ebx ; otherwise, update the remaining size
mov [brk_region_size], eax ; store it
pop eax ; return the backed-up pointer to the region
ret
; Initialize the brk by allocating a chunk of memory
initialize_brk:
push 0 ; offset = 0
push -1 ; fd = -1
push 0x1000 ; flag = MAP_ANONYMOUS
push 0x03 ; prot = PROT_READ | PROT_WRITE
mov eax, [brk_region_size] ; get the size of the region (predefined)
push eax
push 0 ; addr = 0
mov eax, 197
call kernel_entry ; call mmap with brk_region_size to allocate
add esp, 24 ; fix the stack pointer
cmp eax, 0xFFFFFFFF ; if it fails then
je __exception ; goto exception
mov [brk_region], eax ; set the pointer
jmp brk_initialized
; Debugging exit: ends the process, returning the value of
; eax as the exit code.
global __debexit
__debexit:
push eax ; status
mov eax, 1
call kernel_entry ; call exit
; Exceptional exit: ends the process with exit code 13.
; Call this in cases where the Joos code would throw an exception.
global __exception
__exception:
push 13 ; status = 13
mov eax, 1
call kernel_entry ; call exit
; Implementation of java.io.OutputStream.nativeWrite method.
; Outputs the low-order byte of eax to standard output.
global NATIVEjava.io.OutputStream.nativeWrite
NATIVEjava.io.OutputStream.nativeWrite:
mov [char], al ; save the low order byte in memory
push 1 ; nbyte = 1
push char ; buf = char
push 1 ; fd = stdout
mov eax, 4
call kernel_entry ; call write
add esp, 12 ; fix the stack pointer
mov eax, 0 ; return 0
ret
section .data
brk_region_size:
dd 4194304
brk_region:
dd 0
char:
dd 0
extern _GetStdHandle@4
extern _WriteConsoleA@20
extern _ExitProcess@4
extern _VirtualAlloc@16
section .bss
numCharsWritten: resb 1
section .text
; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
global __malloc
__malloc:
push eax ; back-up the size to be allocated
mov eax, [brk_region] ; load the current brk region
test eax, eax ; if it's not been initialized yet, then
je initialize_brk ; initialize it
brk_initialized: ; eax now contains the region
pop ebx ; pop size to be allocated to ebx
push eax ; back it up
add eax, ebx ; adjust the pointer
mov [brk_region], eax ; store the adjusted pointer
mov eax, [brk_region_size] ; get the remaining region size
cmp eax, ebx ; if it less than the size we want to allocate
jb __exception ; goto exception
sub eax, ebx ; otherwise, update the remaining size
mov [brk_region_size], eax ; store it
pop eax ; return the backed-up pointer to the region
ret
; Initialize the brk by allocating a chunk of memory
initialize_brk:
push 0x04 ; flag = PAGE_READWRITE
push 0x3000 ; fAllocationType = MEM_COMMIT | MEM_RESERVE
mov eax, [brk_region_size] ; get the size of the region (predefined)
push eax
push 0 ; lpAddress = 0
mov eax, 197
call _VirtualAlloc@16 ; call VirtualAlloc with brk_region_size to allocate
test eax, eax ; if it fails then
je __exception ; goto exception
mov [brk_region], eax ; set the pointer
jmp brk_initialized
; Debugging exit: ends the process, returning the value of
; eax as the exit code.
global __debexit
__debexit:
push eax ; Arg1: push exit code
call _ExitProcess@4
; Exceptional exit: ends the process with exit code 13.
; Call this in cases where the Joos code would throw an exception.
global __exception
__exception:
push dword 13
call _ExitProcess@4
; Implementation of java.io.OutputStream.nativeWrite method.
; Outputs the low-order byte of eax to standard output.
global NATIVEjava.io.OutputStream.nativeWrite
NATIVEjava.io.OutputStream.nativeWrite:
; get std handle
mov [char], al ; save the low order byte in memory
push dword -11
call _GetStdHandle@4
push dword 0 ; Arg5: Unused so just use zero
push numCharsWritten ; Arg4: push pointer to numCharsWritten
push dword 1 ; Arg3: push length of output string
push char ; Arg2: push pointer to output string
push eax ; Arg1: push handle returned from _GetStdHandle
call _WriteConsoleA@20
mov eax, 0 ; return 0
ret
section .data
brk_region_size:
dd 4194304
brk_region:
dd 0
char:
dd 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment