213 lines
3.2 KiB
ArmAsm
213 lines
3.2 KiB
ArmAsm
.intel_syntax noprefix
|
|
.global _start
|
|
|
|
.data
|
|
welcome: .ascii "Welcome to Brainfuck by cat, written in ASM(GNU)!\nMax char: 65536(incl LF)!\nAllocating memory...\n\0"
|
|
msg2: .ascii "Clearing buffer...\n\0"
|
|
msg3: .ascii "Reading code...\n\0"
|
|
msg4: .ascii "Interpreting...\n\0"
|
|
error_msg_no_path: .ascii "You must specify a path as first argument!!\nAborting!\n\0"
|
|
|
|
.text
|
|
_start:
|
|
mov rdi, 1
|
|
mov rsi, offset welcome
|
|
call write
|
|
|
|
# Is file specified?
|
|
cmp qword ptr [rsp], 1
|
|
jle error_no_path
|
|
|
|
mov rdi, [rsp+16] # rsp is argc, rsp+8 is argv[0]
|
|
call open_fd
|
|
mov rbx, rax # FD
|
|
|
|
# Allocate memory
|
|
mov rdi, code_max_size
|
|
call brk_alloc
|
|
mov r12, rax # Code heap
|
|
|
|
mov rdi, max_size
|
|
call brk_alloc
|
|
mov r13, rax # Text buffer
|
|
|
|
mov rdi, max_size
|
|
call brk_alloc
|
|
mov r14, rax # Cells
|
|
|
|
mov rdi, 1
|
|
mov rsi, offset msg2
|
|
call write
|
|
|
|
# Clear the space
|
|
mov rdi, r12
|
|
mov rsi, code_max_size
|
|
call clear_heap_block
|
|
|
|
mov rdi, r13
|
|
mov rsi, max_size
|
|
call clear_heap_block
|
|
|
|
mov rdi, r14
|
|
mov rsi, max_size
|
|
call clear_heap_block
|
|
|
|
mov rdi, 1
|
|
mov rsi, offset msg3
|
|
call write
|
|
|
|
# Read from file
|
|
mov rdi, rbx
|
|
mov rsi, r12
|
|
mov rdx, code_max_size
|
|
call read
|
|
|
|
mov rdi, 1
|
|
mov rsi, offset msg4
|
|
call write
|
|
# Execution
|
|
call process_commands
|
|
|
|
# Writing result
|
|
mov rdi, 1
|
|
mov rsi, r13
|
|
call write
|
|
|
|
# Exiting procedures
|
|
mov rdi, rbx
|
|
call close_fd
|
|
|
|
xor rdi, rdi
|
|
call exit
|
|
|
|
error_no_path:
|
|
mov rdi, 1
|
|
mov rsi, offset error_msg_no_path
|
|
call write
|
|
|
|
mov rdi, 1
|
|
call exit
|
|
|
|
# r10 text pointer
|
|
# r11 code pointer
|
|
# r12 code
|
|
# r13 text
|
|
# r14 cell
|
|
# r15 cell pointer
|
|
process_commands:
|
|
xor r11, r11
|
|
xor r15, r15
|
|
mov r10, r13
|
|
process_loop:
|
|
mov r8b, [r12+r11] # Get char
|
|
call process_symbol
|
|
inc r11
|
|
cmp r8b, 0
|
|
jne process_loop
|
|
ret
|
|
|
|
# r8b = char
|
|
process_symbol:
|
|
cmp r8b, 43 # +
|
|
je process_inc
|
|
|
|
cmp r8b, 45 # -
|
|
je process_dec
|
|
|
|
cmp r8b, 60 # <
|
|
je process_back
|
|
|
|
cmp r8b, 62 # >
|
|
je process_forw
|
|
|
|
cmp r8b, 46 # .
|
|
je process_prnt
|
|
|
|
cmp r8b, 44 # ,
|
|
je process_inpt
|
|
|
|
cmp r8b, 91 # [
|
|
je process_loop_start
|
|
|
|
cmp r8b, 93 # ]
|
|
je process_loop_end
|
|
|
|
ret
|
|
|
|
# Ret's here return to process_loop not process_symbol due to Jcc
|
|
process_inc:
|
|
inc byte ptr [r14+r15]
|
|
ret
|
|
|
|
process_dec:
|
|
dec byte ptr [r14+r15]
|
|
ret
|
|
|
|
# you can't go below or above allocated memory
|
|
process_forw:
|
|
cmp r15, max_size
|
|
je 1f
|
|
inc r15
|
|
1:
|
|
ret
|
|
|
|
process_back:
|
|
cmp r15, 0
|
|
je 1f
|
|
dec r15
|
|
1:
|
|
ret
|
|
|
|
process_prnt:
|
|
mov r9b, [r14+r15]
|
|
mov byte ptr [r10], r9b
|
|
inc r10
|
|
ret
|
|
|
|
process_inpt:
|
|
# Gotta flush the buffer first
|
|
mov rdi, 1
|
|
mov rsi, r13
|
|
call write
|
|
|
|
# Clear Text buffer
|
|
mov rdi, r10
|
|
sub rdi, r13
|
|
mov rsi, rdi
|
|
mov rdi, r13
|
|
call clear_heap_block
|
|
mov r10, r13
|
|
|
|
# Ask character
|
|
mov rdi, r14
|
|
add rdi, r15
|
|
mov rsi, rdi # char*
|
|
xor rdi, rdi # fd
|
|
mov rdx, 1 # size
|
|
call read
|
|
ret
|
|
|
|
# In stack it is
|
|
# A = Address to loop back
|
|
process_loop_start:
|
|
pop rdi
|
|
push r11 # Address to loopback
|
|
push rdi
|
|
ret
|
|
|
|
process_loop_end:
|
|
# Gotta get ret value
|
|
pop rsi
|
|
pop rax # Address
|
|
|
|
# if cell is 0 we are done with loop
|
|
cmp byte ptr [r14+r15], 0
|
|
je 1f
|
|
mov r11, rax
|
|
|
|
# Make sure stack isn't caught on fire
|
|
push rax
|
|
1:
|
|
jmp rsi
|
|
|