FRAK

From Esolang
Jump to navigation Jump to search

FRAK is an assembler for the esoteric language brainfuck. It works by simulating an 8-bit conventional computer on the brainfuck machine. The simulated architecture is a RISC whose instruction set is inspired by Processor/1. The word "Frak" is the offensive word used in Battlestar Galactica instead of fuck. It was selected to represent the fact that an assembler 'fracked' the goal of brainfuck by allowing the writing of brainfuck program in an intuitive and not clever way.

Since FRAK's goal is to produce a proof of concept, it has many limitations: programs cannot address more than 256 bytes of memory (8-bit addresses), some operations are slow (those which are unknown to native brainfuck such as bitwise manipulations, if-then-else, etc.) and the instruction set is limited (no floating point support, etc.). FRAK/ASA introduces new macro instructions to overcome some of these limitations (see below).

FRAK could be improved by widening registers (16-bit would be enough to map the standard 30 000 byte memory, but 64 or 128 would taste more esoteric), extending the instruction set (a CISC would allow more efficient instructions on brainfuck 'hardware').

Architecture

FRAK has General Purpose Registers (GPR) accessible by the programmer, a System Register (SR) hidden from the programmer, Control Registers (CR) accessible to the programmer but altered as a side effect of operations, and Scratch Cells that are used by the system.

Instruction Set

  Name Description CR0 change Example
A r0,r1 ADD Adds register r1 to register r0. 1 if carry, 0 otherwise A 3,1 Adds r1 to r3
AND r0,r1 BITWISE AND Performs a bitwise AND between register r0 and register r1 and stores the result into register r0.   AND 3,1 r1 AND r3
BAND r0,r1 BOOLEAN AND Performs a boolean AND between register r0 and register r1 and stores the result into register r0.   BAND 3,1 r1 and r3
BNOT r0 BOOLEAN NOT Applies a boolean NOT to register r0.   BNOT 3 not r3
BOR r0,r1 BOOLEAN OR Performs a boolean OR between register r0 and register r1 and stores the result into register r0.   BAND 3,1 r1 and r3
DEC r0 DECREMENT Subtracts 1 from register r0. 1 if wrap around, 0 otherwise DEC 3 Subtracts 1 from r3
DO r0 LOOP STATEMENT While r0 is not null, execution will continue. Otherwise, execution jumps to after the matching OD. When the matching OD is encountered, execution jumps back to the matching DO and r0 is tested again.  

LI r1,1
DO r3
A r2,r3
S r3,r1
OD r3

Sets r1 to 1
While r3 = 0
Adds r3 to r2
Decrement r3

DIV r0,r1 DIVIDE Divides register r0 by register r1. 1 if the remainder is not 0, 0 otherwise DIV 2,0 Divides r2 by r0
ELSE r0 CONDITIONAL STATEMENT If the value of register r0 is null, execution will continue. Otherwise, execution will jump to after the matching ESLE instruction.  

ELSE r3
A r3,r2
ESLE r3

If r3 = 0
Adds r2 to r3

GET r0 INPUT Inputs the next byte into register r0.   GET 1 Inputs the next byte into r1.
IF r0 CONDITIONAL STATEMENT If the value of register r0 is not zero, execution will continue. Otherwise, execution will jump to after the matching FI instruction.  

IF r3
A r3,r2
FI r3

If r3 is not null
Adds r2 to r3

LI r0,i0 LOAD IMMEDIATE Sets the value of register r0 to the immediate value i0.   LI 3,15 Sets r3 to 15
INC r0 INCREMENT Adds 1 to register r0. 1 if carry, 0 otherwise INC 3 Adds 1 to r3
L r0,r1 LOAD Loads the byte at the address pointed by register r1 into register r0.   L 1,3 Loads the byte at the address pointed to by r3 into r0.
LR r0,r1 LOAD REGISTER Copies register r1 to register r0.   LR 2,0 Copies r0 to r2
MOD r0,r1 MODULO Divides register r0 by register r1 and sets register r0 to the remainder. 1 if the remainder is not 0, 0 otherwise MOD 2,0 Divides r2 by r0 and sets r2 to the remainder
MUL r0,r1 MULTIPLY Multiplies register r0 by register r1. 1 if overflow, 0 otherwise MUL 2,0 Multiplies r2 by r0
NOT r0 BITWISE NOT Applies a bitwise NOT to the value of register r0.   NOT 0 Invert r0
OR r0,r1 BITWISE OR Performs a bitwise OR between register r0 and register r1 and stores the result into register r0.   OR 2,1 r2 OR r1
PUT r0 OUTPUT Outputs the byte in register r0.   PUT 1 Outputs r1.
S r0,r1 SUBTRACT Subtracts register r1 from register r0. 1 if wrap around, 0 otherwise S 3,1 Subtracts r1 to r3
SL r0 SHIFT LEFT Shifts register r0 to the left. 1 if the leftmost bit was on SL 3 Shift left r3
SR r0 SHIFT RIGHT Shifts register r0 to the right. 1 if the rightmost bit was on SR 3 Shift right r3
ST r0,r1 STORE Stores register r0 at the address pointed to by register r1.   ST 1,3 Store r1 at the address pointed to by r3

Code examples

This program adds 100 to 200 and sets register 2 to 255 if the result overflows (which is always the case ...):

LI 0,200   LOADS IMMEDIATE VALUE 200 INTO GPR 0
LI 1,100   LOADS IMMEDIATE VALUE 100 INTO GPR 1
A 0,1      ADDS GPR 1 TO GPR 0
IF c0      IF CR 0 IS NULL JUMP TO THE MATCHING FI
LI 2,X'FF' LOADS IMMEDIATE VALUE 0xFF (255) INTO GPR 2
FI c0

FRAK/ASA

In 2009, FRAK was updated to allow the programmer to access more than 256 bytes of RAM. ASA allow a program to access a larger, but still finite, quantity of memory through distinct 'address spaces' of 256 bytes. The new architecture adds the SPACE macro instruction to the FRAK instruction set to support this feature. ASA maintains upward compatibility and is able to assemble unmodified any FRAK programs.

New features of the FRAK/ASA assembler

SPACE

Tells the assembler to use the specified address space until another SPACE instruction is encountered.

Examples:

LI 0,0      LOADS 0 INTO GPR 0
LI 1,1      LOADS 1 INTO GPR 1
SPACE 1     USE ADDRESS SPACE 1 INSTEAD OF ADDRESS SPACE 0 (DEFAULT ADDRESS SPACE)
ST 1,0      STORES THE CONTENT OF GPR 1 INTO THE BYTE AT ADDRESS 0 (GPR 0 CONTAINS 0) OF ADDRESS SPACE 1
SPACE 0     USE ADDRESS SPACE 0 INSTEAD OF ADDRESS SPACE 1
LI 2,2      LOADS 2 INTO GPR 2
ST 2,0      STORES THE CONTENT OF GPR 2 INTO THE BYTE AT ADDRESS 0 (GPR 0 CONTAINS 0) OF ADDRESS SPACE 0 (DEFAULT ADDRESS SPACE)
SPACE 4095  MOVE TO THE LAST ADDRESS SPACE OF A MEGABYTE
GET 1       READS A BYTE FROM THE INPUT STREAM INTO REGISTER 1
LI 0,255    STORES THE ADDRESS OF THE LAST BYTE IN REGISTER 0
ST 1,0      STORES THE CONTENT OF REGISTER 1 INTO THE BYTE POINTED BY REGISTER 0

ADDRESS

Tells the assembler to move the pointer at the specified displacement from the beginning of the current address space. Used in conjunction with literals.

Example:

ADDRESS 3   MOVE TO THE FOURTH CELL
'+'         INCREMENT THIS CELL

Literals

Literals are strings of brainfuck code to be included as-is in the assembled program or sequences of numerical values to be added to the cells pointed py the pointer. Be careful to move the pointer back to its original position at the end of the execution of the code when coding a code literal because the assembler is dependent of its knowledge of the pointer position. Also, you may have to use the macro instruction ADDRESS to move the pointer to a specific address. By default, the pointer is placed at the beginning of the current address space.

Examples:

'you can include anything including comments'
ADDRESS 3   MOVE TO THE FOURTH CELL
'[->+<]'    MOVE THE CONTENT OF THE CELL (CODE LITERAL)
C'Hello World' WRITE THE STRING TO MEMORY (DATA LITERAL)
ADDRESS 0   MOVE THE POINTER TO THE BEGINNING OF THE STRING
'[.>]'      PRINT THE STRING (CODE LITERAL)
SPACE 4095  MOVE TO THE LAST ADDRESS SPACE OF A MEGABYTE
ADDRESS 255 MOVE TO THE LAST BYTE OF A MEGABYTE
'+'         WRITE A 1 AT THE LAST BYTE OF A MEGABYTE (CODE LITERAL)

SET

Tells the assembler to set the specified number of contiguous cells to the specified value, starting at the current pointer position.

Examples:

C'BRAINFUCK' WRITE THE STRING TO MEMORY
ADDRESS 6    MOVE THE POINTER TO THE CELL THAT HOLDS U
SET 2,C'*'   ERASE 2 CELLS (UC)
ADDRESS 0    MOVE THE POINTER TO THE BEGINNING OF THE STRING
'[.>]'       PRINT THE EXPURGATED STRING
C'BRAINFUCK' WRITE THE STRING TO MEMORY
SET -3,C'*'   ERASE THE 3 PREVIOUS CELLS (UCK)
ADDRESS 0    MOVE THE POINTER TO THE BEGINNING OF THE STRING
'[.>]'       PRINT THE EXPURGATED STRING

External resources