Teil I.Teil IITeil IIITeil ivTeil vDieser Artikel befasst sich mit der Erstellung eines Interpreters einer bestimmten esoterischen Sprache
LMCode , die auf der Architektur von
Little Man Computer basiert.
Tatsächlich ist dies ein Assembler-Emulator für
LMC , nur hier werden anstelle der Assembler-Befehle INP, STA, ADD, SUB, OUT spezielle verwendet. Zeichen.
Um die Nummer in den Speicher der Befehle
command_mem zu laden, von Befehl zu Befehl zu
wechseln und das Ergebnis auszugeben, werden
Brainfuck- Befehle verwendet.
- Lassen Sie den INP- Befehl übereinstimmen
- Der OUT- Befehl entspricht .
- Der Befehl ADD entspricht +
- Der Unterbefehl entspricht -
- Der STA- Befehl entspricht ~
- Der LDA- Befehl entspricht ^
Wir schreiben ein Programm, das eine Nummer vom Eingabegerät in die Batterie lädt, die Nummer im Speicher speichert, die Nummer aus dem Speicher zur Batterie hinzufügt (die Nummer verdoppelt) und die doppelte Nummer an das Ausgabegerät ausgibt.
In Assembler LMC sieht dieses Programm folgendermaßen aus (die anfängliche Zelle sei 20).
INP STA 20 ADD 20 OUT
In LMCode sieht dieses Programm wie folgt aus
: ~ +.In unserer LMCode-Maschine sind der Codespeicher und der Datenspeicher getrennt (Harvard-Architektur). Wir erstellen die Zeile
command_mem , um den LMCode-Code zu laden. Die Zeichenfolge
command_mem repräsentiert den Speicher der Befehle. Wir erstellen auch ein
data_mem-Datenarray , das den Datenspeicher darstellt.
Wir laden das Programm in
command_mem , ~ +. #include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; // char command_mem[100] = ",~+."; // int data_mem[10]={0}; // while (command_mem[i] != '\0') { if (command_mem[i]==',') // scanf("%d", &acc); if (command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if (command_mem[i]=='~') // data_mem[j]=acc; // if (command_mem[i]=='.') // printf("Output: %d",acc); i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
Beim Laden der Nummer
123 in das Eingabegerät erhalten wir die Nummer
246 .
Sie können in oline ide
ideone.com eincheckenBefehle hinzufügen für
- gehe zur nächsten Zelle >
- gehe zur vorherigen Zelle <
Bei der Verarbeitung des Symbols
> erhöhen wir den Index
j des Datenarrays data_mem if(command_mem[i]=='>') j++;
Bei der Verarbeitung des Symbols
< verringern wir den Index
j des Datenarrays data_mem if(command_mem[i]=='<') j--;
Auf Befehl vorwärts springen
? Wir werden den Übergang zum Label machen
!Dazu überspringen wir alle Zeichen zwischen
? und
! if(command_mem[i]=='?') { while(command_mem[i] != '!' ) { i++; } }
Zum Vergleich schreiben wir ein Programm, in dem der Benutzer eine Zahl, zum Beispiel
5 , mit einem Befehl in fünf Zellen hintereinander mit Befehlen eingibt
~> ~> ~> ~> ~ #include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; // char command_mem[100] = ",~>~>~>~>~"; // int data_mem[10]={0}; // while (command_mem[i] != '\0') { if (command_mem[i]==',') // scanf("%d", &acc); if (command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if (command_mem[i]=='~') // data_mem[j]=acc; // if (command_mem[i]=='.') // printf("Output: %d",acc); if(command_mem[i]=='>') // j++; if(command_mem[i]=='<') // j--; if(command_mem[i]=='?') { // ! while(command_mem[i] != '!') i++; } i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
Als Ergebnis erhalten wir ein Array
5 5 5 5 5 0 0 0 0 0 0ideone.comund dasselbe Programm, in dem mehrere Schritte vorwärts durch den bedingungslosen Sprungbefehl
~> ~?> ~> ~> ~ übersprungen werden
!Wir erhalten ein Array
5 5 0 0 0 0 0 0 0 0 0 0ideone.comFügen Sie das
pzflag- Flag PositiveZero-flag hinzu
Das Flag wird nur gehisst, wenn die Zahl in der Batterie größer oder gleich Null ist.
if(acc>=0){ pzflag=1;} else { pzflag=0;}
Unter der Bedingung
pzflag == 1 werden wir die Befehle
{ und
} ausführen.
if(command_mem[i]=='{') && (pzflag==1){ while(command_mem[i] != '}' ) i++; }
Als nächstes sollen zwei Zahlen in unserem Speicher gespeichert werden
data_mem [0] = 3 und
data_mem [1] = 5Wir werden ein Programm schreiben, das die maximale Anzahl anzeigt.
#include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; int pzflag = 1; // acc>=0 char command_mem[100] = "^>-{^?}<^!."; // int data_mem[10]={0}; data_mem[0]=3; // data_mem[1]=5; while ( command_mem[i] != '\0') { if(command_mem[i]==',') // scanf("%d", &acc); if(command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if(command_mem[i]=='-') // data_mem acc=acc-data_mem[j]; // if(command_mem[i]=='>') // j++; if(command_mem[i]=='<') // j--; if(command_mem[i]=='~') // data_mem[j]=acc; // if(command_mem[i]=='^') // data_mem acc=data_mem[j]; // if(command_mem[i]=='.') { // printf("Output: %d",acc); printf(" "); }; if(command_mem[i]=='?') { // ! while(command_mem[i] != '!') i++; } if (command_mem[i]=='{' && pzflag==1) { // acc>=0 while(command_mem[i] != '}') i++; } if(acc>=0){ // , acc>=0 pzflag=1; } else { pzflag=0; } i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
ideone.comUm zurückzuspringen, fügen Sie die Variable
pz_prev hinzu .
Wenn das aktuelle Zeichen
{ist , dann "
hisse das Flag"
pz_prev if (command_mem[i]=='}') pz_prev=1;
Wenn die Bezeichnung
} vor dem Befehl
{steht , müssen Sie zurückspringen
if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; }
Wir werden ein Programm schreiben, das gerade Zahlen von
10 bis
0 anzeigt.
Wir laden die Zahlen
10 und
2 in das Array
data_mem . Während die Zahl in
acc größer oder gleich Null ist, subtrahieren wir
2 von
10 und zeigen das Ergebnis an
#include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; int pzflag = 1; // acc>=0 int pz_prev=0; // acc>=0 char command_mem[100] = "}^.>-<~{"; // 10 0 int data_mem[10]={0}; data_mem[0]=10; // data_mem[1]=2; while ( command_mem[i] != '\0') { if(command_mem[i]==',') // scanf("%d", &acc); if(command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if(command_mem[i]=='-') // data_mem acc=acc-data_mem[j]; // if(command_mem[i]=='>') // j++; if(command_mem[i]=='<') // j--; if(command_mem[i]=='~') // data_mem[j]=acc; // if(command_mem[i]=='^') // data_mem acc=data_mem[j]; // if(command_mem[i]=='.') { // printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') // ? pz_prev=1; if(command_mem[i]=='?') { // ! while(command_mem[i] != '!') i++; } if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { // while(command_mem[i] != '}') // acc>=0 i++; } if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { // while(command_mem[i] != '}') // acc>=0 i--; } if(acc>=0){ // , acc>=0 pzflag=1;} else { pzflag=0;} //printf("i=%d",i);printf(" "); i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
ideone.comUm zwei Zahlen
A und
B zu multiplizieren, müssen Sie
B mal
A zu
B addieren
.In der Schleife subtrahieren wir bei jeder Iteration eins von
A und addieren
B zu B, während
A nicht Null ist.
LMCode-Programm
} >>> ^ <+> ~ <<< ^> - <~ {>>> ^. multipliziert die Zahlen
A + 1 und
B , d.h. Ein Faktor muss bewusst um eins reduziert werden.
Dies liegt daran, dass die Schleife nur endet, wenn
-1 gem .
Multiplizieren Sie beispielsweise
5 mit
5 .
Platzieren Sie dazu zunächst die erforderlichen Werte in
data_mem data_mem[0]=4; data_mem[1]=1; data_mem[2]=5;
ideone.comFügen Sie bedingungslose Sprünge
zurück .
Fügen Sie dazu die Variable
prev hinzu .
Wir fügen auch
Vorwärts- / Rückwärtsübergänge unter der Bedingung
acc = 0 hinzu . Erstellen
Sie für solche Übergänge das
zflag- Flag (ZeroFlag) und die Variable
z_prev .
Übergänge durch die Bedingung
zflag == 1 werden durch Befehle
( und
) ausgeführt.Wir multiplizieren
5 und
5 mit dem unbedingten Übergang und dem Übergang gemäß der Bedingung
zflag == 1 .
Platzieren Sie zuerst die erforderlichen Werte in
data_arr data_arr[0]=5; data_arr[1]=1; data_arr[2]=5;
LMCode-Programm
! >>> ^ <+> ~ <<< ^> - <~ (?) >>> ^. entspricht dem Assembler-Programm
INP STA 20 INP STA 21 INP STA 22 LDA 23 ADD 22 STA 23 LDA 20 SUB 21 STA 20 BRZ 14 BRA 06 LDA 23 OUT HLT
C-Code
#include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; int pzflag = 1; // acc>=0 int zflag =1; // acc==0 int pz_prev=0; // acc>=0 int z_prev=0; // acc==0 int prev=0; // char command_mem[100] ="!>>>^<+>~<<<^>-<~(?)>>>^."; int data_mem[10]={0}; data_mem[0]=5; // data_mem[1]=1; data_mem[2]=5; while ( command_mem[i] != '\0') { if(command_mem[i]==',') // scanf("%d", &acc); if(command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if(command_mem[i]=='-') // data_mem acc=acc-data_mem[j]; // if(command_mem[i]=='>') // j++; if(command_mem[i]=='<') // j--; if(command_mem[i]=='~') // data_mem[j]=acc; // if(command_mem[i]=='^') // data_mem acc=data_mem[j]; // if(command_mem[i]=='.') { // printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') // ? pz_prev=1; if (command_mem[i]==')') // ? z_prev=1; if (command_mem[i]=='!') // ? prev=1; // if (command_mem[i]=='?' && prev==0) { while(command_mem[i] != '!') i++; } // if (command_mem[i]=='?' && prev==1) { while(command_mem[i] != '!') i--; } // acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==0) { while(command_mem[i] != ')') i++; } // acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==1) { while(command_mem[i] != ')') i--; } // acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { while(command_mem[i] != '}') i++; } // acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } // if(acc>=0){ pzflag=1;} else { pzflag=0;} if(acc==0){ zflag=1;} else { zflag=0;} //printf("i=%d",i);printf(" "); i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
ideone.comIm Allgemeinen konnten keine Flags erstellt werden, sondern überprüfen sofort, wie hoch die Nummer in der Batterie ist.
Lassen Sie uns überprüfen, wie die Fibonacci-Zahlen berechnet werden.
#include <stdio.h> int main(void) { int i=0; // int j=0; // int acc = 0; int pzflag = 1; // acc>=0 int zflag =1; // acc==0 int pz_prev=0; // acc>=0 int z_prev=0; // acc==0 int prev=0; // char command_mem[100] ="}>>^>+.~<+.~<<^>-<~{"; int data_mem[10]={0}; data_mem[0]=5; // data_mem[1]=1; data_mem[2]=1; while ( command_mem[i] != '\0') { if(command_mem[i]==',') // scanf("%d", &acc); if(command_mem[i]=='+') // data_mem acc=acc+data_mem[j]; // if(command_mem[i]=='-') // data_mem acc=acc-data_mem[j]; // if(command_mem[i]=='>') // j++; if(command_mem[i]=='<') // j--; if(command_mem[i]=='~') // data_mem[j]=acc; // if(command_mem[i]=='^') // data_mem acc=data_mem[j]; // if(command_mem[i]=='.') { // printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') // ? pz_prev=1; if (command_mem[i]==')') // ? z_prev=1; if (command_mem[i]=='!') // ? prev=1; // if (command_mem[i]=='?' && prev==0) { while(command_mem[i] != '!') i++; } // if (command_mem[i]=='?' && prev==1) { while(command_mem[i] != '!') i--; } // acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==0) { while(command_mem[i] != ')') i++; } // acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==1) { while(command_mem[i] != ')') i--; } // acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { while(command_mem[i] != '}') i++; } // acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } // if(acc>=0){ pzflag=1;} else { pzflag=0;} if(acc==0){ zflag=1;} else { zflag=0;} //printf("i=%d",i);printf(" "); i++; // } // printf("\n"); // for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; }
ideone.comIch habe
hier auf esolang.org einen Hinweis zur
LMCode- Sprache veröffentlicht
PS Ein Artikel über den Assembler-Emulator für Intel-4004
zur Unterhaltung hier