im not good at asm
This commit is contained in:
@ -3,11 +3,12 @@
|
|||||||
BITS 64 ; Explicitly specify 64-bit mode
|
BITS 64 ; Explicitly specify 64-bit mode
|
||||||
DEFAULT REL ; Use RIP-relative addressing by default
|
DEFAULT REL ; Use RIP-relative addressing by default
|
||||||
|
|
||||||
|
%define BUILD_DEBUG 1
|
||||||
|
|
||||||
;region DSL
|
;region DSL
|
||||||
%define marg
|
%define marg
|
||||||
|
|
||||||
%define rcounter_32 ecx
|
%define rcounter_32 ecx
|
||||||
|
|
||||||
%define r8_32 r8d
|
%define r8_32 r8d
|
||||||
|
|
||||||
%define raccumulator rax
|
%define raccumulator rax
|
||||||
@ -15,26 +16,80 @@ DEFAULT REL ; Use RIP-relative addressing by default
|
|||||||
%define rdata rdx
|
%define rdata rdx
|
||||||
%define rstack_ptr rsp
|
%define rstack_ptr rsp
|
||||||
%define rstack_base_ptr rbp
|
%define rstack_base_ptr rbp
|
||||||
|
;endregion DSL
|
||||||
|
|
||||||
%define reg9 r9
|
;region Registers
|
||||||
;endregion
|
|
||||||
|
|
||||||
;region debug
|
; Wipes all 64-bit general-purpose registers except for the stack pointer (RSP).
|
||||||
|
; Zeroing RSP would corrupt the stack and crash the program.
|
||||||
|
; Zeroing RBP will break the stack frame chain used by debuggers.
|
||||||
|
%macro wipe_gprs 0
|
||||||
|
xor rax, rax
|
||||||
|
xor rbx, rbx
|
||||||
|
xor rcx, rcx
|
||||||
|
xor rdx, rdx
|
||||||
|
xor rsi, rsi
|
||||||
|
xor rdi, rdi
|
||||||
|
; xor rbp, rbp
|
||||||
|
xor r8, r8
|
||||||
|
xor r9, r9
|
||||||
|
xor r10, r10
|
||||||
|
xor r11, r11
|
||||||
|
xor r12, r12
|
||||||
|
xor r13, r13
|
||||||
|
xor r14, r14
|
||||||
|
xor r15, r15
|
||||||
|
%endmacro
|
||||||
|
;endregion Registers
|
||||||
|
|
||||||
|
;region Debug
|
||||||
%define debug_trap 3
|
%define debug_trap 3
|
||||||
;endregion
|
|
||||||
|
%ifidn BUILD_DEBUG, 1
|
||||||
|
%macro assert_not_null 1
|
||||||
|
cmp %1, nullptr
|
||||||
|
jnz %%.passed
|
||||||
|
int debug_trap
|
||||||
|
%%.passed: ; macro-unique-prefix (%%) .passed is the label name
|
||||||
|
%endmacro
|
||||||
|
%macro slice_assert 1
|
||||||
|
cmp qword [%1 + Slice.ptr], 0
|
||||||
|
jnz %%.ptr_passed
|
||||||
|
int debug_trap
|
||||||
|
%%.ptr_passed:
|
||||||
|
cmp qword [%1 + Slice.len]
|
||||||
|
jg %%.len_passed
|
||||||
|
int debug_trap
|
||||||
|
%%.len_passed:
|
||||||
|
%endmacro
|
||||||
|
%define dbg_wipe_gprs wipe_gprs
|
||||||
|
%else
|
||||||
|
%macro assert_not_null 1
|
||||||
|
%endmacro
|
||||||
|
%macro slice_assert 1
|
||||||
|
%endmacro
|
||||||
|
%define dbg_wipe_gprs
|
||||||
|
%endif ; BUILD_DEBUG
|
||||||
|
;endregion Debug
|
||||||
|
|
||||||
;region Memory
|
;region Memory
|
||||||
|
%define nullptr 0
|
||||||
%define kilo 1024
|
%define kilo 1024
|
||||||
|
|
||||||
%define nullptr 0
|
; Usage: def_array <name: %1> <size: %2>
|
||||||
|
%macro def_farray 2+
|
||||||
%macro assert_not_null 1
|
struc %1
|
||||||
cmp %1, nullptr
|
.ptr: resb %2
|
||||||
jnz %%+.passed
|
endstruc
|
||||||
int debug_trap
|
|
||||||
%%+.passed ; macro-unique-prefix (%%) + internal expansion .passed is the label name
|
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
def_farray Mem_128k, 128 * kilo
|
||||||
|
|
||||||
|
struc Slice
|
||||||
|
.ptr: resq 1
|
||||||
|
.len: resq 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
; Usage: def_Slice %1: <slice_label>
|
; Usage: def_Slice %1: <slice_label>
|
||||||
%macro def_Slice 1
|
%macro def_Slice 1
|
||||||
struc Slice_ %+ %1
|
struc Slice_ %+ %1
|
||||||
@ -44,26 +99,36 @@ DEFAULT REL ; Use RIP-relative addressing by default
|
|||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
def_Slice Byte
|
def_Slice Byte
|
||||||
def_Slice Str8
|
|
||||||
;endregion Memory
|
;endregion Memory
|
||||||
|
|
||||||
;region Str8 Table
|
;region Strings
|
||||||
|
def_Slice Str8
|
||||||
|
|
||||||
; Usage: lit %1: <slice_label>, %2: <utf-8 literal>
|
; Usage: lit %1: <slice_label>, %2: <utf-8 literal>
|
||||||
|
; Both the struct and the string data are emitted into the current section.
|
||||||
%macro lit 2
|
%macro lit 2
|
||||||
lit_ %+ %1: db %2
|
%%str_data: db %2
|
||||||
lit_ %+ %1 %+ _len: equ $ - (lit_ %+ %1)
|
%%str_len: equ $ - %%str_data
|
||||||
|
%1:
|
||||||
|
istruc Slice_Str8
|
||||||
|
; Store the ADDRESS of the string data in the ptr field.
|
||||||
|
at Slice_Str8.ptr, dq %%str_data
|
||||||
|
; Store the pre-calculated LENGTH in the len field.
|
||||||
|
at Slice_Str8.len, dq %%str_len
|
||||||
|
iend
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
; Usage: stack_slice %1: <type>, %2 <slice id>
|
; Usage: stack_slice %1: <type>, %2 <slice id>
|
||||||
%macro stack_slice %2
|
%macro stack_slice 2
|
||||||
|
; Gemini finish this definition for me
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
section .lits progbits noexec nowrite
|
section .lits progbits noexec nowrite
|
||||||
lit path_hello_files_asm, `./code/asm/hello_files.asm`
|
lit path_hello_files_asm, `./code/asm/hello_files.asm`
|
||||||
;endregion Str8 Table
|
;endregion Strings
|
||||||
|
|
||||||
;region WinAPI
|
;region WinAPI
|
||||||
|
|
||||||
; kernel32.lib
|
; kernel32.lib
|
||||||
; Console IO
|
; Console IO
|
||||||
extern GetStdHandle
|
extern GetStdHandle
|
||||||
@ -85,52 +150,105 @@ extern ReadFile
|
|||||||
%define wapi_arg4_offset 28
|
%define wapi_arg4_offset 28
|
||||||
%define wapi_arg5_offset 32
|
%define wapi_arg5_offset 32
|
||||||
|
|
||||||
%define wapi_write_console_written_chars reg9
|
%define wapi_write_console_written_chars r9
|
||||||
%macro wapi_write_console 2
|
%macro wapi_write_console 2
|
||||||
mov rcounter,[%1] ; Console Handle
|
mov rcounter,[%1] ; Console Handle
|
||||||
lea rdata, [%2] ; Slice_Str8.Ptr
|
lea rdata, [%2] ; Slice_Str8.Ptr
|
||||||
mov r8_32, %2 %+ _len ; Slice_Str8.Len
|
mov r8_32, %2 %+ _len ; Slice_Str8.Len
|
||||||
lea reg9, [rstack_ptr + wapi_arg4_offset] ; Written chars
|
lea r9, [rstack_ptr + wapi_arg4_offset] ; Written chars
|
||||||
mov qword [rstack_ptr + wapi_arg5_offset], 0 ; Reserved (must be 0)
|
mov qword [rstack_ptr + wapi_arg5_offset], 0 ; Reserved (must be 0)
|
||||||
call WriteConsoleA
|
call WriteConsoleA
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
section .data
|
section .data
|
||||||
std_out_hndl dq 0
|
std_out_hndl dq 0
|
||||||
;endregion
|
;endregion WinAPI
|
||||||
|
|
||||||
|
struc FileOpInfo
|
||||||
|
.content: resb Slice_Byte_size ; gemini is this allowed?
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
;region api_file_read_contents
|
||||||
|
; Reg allocation:
|
||||||
|
; result: rcounter = [FileOpInfo]
|
||||||
|
; path: Slice_Str8 = { .ptr = rdata, .len = r8 }
|
||||||
|
; backing: r9 = [Slice_Byte]
|
||||||
|
%push api_file_read_contents
|
||||||
|
%define result rcounter
|
||||||
|
%define path_ptr rdata
|
||||||
|
%define path_len r8
|
||||||
|
%define backing r9
|
||||||
|
|
||||||
|
section .text
|
||||||
api_file_read_contents:
|
api_file_read_contents:
|
||||||
section .text
|
|
||||||
%define result ;TODO(Ed): figure out the convention
|
|
||||||
%define path ;TODO(Ed): figure out the convention
|
|
||||||
%define backing ;TODO(Ed): figure out the convention
|
|
||||||
|
|
||||||
assert_not_null result
|
assert_not_null result
|
||||||
slice_assert path
|
; slice_assert path
|
||||||
slice_assert backing
|
; slice_assert backing
|
||||||
; local_persist scratch_kilo: [64 * kilo]U8; (api_file_read_contents.scratch_kilo)
|
; local_persist scratch_kilo: [64 * kilo]U8; (api_file_read_contents.scratch_kilo)
|
||||||
|
|
||||||
%define slice_fmem_scratch ;TODO(Ed): figure this out
|
; %define slice_fmem_scratch ;TODO(Ed): figure this out
|
||||||
call str8_to_cstr_capped path_c_str, path, slice_fmem_scratch
|
; call str8_to_cstr_capped path_c_str, path, slice_fmem_scratch
|
||||||
|
|
||||||
; TODO(Ed): Form-fill
|
; TODO(Ed): Form-fill
|
||||||
call CreateFileA
|
; call CreateFileA
|
||||||
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
api_file_read_contents.scratch_kilo: resb 64 * kilo
|
api_file_read_contents.scratch_kilo: resb 64 * kilo
|
||||||
api_file_read_contents.path_cstr: resq 1
|
api_file_read_contents.path_cstr: resq 1
|
||||||
|
%pop api_file_read_contents
|
||||||
|
;endregion api_file_read_contents
|
||||||
|
|
||||||
|
; Args: result: [FileOpInfo], path: Slice_Str8, backing: [Slice_Byte]
|
||||||
|
%macro file_read_contents 3
|
||||||
|
%push rcounter
|
||||||
|
%push rdata
|
||||||
|
%push r8
|
||||||
|
%push r9
|
||||||
|
lea rcounter, %1
|
||||||
|
lea rdata, [%2 + Slice.ptr]
|
||||||
|
mov r8, %2 + Slice.len
|
||||||
|
lea r9, %3
|
||||||
|
call api_file_read_contents
|
||||||
|
%pop r9
|
||||||
|
%pop r8
|
||||||
|
%pop rdata
|
||||||
|
%pop rcounter
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
global main
|
global main
|
||||||
|
main:
|
||||||
|
; dbg_wipe_gprs
|
||||||
|
|
||||||
main:
|
%push calling
|
||||||
wapi_shadow_space
|
%define stack_alloc (Slice_Byte_size)
|
||||||
|
push rstack_base_ptr
|
||||||
|
mov rstack_base_ptr, rstack_ptr
|
||||||
|
sub rstack_ptr, -stack_alloc
|
||||||
|
|
||||||
; TODO(Ed): Form-fill
|
%define local_backing (rstack_base_ptr - stack_alloc)
|
||||||
|
|
||||||
|
mov qword [local_backing + Slice_Byte.ptr], read_mem
|
||||||
|
mov qword [local_backing + Slice_Byte.len], Mem_128k_size
|
||||||
|
|
||||||
|
lea rcounter, file
|
||||||
|
lea rdata, [path_hello_files_asm + Slice.ptr]
|
||||||
|
mov r8, path_hello_files_asm + Slice.len
|
||||||
|
lea r9, [local_backing]
|
||||||
call api_file_read_contents
|
call api_file_read_contents
|
||||||
|
%pop calling
|
||||||
|
|
||||||
leave
|
; file_read_contents file, path_hello_files_asm, read_mem
|
||||||
|
|
||||||
|
mov rstack_ptr, rstack_base_ptr
|
||||||
|
pop rstack_base_ptr
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
read_mem: resb Mem_128k_size
|
||||||
|
|
||||||
|
file: resb FileOpInfo_size
|
||||||
|
@ -39,6 +39,7 @@ $args = @(
|
|||||||
$hello_nasm,
|
$hello_nasm,
|
||||||
$f_optimize_none,
|
$f_optimize_none,
|
||||||
# $f_preprocess_only,
|
# $f_preprocess_only,
|
||||||
|
# ($f_dmacro + "BUILD_DEBUG 1"),
|
||||||
$f_bin_fmt_win64,
|
$f_bin_fmt_win64,
|
||||||
$f_debug_fmt_win64,
|
$f_debug_fmt_win64,
|
||||||
($f_listing + $listing),
|
($f_listing + $listing),
|
||||||
@ -54,6 +55,7 @@ $link = 'link.exe'
|
|||||||
$link_debug = '/DEBUG:'
|
$link_debug = '/DEBUG:'
|
||||||
$link_entrypoint = '/ENTRY:'
|
$link_entrypoint = '/ENTRY:'
|
||||||
$link_library = '/'
|
$link_library = '/'
|
||||||
|
$link_large_address_aware = '/LARGEADDRESSAWARE:NO'
|
||||||
$link_outfile = '/OUT:'
|
$link_outfile = '/OUT:'
|
||||||
$link_win_machine_64 = '/MACHINE:X64'
|
$link_win_machine_64 = '/MACHINE:X64'
|
||||||
$link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
|
$link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
|
||||||
@ -62,8 +64,10 @@ $rad_debug = '/RAD_DEBUG'
|
|||||||
$rad_debug_name = '/RAD_DEBUG_NAME:'
|
$rad_debug_name = '/RAD_DEBUG_NAME:'
|
||||||
$rad_large_pages = '/RAD_LARGE_PAGES:'
|
$rad_large_pages = '/RAD_LARGE_PAGES:'
|
||||||
$args = @(
|
$args = @(
|
||||||
$rad_debug,
|
$link_debug,
|
||||||
|
# $rad_debug,
|
||||||
# ($link_debug + 'FULL'),
|
# ($link_debug + 'FULL'),
|
||||||
|
$link_large_address_aware,
|
||||||
$link_win_machine_64,
|
$link_win_machine_64,
|
||||||
$link_win_subsystem_console,
|
$link_win_subsystem_console,
|
||||||
$lib_kernel32,
|
$lib_kernel32,
|
||||||
|
Reference in New Issue
Block a user