HiveBrain v1.2.0
Get Started
← Back to all entries
patternMajor

Brainfuck Interpreter written in x86 Assembly

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
interpreterwrittenx86assemblybrainfuck

Problem

Story time: A week ago I found a question about optimizing Assembly code, then I remembered how awesome Brainfuck was, and the match was made very quickly. I decided to write a Brainfuck Interpreter in Assembly!

For this I have used the NASM assembler with x86 Assembly and is intended to run on an Intel CPU and on the Windows OS. I'm sure you can make it run on other combinations if you really want to. I'm also using the Borland 5.5 C Compiler, which is quite old, but the Assembly Book used it and I decided not to deviate from it.

You can compile the code with the following:

  • nasm -f obj bf-interpreter.asm



  • bcc32 bf-interpreter.obj



I wrote the interpreter with performance as main focus, yet I have not read a lot about optimization yet, so I'm not surprised if it turns out to be quite horrible code. As the code is linking with the C stdlib I'm able to call methods from the C stdlib, and essentially only the EBX, EDI and ESI registers are considered "safe", that means they won't be overwritten by calls to the C stdlib, my implementation uses that convention a lot.

This version of the BF Interpreter reads from a file that is passed as argument to the program.

`extern _malloc, _calloc, _printf, _fdopen, _fprintf, _scanf, _getchar, _putchar, _fopen, _fseek, _ftell, _rewind, _fgetc, _fclose

%define STDERR 2
%define SEEK_END 2
%define EOF -1

%define BF_MEMORY_CELL_AMOUNT 30000

%define BF_PROGRAM_END 255

%define JUMP_PAST_CODE 91
%define JUMP_BACK_CODE 93

segment _DATA public align=4 class=DATA use32

format_int db "%d", 0

write_mode db "w", 0
read_mode db "r", 0

bfprogram_jump_table times 43 dd run_program_loop_end,
dd bfprogram_memory_inc,
dd bfprogram_input,
dd bfprogram_memory_dec,
dd bfprogram_output,

Solution

-
The comment ; *argv should be ; argv, since you are not yet dereferencing the pointer.

-
After a cmp instruction, you should prefer je over jz, since it is nicer to the human reader.

Oh, the old times, where you had to tell the assembler to jmp short because it couldn't figure it out on its own. :)

-
In the run the BF program section, I would have changed esi and edi so that the s register points to the source code and the d register points to the data. But that is just for fun.

-
In bfprogram_memory_inc, you can just say inc byte [esi]. The inc instruction has an r/m8 encoding that allows incrementing a value in memory directly, without needing the indirection.

-
The safe to do optimization is nice.

-
Since you rely on the ASCII encoding anyway, you should define JUMP_PAST_CODE as '[' instead of 91, if possible. Not every reader knows the ASCII codes by heart.

-
Does NASM support local labels? That would make the label names in bfprogram_jump_past_loop a little shorter and thereby easier to read.

-
Instead of calling _fdopen, is stderr a linker-visible symbol so that you can access it directly?

-
Since your error messages don't contain percent characters, you should call fputs instead of fprintf.

-
The error messages should include a trailing newline.

(Or are they missing because Windows adds this newline anyway? If so, then it's ok, since it is not necessary to write strictly conforming ANSI C code when you target a specific platform.)

-
The bfprogram_jump_table is very large. You can probably make it smaller by encoding the jump target relative to a known location, which should only take a single byte per entry. times 43 db 0, db bfprogram_memory_inc - run_program_loop_end, ....

-
format_int seems to be unused.

-
STDERR should be called STDERR_FILENO (although that name comes from POSIX, not from Windows, it is still widely known).

-
Since 0xFF is a valid instruction in a Brainfuck program, using it as the EOF marker is not a good idea. When loading the code from the file, you could replace every character above 93 or below 43 with 44. This change would also allow you to make the jump table smaller.

Overall, it's a nice little program and the code does the obvious thing. It's a pleasure to read.

Context

StackExchange Code Review Q#147023, answer score: 45

Revisions (0)

No revisions yet.