Compare commits
6 Commits
244fe869e5
...
main
Author | SHA1 | Date | |
---|---|---|---|
1ba6765c85 | |||
ceb84c9e3d | |||
15311ca7d1 | |||
d59a5c8b39 | |||
d3cb608a55 | |||
ea84361ca8 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
bf-cat
|
||||||
|
bf-cat.o
|
@@ -1,3 +1,9 @@
|
|||||||
# brainfuck-on-asm
|
# brainfuck-on-asm
|
||||||
|
|
||||||
My own brainfuck interpreter written in pure assembly and agony
|
My own brainfuck interpreter written in pure assembly and agony.
|
||||||
|
|
||||||
|
# Compile
|
||||||
|
You will need GAS(or as)! Just run ``compile.sh`` then voila!
|
||||||
|
|
||||||
|
# Running
|
||||||
|
``./bf-cat path/to/brainfuck-script``
|
||||||
|
5
compile.sh
Executable file
5
compile.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
as *.s -o bf-cat.o
|
||||||
|
ld bf-cat.o -N -o bf-cat
|
||||||
|
strip bf-cat
|
||||||
|
echo "size =" $(wc -c bf-cat) "octets"
|
4
debug.sh
Executable file
4
debug.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
as *.s -g -o bf-cat.o
|
||||||
|
ld bf-cat.o -g -o bf-cat
|
||||||
|
gdb --args ./bf-cat $@
|
132
helper.s
Normal file
132
helper.s
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
.data
|
||||||
|
error_msg_closefd: .ascii "Cannot close STD IO!\n\0"
|
||||||
|
error_msg_openfd_noexist: .ascii "The file does not exist or can't be opened!\n\0"
|
||||||
|
code_max_size: .quad 65536
|
||||||
|
max_size: .quad 16384
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
# ===================
|
||||||
|
# Memory Allocs
|
||||||
|
# ===================
|
||||||
|
# rdi = address
|
||||||
|
# rsi = size
|
||||||
|
clear_heap_block:
|
||||||
|
xor rcx, rcx
|
||||||
|
clear_heap_block_loop:
|
||||||
|
mov byte ptr [rdi+rcx], 0
|
||||||
|
inc rcx
|
||||||
|
cmp rcx, rsi
|
||||||
|
jl clear_heap_block_loop
|
||||||
|
ret
|
||||||
|
|
||||||
|
# rdi = size in octets
|
||||||
|
brk_alloc:
|
||||||
|
push rbx
|
||||||
|
push r12
|
||||||
|
mov rbx, rdi
|
||||||
|
|
||||||
|
mov rax, 12
|
||||||
|
xor rdi, rdi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
mov rdi, rax # To push brk
|
||||||
|
add rdi, rbx
|
||||||
|
mov r12, rax # To return
|
||||||
|
|
||||||
|
# Pushed
|
||||||
|
mov rax, 12
|
||||||
|
syscall
|
||||||
|
|
||||||
|
mov rax, r12
|
||||||
|
|
||||||
|
# Gotta return
|
||||||
|
pop r12
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
# ===================
|
||||||
|
# File I/O
|
||||||
|
# ===================
|
||||||
|
# rdi = FD
|
||||||
|
# rsi = char*
|
||||||
|
# rdx = size
|
||||||
|
read:
|
||||||
|
push r11 # read uses r11
|
||||||
|
xor rax, rax
|
||||||
|
syscall
|
||||||
|
pop r11
|
||||||
|
ret
|
||||||
|
|
||||||
|
# rdi = FD
|
||||||
|
# rsi = char*
|
||||||
|
write:
|
||||||
|
push r15
|
||||||
|
push r11
|
||||||
|
mov r15, rdi
|
||||||
|
mov rdi, rsi # no need to touch rsi
|
||||||
|
call count
|
||||||
|
|
||||||
|
mov rdx, rax # Lenght
|
||||||
|
mov rax, 1
|
||||||
|
mov rdi, r15
|
||||||
|
|
||||||
|
syscall
|
||||||
|
pop r11
|
||||||
|
pop r15
|
||||||
|
ret
|
||||||
|
|
||||||
|
# rdi = String to count
|
||||||
|
count:
|
||||||
|
mov rax, rdi
|
||||||
|
count_loop:
|
||||||
|
mov r9b, [rax]
|
||||||
|
inc rax
|
||||||
|
cmp r9b, 0
|
||||||
|
jnz count_loop
|
||||||
|
dec rax
|
||||||
|
sub rax, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
# ===================
|
||||||
|
# File Handling
|
||||||
|
# ===================
|
||||||
|
# rdi = Path
|
||||||
|
open_fd:
|
||||||
|
mov rax, 2
|
||||||
|
xor rsi, rsi # RO
|
||||||
|
mov rdx, 644
|
||||||
|
syscall
|
||||||
|
cmp rax, 0
|
||||||
|
jl error_out_open
|
||||||
|
ret
|
||||||
|
|
||||||
|
# rdi = FD
|
||||||
|
close_fd:
|
||||||
|
cmp rdi, 0
|
||||||
|
je error_out_close
|
||||||
|
mov rax, 3
|
||||||
|
syscall
|
||||||
|
ret
|
||||||
|
|
||||||
|
# ===================
|
||||||
|
# Exit & Errors
|
||||||
|
# ===================
|
||||||
|
# rdi = Exit code
|
||||||
|
exit:
|
||||||
|
mov rax, 60
|
||||||
|
syscall
|
||||||
|
|
||||||
|
error_out_close:
|
||||||
|
mov rdi, 1
|
||||||
|
mov rsi, offset error_msg_closefd
|
||||||
|
call write
|
||||||
|
call exit
|
||||||
|
|
||||||
|
error_out_open:
|
||||||
|
mov rdi, 1
|
||||||
|
mov rsi, offset error_msg_openfd_noexist
|
||||||
|
call write
|
||||||
|
call exit
|
212
main.s
Normal file
212
main.s
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
.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
|
||||||
|
|
2
tests/test1.bf
Normal file
2
tests/test1.bf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
|
1
tests/test2.bf
Normal file
1
tests/test2.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
++++++++[>++++++++>++++++++<<-]>+.>++.
|
1
tests/test3.bf
Normal file
1
tests/test3.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
++++[>++++[>++++<-]<-]>>++.[<<+>>-]<<.
|
1
tests/test4.bf
Normal file
1
tests/test4.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
|
1
tests/test5.bf
Normal file
1
tests/test5.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
++++++++[>++++++++<-]>+.,+.,,
|
1
welcome.bf
Normal file
1
welcome.bf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
+++++++++[>++++++++>+++++++++++>++++>++++++++++>+++++++++++>++++>+++++++++++<<<<<<<-]>.>++.+++++++..+++.>---.-.>---.>++.<<<---.>>>--.<<<+++.--.>>>++.<<.<+++++++.-----.>.>>--.--.<<<+++++.>>>>+++.<<<<-.>.>>+.<<<-.>>>-.++++++++.+++++.>>+++.<<<<<+++.>>>>>---.<<---.<<.>>--.+++++.<<<-.>>>>>++.<<++++.--.++.>>.<<++.>>.<<--.>+++++.<<<.<+++.>>>.>>++++.<<++..>>----.<<------.<<.>>-----.+++++.<<.<<-------.>>>----.------.<+.>>>>>++++++++++.
|
Reference in New Issue
Block a user