Skip to content

Instantly share code, notes, and snippets.

@JustAPerson

JustAPerson/brain86.rs

Last active Aug 29, 2015
Embed
What would you like to do?
Brainfuck compiler
// Brain86
// This program compiles well-formed brainfuck code to x86 assembler.
// Requires rust nightly, nasm, and ld
//
// An interesting sample program:
// https://raw.githubusercontent.com/JustAPerson/brainrust/master/tests/mandelbrot.bf
//
// $ rustc brain86.rs
// $ cat mandelbrot.bf | ./brain86 > mandelbrot.s
// $ nasm -f elf64 mandelbrot.s
// $ ld mandelbrot.o -o mandelbrot
// $ ./mandelbrot
#![feature(io)]
use std::io::Read;
fn main() {
let mut labels = Vec::new();
let mut label_counter = 0;
println!("section .bss");
println!(" stack: resb 30000");
println!("section .text");
println!(" global _start");
println!("_start:");
println!(" xor esi, esi"); // esi will be the stack pointer
for char in std::io::stdin().chars() {
match char.unwrap() {
'+' => {
println!(" add byte [stack+esi], 1");
},
'-' => {
println!(" sub byte [stack+esi], 1");
},
'>' => { println!(" add esi, 1"); },
'<' => { println!(" sub esi, 1"); },
'[' => {
let label = format!("loop{}", label_counter);
label_counter += 1;
labels.push(label.clone());
println!(".{}_start:", &label);
println!(" cmp byte [stack+esi], 0");
println!(" jz .{}_end", &label);
},
']' => {
let label = labels.pop().unwrap();
println!(" jmp .{}_start", &label);
println!(".{}_end:", &label);
},
'.' => {
println!(" mov edx, 1");
println!(" lea ecx, [stack+esi]");
println!(" mov ebx, 1"); // stdout
println!(" mov eax, 4"); // sys_write
println!(" int 0x80");
},
',' => {
println!(" mov edx, 1");
println!(" lea ecx, [stack+esi]");
println!(" mov ebx, 0"); // stdin
println!(" mov eax, 3"); // sys_read
println!(" int 0x80");
},
_ => { },
}
}
println!(" mov ebx, 0"); // exit code = 0
println!(" mov eax, 1"); // sys_exit
println!(" int 0x80");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.