///
The `ewor_brainfuck` project introduces an extended Brainfuck interpreter mode known as Brainfuck with Syscall Extensions, or **BFA Mode**. This mode significantly enhances the capabilities of standar
57 views
~57 views from guests
Guest views are estimated from total page views. These include anonymous visitors and users who weren't logged in when they viewed the page.
The ewor_brainfuck project introduces an extended Brainfuck interpreter mode known as Brainfuck with Syscall Extensions, or BFA Mode. This mode significantly enhances the capabilities of standard Brainfuck by allowing programs to interact with the underlying operating system through direct system calls (syscalls). This functionality is crucial for developing applications that require interaction with the system, such as networking (e.g., a ping-pong server) or file I/O.
The Mode::BFA enum variant in src/bf.rs is responsible for activating this extended behavior within the BF interpreter. When you instantiate the BF interpreter, you can explicitly set it to Mode::BFA.
The main executable (src/main.rs) automatically switches to Mode::BFA if the input Brainfuck file has a .bfa extension. If no extension is specified or it's .bf, it defaults to Mode::BF. However, it's generally recommended to use .bfa for files containing syscalls to ensure the correct interpreter mode is used.
For more details on how to run programs in BFA mode, refer to the Getting Started: Running Brainfuck and BFL page.
In BFA mode, a specific memory layout is adopted to pass arguments to syscalls and retrieve their return values. This convention uses the initial cells of the Brainfuck memory tape:
Any other memory cells can be used by the Brainfuck program as needed, but cells 0-7 are reserved for this syscall interface.
. Instruction in BFA ModeIn standard Brainfuck, the . (dot) instruction prints the ASCII character value of the current cell. In BFA Mode, the behavior of the . instruction is repurposed. Instead of printing, it triggers the execution of a system call as defined by the values in cells 1-7.
This means that to perform I/O like printing to stdout, you must use the write syscall instead of the traditional . instruction. This allows BFA programs to have fine-grained control over system interactions.
The BFA interpreter supports a subset of common Linux/macOS system calls, allowing for basic file and network operations. These syscall numbers are defined in src/syscall_consts.rs to ensure portability between Linux and macOS. The execute_bfa function in src/bf.rs maps these numbers to the actual syscalls crate functions.
The following syscalls are currently supported:
SYS_WRITE (Syscall number 1 on Linux, 4 on macOS)
arg1 (cell 1): File descriptor (e.g., 1 for stdout).arg2 (cell 2): Memory address (pointer) to the start of the data buffer.arg3 (cell 3): Number of bytes to write.SYS_WRITE in cell 7, 1 in cell 1 (stdout), the address of 'H' in cell 2, and 5 in cell 3, then executing ..SYS_READ (Syscall number 0 on Linux, 3 on macOS)
arg1 (cell 1): File descriptor (e.g., 0 for stdin).arg2 (cell 2): Memory address (pointer) to the start of the buffer to read into.arg3 (cell 3): Maximum number of bytes to read.SYS_CLOSE (Syscall number 3 on Linux, 6 on macOS)
arg1 (cell 1): File descriptor to close.SYS_SOCKET (Syscall number 41 on Linux, 97 on macOS)
arg1 (cell 1): Domain (e.g., AF_INET for IPv4).arg2 (cell 2): Type (e.g., SOCK_STREAM for TCP).arg3 (cell 3): Protocol (usually 0).AF_INET = 2, SOCK_STREAM = 1.SYS_BIND (Syscall number 49 on Linux, 104 on macOS)
arg1 (cell 1): Socket file descriptor.arg2 (cell 2): Memory address (pointer) to the sockaddr structure.arg3 (cell 3): Length of the sockaddr structure.SYS_LISTEN (Syscall number 50 on Linux, 106 on macOS)
arg1 (cell 1): Socket file descriptor.arg2 (cell 2): Backlog (maximum length of pending connections queue).SYS_ACCEPT (Syscall number 43 on Linux, 30 on macOS)
arg1 (cell 1): Listening socket file descriptor.arg2 (cell 2): Memory address (pointer) to a sockaddr structure to fill with client address info (can be 0/NULL).arg3 (cell 3): Memory address (pointer) to a socklen_t to fill with sockaddr length (can be 0/NULL).To illustrate how a syscall works directly in Brainfuck, consider writing a single character (e.g., 'A' which is ASCII 65) to standard output.
Assume the Brainfuck program starts with its pointer at cell 0.
The constants are: SYS_WRITE (Linux) = 1, stdout = 1.
In this snippet:
1 (for SYS_WRITE).SYS_WRITE.1.8, indicating that our character is stored at memory address 8.1 (stdout).65 (ASCII for 'A').., which triggers the write syscall.This direct Brainfuck implementation highlights the complexity of performing even simple operations. This is precisely why the BFL (Brainfuck-like Language) and its compiler architecture were developed: to abstract away these low-level details and make complex programs, especially those involving syscalls and networking, more manageable.
For practical examples showcasing BFA mode in action, refer to the Practical Examples page, particularly examples/hello_bfl.rs, examples/syscall_print.rs, and examples/ping_pong_server.rs.