Compare commits

..

6 Commits

Author SHA1 Message Date
cat
1ba6765c85 Cleaning residue plus minor jmp advantage 2025-06-23 13:20:38 +03:00
cat
ceb84c9e3d Fixed read loop glitch 2025-06-23 13:12:31 +03:00
cat
15311ca7d1 fixed my dumbassary 2025-06-21 20:45:30 +03:00
cat
d59a5c8b39 Further tiding up 2025-06-21 16:39:18 +03:00
cat
d3cb608a55 Tiding up 2025-06-21 16:34:17 +03:00
cat
ea84361ca8 Adding everything 2025-06-21 16:29:23 +03:00
12 changed files with 369 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bf-cat
bf-cat.o

View File

@@ -1,3 +1,9 @@
# 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,2 @@
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.

1
tests/test2.bf Normal file
View File

@@ -0,0 +1 @@
++++++++[>++++++++>++++++++<<-]>+.>++.

1
tests/test3.bf Normal file
View File

@@ -0,0 +1 @@
++++[>++++[>++++<-]<-]>>++.[<<+>>-]<<.

1
tests/test4.bf Normal file
View File

@@ -0,0 +1 @@
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

1
tests/test5.bf Normal file
View File

@@ -0,0 +1 @@
++++++++[>++++++++<-]>+.,+.,,

1
welcome.bf Normal file
View File

@@ -0,0 +1 @@
+++++++++[>++++++++>+++++++++++>++++>++++++++++>+++++++++++>++++>+++++++++++<<<<<<<-]>.>++.+++++++..+++.>---.-.>---.>++.<<<---.>>>--.<<<+++.--.>>>++.<<.<+++++++.-----.>.>>--.--.<<<+++++.>>>>+++.<<<<-.>.>>+.<<<-.>>>-.++++++++.+++++.>>+++.<<<<<+++.>>>>>---.<<---.<<.>>--.+++++.<<<-.>>>>>++.<<++++.--.++.>>.<<++.>>.<<--.>+++++.<<<.<+++.>>>.>>++++.<<++..>>----.<<------.<<.>>-----.+++++.<<.<<-------.>>>----.------.<+.>>>>>++++++++++.