You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
681 lines
13 KiB
681 lines
13 KiB
2 years ago
|
.include "instr.inc"
|
||
|
.text
|
||
|
|
||
|
mem_e000:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_e002:
|
||
|
.fill 0x0efe
|
||
|
|
||
|
mem_ef00:
|
||
|
.fill 0xb0
|
||
|
|
||
|
mem_efb0:
|
||
|
.fill 0x30
|
||
|
|
||
|
mem_efe0:
|
||
|
.fill 0x20
|
||
|
|
||
|
.global _start
|
||
|
_start:
|
||
|
ld_sp stack
|
||
|
|
||
|
# Set up the entrypoint for the breakpoint instruction
|
||
|
ld_r0 entry
|
||
|
ld_r1 0x98 # 'call'
|
||
|
strb_r1_r0
|
||
|
inc_r0
|
||
|
ld_r1 main
|
||
|
str_r1_r0
|
||
|
|
||
|
# Explain the debugger
|
||
|
ld_r2 str_intro
|
||
|
call PrintStr
|
||
|
|
||
|
# Execute the breakpoint, jump to main
|
||
|
brk
|
||
|
|
||
|
# If breakpoint returns here, we've ran out of stack
|
||
|
ld_r2 str_dry_stack
|
||
|
call PrintStr
|
||
|
copr_halt
|
||
|
die:
|
||
|
jp die
|
||
|
|
||
|
main:
|
||
|
# Save all the registers
|
||
|
push_sp
|
||
|
str_r0 mem_save_r0
|
||
|
str_r1 mem_save_r1
|
||
|
str_r2 mem_save_r2
|
||
|
str_r3 mem_save_r3
|
||
|
|
||
|
# Store the stack pointer
|
||
|
pop_r0
|
||
|
str_r0 mem_info_sp
|
||
|
|
||
|
# Read the return address
|
||
|
ld_r0_sp
|
||
|
ldr_r0_r0
|
||
|
add_r0 -1
|
||
|
str_r0 mem_info_pc
|
||
|
|
||
|
# Read some more stack values
|
||
|
ld_r1 (6 * 2)
|
||
|
ld_r2 mem_info_stack
|
||
|
ldr_r3 mem_info_sp
|
||
|
call MemCpy
|
||
|
|
||
|
# Print the processor state
|
||
|
ld_r2 str_breakpoint
|
||
|
call PrintStr
|
||
|
|
||
|
main_cmd_loop:
|
||
|
ld_r0 0
|
||
|
strb_r0 mem_e002
|
||
|
|
||
|
ld_r2 str_ready
|
||
|
call PrintStr
|
||
|
|
||
|
# Read input
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
cp_r3 0
|
||
|
jp_eq error_too_long
|
||
|
ld_r2 mem_e000
|
||
|
call StrTrim
|
||
|
|
||
|
# Make sure the input is at most 2 characters
|
||
|
ldrb_r0 mem_e002
|
||
|
cp_r0 0
|
||
|
jp_ne error_bad_command
|
||
|
|
||
|
# Parse all the commands
|
||
|
ldr_r0 mem_e000
|
||
|
|
||
|
cp_r0 ('h' + '\n' * 0x100)
|
||
|
jp_eq cmd_help
|
||
|
cp_r0 'h'
|
||
|
jp_eq cmd_help
|
||
|
|
||
|
cp_r0 'r'
|
||
|
jp_eq cmd_read
|
||
|
cp_r0 ('r' + '\n' * 0x100)
|
||
|
jp_eq cmd_read
|
||
|
|
||
|
cp_r0 'p'
|
||
|
jp_eq cmd_print
|
||
|
cp_r0 ('p' + '\n' * 0x100)
|
||
|
jp_eq cmd_print
|
||
|
|
||
|
cp_r0 'x'
|
||
|
jp_eq cmd_exec
|
||
|
cp_r0 ('x' + '\n' * 0x100)
|
||
|
jp_eq cmd_exec
|
||
|
|
||
|
cp_r0 'c'
|
||
|
jp_eq cmd_cont
|
||
|
cp_r0 ('c' + '\n' * 0x100)
|
||
|
jp_eq cmd_cont
|
||
|
|
||
|
cp_r0 ('U' + 'C' * 0x100)
|
||
|
jp_eq cmd_undoc
|
||
|
|
||
|
cp_r0 ('l' + 's' * 0x100)
|
||
|
jp_eq cmd_list
|
||
|
|
||
|
cp_r0 ('r' + 'f' * 0x100)
|
||
|
jp_eq cmd_readfile
|
||
|
|
||
|
cp_r0 'w'
|
||
|
jp_eq cmd_write
|
||
|
cp_r0 ('w' + '\n' * 0x100)
|
||
|
jp_eq cmd_write
|
||
|
|
||
|
error_bad_command:
|
||
|
ld_r2 str_error_bad_command
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
error_too_long:
|
||
|
ld_r2 str_error_too_long
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_help:
|
||
|
ld_r2 str_help
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_read:
|
||
|
# Get the address to read
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_read_invalid
|
||
|
push_r0
|
||
|
|
||
|
# Get the amount of lines to read
|
||
|
ld_r2 str_prompt_lines
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_read_invalid
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_read_invalid
|
||
|
|
||
|
# r2 = address, r3 = lines
|
||
|
ld_r3_r0
|
||
|
pop_r2
|
||
|
|
||
|
cmd_read_loop:
|
||
|
# Read 8 bytes
|
||
|
push_r2
|
||
|
push_r3
|
||
|
ld_r1 8
|
||
|
ld_r3_r2
|
||
|
ld_r2 mem_data
|
||
|
call MemCpy
|
||
|
pop_r3
|
||
|
pop_r2
|
||
|
|
||
|
# Store the current read address
|
||
|
str_r2 mem_addr
|
||
|
|
||
|
# Write it out
|
||
|
push_r2
|
||
|
push_r3
|
||
|
ld_r2 str_hexdump
|
||
|
call PrintStr
|
||
|
pop_r3
|
||
|
pop_r2
|
||
|
|
||
|
# Check if we're done
|
||
|
add_r2 8
|
||
|
dec_r3
|
||
|
cp_r3 0
|
||
|
jp_ne cmd_read_loop
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_read_invalid:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_write:
|
||
|
# Get the address to write
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_invalid
|
||
|
str_r0 mem_addr
|
||
|
|
||
|
ld_r2 str_prompt_hex
|
||
|
call PrintStr
|
||
|
|
||
|
cmd_write_loop:
|
||
|
# Clear the buffer
|
||
|
ld_r3 mem_e000 + 2
|
||
|
ld_r0 0
|
||
|
strb_r0_r3
|
||
|
dec_r3
|
||
|
strb_r0_r3
|
||
|
dec_r3
|
||
|
|
||
|
cmd_write_loop_first:
|
||
|
# Get the first nybble
|
||
|
copr_getc
|
||
|
strb_r0_r3
|
||
|
ld_r2_r3
|
||
|
|
||
|
# Check if it's the end or invalid
|
||
|
cp_r0 '.'
|
||
|
jp_eq cmd_write_end
|
||
|
cp_r0 '\n'
|
||
|
jp_eq cmd_write_loop_first
|
||
|
|
||
|
# Try to convert the nybble
|
||
|
push_r3
|
||
|
call ConvertHex
|
||
|
pop_r3
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_loop_first
|
||
|
|
||
|
inc_r3
|
||
|
|
||
|
cmd_write_loop_second:
|
||
|
# Get the second nybble
|
||
|
copr_getc
|
||
|
strb_r0_r3
|
||
|
ld_r2_r3
|
||
|
|
||
|
# Check if it's the end or invalid
|
||
|
cp_r0 '.'
|
||
|
jp_eq cmd_write_end
|
||
|
cp_r0 '\n'
|
||
|
jp_eq cmd_write_loop_second
|
||
|
|
||
|
# Try to convert the nybble
|
||
|
push_r3
|
||
|
call ConvertHex
|
||
|
pop_r3
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_loop_second
|
||
|
|
||
|
# Convert and store the full byte
|
||
|
dec_r3
|
||
|
ld_r2_r3
|
||
|
call ConvertHex
|
||
|
ldr_r1 mem_addr
|
||
|
strb_r0_r1
|
||
|
inc_r1
|
||
|
str_r1 mem_addr
|
||
|
jp cmd_write_loop # 0xf1d0
|
||
|
|
||
|
cmd_write_end:
|
||
|
# Read until newline
|
||
|
copr_getc
|
||
|
cp_r0 '\n'
|
||
|
jp_ne cmd_write_end
|
||
|
|
||
|
ld_r2 str_loaded
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_write_invalid:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_print:
|
||
|
# Get the string to print
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
|
||
|
ld_r2_r0
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_exec:
|
||
|
# Get the address to execute
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
|
||
|
# Prompt the user to execute the address
|
||
|
push_r0
|
||
|
str_r0 mem_addr
|
||
|
ld_r2 str_prompt_exec
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ldrb_r0 mem_e000
|
||
|
cp_r0 'Y'
|
||
|
jp_eq cmd_exec_go
|
||
|
cp_r0 'y'
|
||
|
jp_eq cmd_exec_go
|
||
|
|
||
|
# Cancel the call
|
||
|
ld_r2 str_error_cancelled
|
||
|
call PrintStr
|
||
|
pop_r0
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_exec_go:
|
||
|
# Call the function
|
||
|
pop_r3
|
||
|
call_r3
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_cont:
|
||
|
ld_r2 str_continuing
|
||
|
call PrintStr
|
||
|
|
||
|
# Restore register state and unpause
|
||
|
ldr_r0 mem_save_r0
|
||
|
ldr_r1 mem_save_r1
|
||
|
ldr_r2 mem_save_r2
|
||
|
ldr_r3 mem_save_r3
|
||
|
ret
|
||
|
|
||
|
cmd_list:
|
||
|
ld_r2 str_file_list_header
|
||
|
call PrintStr
|
||
|
|
||
|
# Read directory
|
||
|
ld_r0 0
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
ld_r3 mem_e000
|
||
|
cmd_list_loop:
|
||
|
ldrb_r0_r3
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_list_next
|
||
|
|
||
|
# Store block
|
||
|
push_r3
|
||
|
strb_r0 mem_data
|
||
|
inc_r3
|
||
|
ldr_r0_r3
|
||
|
|
||
|
# Store size
|
||
|
push_r3
|
||
|
str_r0 mem_addr
|
||
|
|
||
|
# Print block and size
|
||
|
ld_r2 str_file_list_entry
|
||
|
call PrintStr
|
||
|
pop_r3
|
||
|
|
||
|
# Print filename
|
||
|
inc_r3
|
||
|
inc_r3
|
||
|
ld_r2_r3
|
||
|
call PrintStr
|
||
|
ld_r0 '\n'
|
||
|
copr_putc
|
||
|
pop_r3
|
||
|
|
||
|
cmd_list_next:
|
||
|
add_r3 0x10
|
||
|
cp_r3 mem_ef00
|
||
|
jp_ne cmd_list_loop
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_undoc:
|
||
|
ld_r2 str_undoc
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile:
|
||
|
ld_r2 str_prompt_filename
|
||
|
call PrintStr
|
||
|
|
||
|
# Read directory
|
||
|
ld_r0 0
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
# Get filename to read
|
||
|
ld_r2 mem_efb0
|
||
|
ld_r3 0x10
|
||
|
call ReadStr
|
||
|
cp_r3 0
|
||
|
jp_eq cmd_readfile_error_too_long
|
||
|
ld_r2 mem_efb0
|
||
|
call StrTrim
|
||
|
|
||
|
ld_r3 mem_e000 + 3
|
||
|
cmd_readfile_loop:
|
||
|
# Check if the filename matches
|
||
|
ld_r2 mem_efb0
|
||
|
push_r3
|
||
|
call StrCmp
|
||
|
pop_r3
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_readfile_match
|
||
|
|
||
|
add_r3 0x10
|
||
|
cp_r3 mem_ef00 + 3
|
||
|
jp_eq cmd_readfile_error_not_found
|
||
|
jp cmd_readfile_loop
|
||
|
|
||
|
cmd_readfile_match:
|
||
|
# Read file block
|
||
|
dec_r3
|
||
|
dec_r3
|
||
|
dec_r3
|
||
|
ldrb_r0_r3
|
||
|
|
||
|
# Read file size
|
||
|
inc_r3
|
||
|
ldr_r1_r3
|
||
|
|
||
|
# Read file into memory
|
||
|
push_r1
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
# Prompt for address to write to
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_efe0
|
||
|
ld_r3 0x10
|
||
|
call ReadStr
|
||
|
ld_r2 mem_efe0
|
||
|
call ConvertHex
|
||
|
pop_r1
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_readfile_error_invalid_input
|
||
|
|
||
|
# Copy the data
|
||
|
ld_r2_r0
|
||
|
ld_r3 mem_e000
|
||
|
call MemCpy
|
||
|
|
||
|
ld_r2 str_loaded
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_not_found:
|
||
|
ld_r2 str_error_not_found
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_too_long:
|
||
|
ld_r2 str_error_too_long
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_invalid_input:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
str_intro:
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "Welcome to Glitch Research Laboratory Network: Test Server 1 (GRLTS01)\n"
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "GRLTS01 is intended for research purposes only, to aid our engineers\n"
|
||
|
.ascii "in migrating their software to the latest GLVM architecture.\n"
|
||
|
.ascii "This server will boot into a machine language monitor, providing\n"
|
||
|
.ascii "a simple environment for development and testing.\n"
|
||
|
.ascii "\n"
|
||
|
.ascii "Note that this server is publicly accessible, and thus, should never\n"
|
||
|
.ascii "be used to store any confidential information. If storage of data is\n"
|
||
|
.ascii "necessary, consider utilizing encryption, or using our dedicated\n"
|
||
|
.ascii "storage servers GRLFS01.\n"
|
||
|
.ascii "Additionally, consider using GRLTS02 for any serious work - it's\n"
|
||
|
.ascii "an authenticated test server, which should be far more secure.\n"
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "Running machine language monitor now.\n"
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "\n\0"
|
||
|
|
||
|
str_error_too_long:
|
||
|
.ascii "! Input too long error.\n\0"
|
||
|
|
||
|
str_error_bad_command:
|
||
|
.ascii "! Bad command error (h for help).\n\0"
|
||
|
|
||
|
str_error_invalid_input:
|
||
|
.ascii "! Invalid input error.\n\0"
|
||
|
|
||
|
str_prompt_address:
|
||
|
.ascii "> Which address? \0"
|
||
|
|
||
|
str_prompt_lines:
|
||
|
.ascii "> How many lines? \0"
|
||
|
|
||
|
str_prompt_exec:
|
||
|
.ascii "> Really exec at "
|
||
|
text_ram_word mem_addr
|
||
|
.ascii "? Type Y if so: \0"
|
||
|
|
||
|
str_error_cancelled:
|
||
|
.ascii "! Cancelled action error.\n\0"
|
||
|
|
||
|
str_continuing:
|
||
|
.ascii "Continuing.\n\0"
|
||
|
|
||
|
str_loaded:
|
||
|
.ascii "Loaded.\n\0"
|
||
|
|
||
|
str_dry_stack:
|
||
|
.ascii "! Dry stack. Halting machine.\n\0"
|
||
|
|
||
|
str_prompt_filename:
|
||
|
.ascii "> Filename? \0"
|
||
|
|
||
|
str_error_not_found:
|
||
|
.ascii "! File not found error.\n\0"
|
||
|
|
||
|
str_prompt_hex:
|
||
|
.ascii "> Enter hex data. End with dot \".\" + newline:\n\0"
|
||
|
|
||
|
str_undoc:
|
||
|
.ascii "Wow, undocumented monitor command! FOOLS2023_{Secret"
|
||
|
text_ram_word 0xe000
|
||
|
.ascii "x"
|
||
|
text_ram_word 0xe001
|
||
|
.ascii "Command}\n\0"
|
||
|
|
||
|
str_help:
|
||
|
.ascii "Available commands:\n"
|
||
|
.ascii "r :: print memory as hex\n"
|
||
|
.ascii "p :: print memory as text\n"
|
||
|
.ascii "w :: write hex data to memory\n"
|
||
|
.ascii "x :: execute memory\n"
|
||
|
.ascii "rf :: load memory from file\n"
|
||
|
.ascii "ls :: print file index\n"
|
||
|
.ascii "h :: print this help message\n"
|
||
|
.ascii "c :: exit monitor and continue\n"
|
||
|
.ascii "Please enter hex numbers when prompted.\n"
|
||
|
.ascii "If necessary for debugging, you can break into monitor\n"
|
||
|
.ascii "with instruction BRK (0x00) and continue with 'c'\n"
|
||
|
.ascii "Note: memory region E000-FFFF is used by monitor\n\0"
|
||
|
|
||
|
str_file_list_header:
|
||
|
.ascii "BLK SIZE NAME\n"
|
||
|
.ascii "=======================\n\0"
|
||
|
|
||
|
str_file_list_entry:
|
||
|
text_ram_byte mem_data
|
||
|
.ascii " "
|
||
|
text_ram_word mem_addr
|
||
|
.ascii " \0" # 0xfa97
|
||
|
|
||
|
str_ready:
|
||
|
.ascii "Ready.\n"
|
||
|
.ascii "> \0"
|
||
|
|
||
|
str_breakpoint:
|
||
|
.ascii "*** BREAK INTO MONITOR AT $"
|
||
|
text_ram_word mem_info_pc
|
||
|
.ascii " ***\n"
|
||
|
.ascii "R0=$"
|
||
|
text_ram_word mem_save_r0
|
||
|
.ascii " R1=$"
|
||
|
text_ram_word mem_save_r1
|
||
|
.ascii " R2=$"
|
||
|
text_ram_word mem_save_r2
|
||
|
.ascii " R3=$"
|
||
|
text_ram_word mem_save_r3
|
||
|
.ascii "\n"
|
||
|
.ascii "SP=$"
|
||
|
text_ram_word mem_info_sp
|
||
|
.ascii " ["
|
||
|
text_ram_byte mem_info_stack + 0
|
||
|
text_ram_byte mem_info_stack + 1
|
||
|
text_ram_byte mem_info_stack + 2
|
||
|
text_ram_byte mem_info_stack + 3
|
||
|
text_ram_byte mem_info_stack + 4
|
||
|
text_ram_byte mem_info_stack + 5
|
||
|
text_ram_byte mem_info_stack + 6
|
||
|
text_ram_byte mem_info_stack + 7
|
||
|
text_ram_byte mem_info_stack + 8
|
||
|
text_ram_byte mem_info_stack + 9
|
||
|
text_ram_byte mem_info_stack + 10
|
||
|
text_ram_byte mem_info_stack + 11
|
||
|
.ascii "]\n\0"
|
||
|
|
||
|
str_hexdump:
|
||
|
text_ram_word mem_addr
|
||
|
.ascii " | "
|
||
|
text_ram_byte mem_data + 0
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 1
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 2
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 3
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 4
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 5
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 6
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 7
|
||
|
.ascii "\n\0"
|
||
|
|
||
|
mem_save_r0:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r1:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r2:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r3:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_sp:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_pc:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_stack:
|
||
|
.fill 12
|
||
|
|
||
|
mem_data:
|
||
|
.fill 8
|
||
|
|
||
|
mem_addr:
|
||
|
.2byte 0
|
||
|
|
||
|
.fill 0xf00 - (. - _start)
|
||
|
stack:
|
||
|
.fill 0xf0
|
||
|
|
||
|
entry:
|
||
|
.fill 0x10
|