Skip to content

Instantly share code, notes, and snippets.

@cbpudding
Last active October 20, 2020 22:50
Show Gist options
  • Save cbpudding/91e0da9ea7cd0c69123328e6671d1089 to your computer and use it in GitHub Desktop.
Save cbpudding/91e0da9ea7cd0c69123328e6671d1089 to your computer and use it in GitHub Desktop.
A small brainf*** interpreter written in MIPS Assembly
.data
buffer: .space 65536
memory: .space 256
.text
main:
la $a0, buffer # Get the source code to execute
li $a1, 65536
li $v0, 8
syscall
la $a0, memory # Initialize memory
la $a1, memory
addi $a1, $a1, 256
memset.loop:
sb $zero, ($a0)
addi $a0, $a0, 1
bne $a0, $a1, memset.loop
memset.end:
la $a0, buffer # Start executing the string as BF code
li $s0, 0
li $s3, 0
loop:
lb $s1, ($a0) # Read a byte from the code
addi $a0, $a0, 1
addi $s0, $s0, 1
li $s2, '+' # Is it an increment?
beq $s1, $s2, increment
li $s2, '-' # Is it a decrement?
beq $s1, $s2, decrement
li $s2, '>' # Is it a right?
beq $s1, $s2, right
li $s2, '<' # Is it a left?
beq $s1, $s2, left
li $s2, '.' # Is it a out?
beq $s1, $s2, out
li $s2, ',' # Is it a in?
beq $s1, $s2, in
li $s2, '[' # Is it a jump if zero?
beq $s1, $s2, jz
li $s2, ']' # Is if a jump is not zero?
beq $s1, $s2, jnz
beq $s1, $zero, done # Are we done?
ble $s0, $zero, done
b loop # If it's nothing we know, skip over it.
increment:
la $a1, memory # Pull that byte from memory
add $a1, $a1, $s3
lb $s1, ($a1)
addi $s1, $s1, 1 # Increment the byte
sb $s1, ($a1) # Put it back
b loop # Back to the loop
decrement:
la $a1, memory # Pull that byte from memory
add $a1, $a1, $s3
lb $s1, ($a1)
subiu $s1, $s1, 1 # Decrement the byte
sb $s1, ($a1) # Put it back
b loop # Back to the loop
right:
addi $s3, $s3, 1 # Increment the memory index
andi $s3, $s3, 255 # Keep the index within the bounds
b loop # Back to the loop
left:
subiu $s3, $s3, 1 # Decrement the memory index
andi $s3, $s3, 255 # Keep the index within the bounds
b loop # Back to the loop
out:
la $a1, memory # Pull that byte from memory
add $a1, $a1, $s3
lb $s1, ($a1)
move $a0, $s1 # Print the character
li $v0, 11
syscall
la $a0, buffer # Fix $a0
add $a0, $a0, $s0
b loop # Back to the loop
in:
la $a1, memory # Get the memory location
add $a1, $a1, $s3
li $v0, 12 # Get a character from the console
syscall
sb $v0, ($a1) # Store the byte
b loop # Back to the loop
jz:
la $a1, memory # Pull the byte from memory
add $a1, $a1, $s3
lb $s1, ($a1)
bne $s1, $zero, loop # Skip if the cell isn't zero
li $s1, 1
jz.loop:
lb $s4, ($a0) # Read the next instruction
addi $a0, $a0, 1
addi $s0, $s0, 1
li $s2, '[' # Is this a [?
beq $s4, $s2, jz.jz
li $s2, ']' # Is this a ]?
beq $s4, $s2, jz.jnz
beq $s4, $zero, done # Are we done?
b jz.loop
jz.jz:
addi $s1, $s1, 1 # Increment the depth variable
b jz.loop
jz.jnz:
subi $s1, $s1, 1 # Decrement the depth variable
beq $s1, $zero, loop # Is this the matching bracket?
b jz.loop
jnz:
la $a1, memory # Pull the byte from memory
add $a1, $a1, $s3
lb $s1, ($a1)
beq $s1, $zero, loop # Skip if the cell is zero
li $s1, 1
subi $a0, $a0, 1
subi $s0, $s0, 1
jnz.loop:
subi $a0, $a0, 1 # Seek to the previous instruction
subi $s0, $s0, 1
blt $s0, $zero, done # Are we done?
lb $s4, ($a0) # Read the previous instruction
li $s2, '[' # Is this a [?
beq $s4, $s2, jnz.jz
li $s2, ']' # Is this a ]?
beq $s4, $s2, jnz.jnz
b jnz.loop
jnz.jz:
subi $s1, $s1, 1 # Decrement the depth variable
beq $s1, $zero, jnz.done# Is this the matching bracket?
b jnz.loop
jnz.jnz:
addi $s1, $s1, 1 # Increment the depth variable
b jnz.loop
jnz.done:
addi $a0, $a0, 1 # Fix a0 and s0
addi $s0, $s0, 1
b loop
done:
li $v0, 10 # Exit gracefully
syscall
@Monadic-Cat
Copy link

Wow, I can almost read this.

@cbpudding
Copy link
Author

Wow, I can almost read this.

Almost eh? How would I make it more readable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment