low_program | ::= | PROGRAM_START_TO label (ENTER) flags |
flags | ::= | flag (ENTER) flags | units |
flag | ::= | FLAG [n/m] FLAG_name; (ENTER) |
units | ::= | unit (ENTER) units | routines |
unit | ::= | UNIT {(ENTER) low_statements} |
routines | ::= | routine (ENTER) routines | ε |
routine | ::= | ROUTINE label {(ENTER) low_statements} |
low_statements | ::= | low_statement(ENTER) low_statements | ε |
low_statement | ::= | label:num | ROT label | REV ROT | OPR label | REV OPR | SKIP label | JMP label | REV JMP | OUTPUT | REV OUTPUT | INPUT | REV INPUT | DUP | IF FLAG_name (ENTER) BRANCH label | NEXT FLAG_name |
# for comment line, i.e., all characters after # are ignored.
Overview
------------------------------ Declaration of ENTRY Declarations of FLAGs Declarations of UNITs Declarations of ROUTINEs ------------------------------
Specifies the start point by "entry label@routine name".
Example: PROGRAM_START_TO ENTRY@Hello
Specifies a flag by "FLAG [initial state/cycle] label". 2,4,5,6 and 9 are allowed as a cycle. A number between 0 and cycle-1 is allowed as an initial state. Flags in state 0 are active, and Flags in the other states are inactive. The states are incremented by an execution of the flag.
Example: FLAG [1/2] F1ag_H;
Specifies a sequence of data (including Malbolge instructions).
Example of a UNIT
UNIT{ 58:73 # 73 is placed on an address 58 (mod 94)
ROT2: 59:ROT # ROT instruction is placed on the address 59, referable by ROT2. REV_ROT2:60:JMP # JMP instruction is placed on the address 60, referable by REV_ROT2. }
Routines are sequences of (possibly labelled) data or instructions.
ROUTINE name of routine { … Instructions or constants … }
A label is a string consists of alphabet, numeric symbol and underscore that begins from an alphabet. A colon follows from a label. Constants or instructions are placed after that.
Example:
PUT_H: IF FLAG_H BRANCH PUT_e
Constants are decimal numbers from 0 until 59048, ternary numbers from 0000000000t until 2222222222t, or DUP, that represents an unspecified number.
Instructions are defined as follows, where n represents a fixed natural number, [LABEL] is the data labelled by the LABEL. D register acts as a program counter.
Instruction | Semantics | Restriction |
ROT label | A,[label] := rotr( [label] ), D := label+1 | D < label ≤ D+n |
REV ROT | recovers ROT, D := D+1 | |
OPR label | A,[label] := op(A,[label] ), D := label+1 | D < label ≤ D+n |
REV OPR | recovers OPR, D := D+1 | |
SKIP label | D := label | D < label ≤ D+n |
JMP label | D := [label] | |
REV JMP | recovers JMP, D := D+1 | |
OUTPUT | putchr(A); D := D+2 | |
REV OUTPUT | recovers OUTPUT, D := D+1 | |
INPUT | A := getchr(); D := D+2 | |
REV INPUT | recovers INPUT, D := D+1 | |
IF FLAG_name BRANCH label |
If it is active, D := [label] ; otherwise, D := D+2 The state is incremented. |
|
NEXT FLAG_name | The state of the flag is incremented. D := D+1 |
Remark that the recovering instructions must be executed after ROT,OPR,OUTPUT,INPUT,JMP instructions are executed.
Remark that the label specified in an operand of an instruction must be defined below the instruction.
Remark that DUP is typically used as a padding data for INPUT/OUTPUT.
Correct example)ROT X X: 0120120120t REV ROT OUTPUT DUP REV OUTPUTIncorrect example)
X: 0120120120t # The operand X of ROT is placed above ROT ROT X REV ROT OUTPUT REV OUTPUT # this is never executed
Remark that module acts only for collision of names. @routine must follow label in a different routine.
Codes that Low-level assembler always generates (on specific addresses)
Address | Data |
59046 ( 2222222220t ) | 74 ( =SNop ) |
59047 ( 2222222221t ) | 74 ( =SNop ) |
59048 ( 2222222222t ) | 74 ( =SNop ) |
0 | 98 ( =JMP ) |