Parte 1Parte IIParte IIIParte ivParte vEste artículo está dedicado a la creación de un intérprete de cierto lenguaje esotérico 
LMCode , que se basa en la arquitectura de 
Little Man Computer .
De hecho, este es un emulador de ensamblador para 
LMC , solo que aquí en lugar de los comandos de ensamblador INP, STA, ADD, SUB, OUT, se usan los especiales. personajes
Para cargar el número en la memoria de los comandos 
command_mem , las transiciones de comando a comando y también para generar el resultado, se utilizan comandos 
brainfuck .
- Deje que el comando INP coincida
- El comando OUT corresponde .
- El comando AGREGAR corresponde a +
- el subcomando corresponde a -
- El comando STA corresponde a ~
- El comando LDA corresponde a ^
Escribimos un programa que carga un número del dispositivo de entrada en la batería, guarda el número en la memoria, agrega el número de la memoria a la batería (duplica el número) y envía el número duplicado al dispositivo de salida.
En el ensamblador LMC, este programa se verá así (deje que la celda inicial sea 20)
INP STA 20 ADD 20 OUT 
En LMCode, este programa se verá así 
, ~ +.En nuestra máquina LMCode, la memoria de código y la memoria de datos están separadas (arquitectura Harvard), crearemos la línea command_mem para cargar el código LMCode. La cadena 
command_mem representará la memoria de los comandos. También creamos una 
matriz de datos 
data_mem que representará la memoria de datos.
Cargamos el programa en 
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; } 
Al cargar el número 
123 en el dispositivo de entrada, obtenemos el número 
246 .
Puedes consultar en oline ide 
ideone.comAgregar comandos para
- ir a la celda siguiente >
- ir a la celda anterior <
Al procesar el símbolo 
> aumentaremos el índice 
j de la matriz de datos 
data_mem if(command_mem[i]=='>') j++; 
Al procesar el símbolo 
<, disminuiremos el índice 
j de la matriz de datos 
data_mem if(command_mem[i]=='<') j--; 
¿Saltar adelante al mando 
? ¡Haremos la transición a la etiqueta 
!Para hacer esto, saltaremos todos los caracteres entre 
? y 
! if(command_mem[i]=='?') { while(command_mem[i] != '!' ) { i++; } } 
A modo de comparación, escribimos un programa en el que el usuario ingresa un número, por ejemplo 
5 , con un comando 
, en cinco celdas seguidas con comandos
~> ~> ~> ~> ~ #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; } 
Como resultado, obtenemos una matriz 
5 5 5 5 5 0 0 0 0 0 0ideone.comy el mismo programa en el que el comando de salto incondicional salta varios pasos hacia adelante 
, ~> ~?> ~> ~> ~!Obtenemos una matriz 
5 5 0 0 0 0 0 0 0 0 0ideone.comAgregue la bandera 
pzflag Positiva- 
cero -bandera
La bandera se elevará solo si el número en la batería es mayor o igual a cero.
  if(acc>=0){ pzflag=1;} else { pzflag=0;} 
Avanzando por la condición 
pzflag == 1 ejecutaremos los comandos 
{ y 
} if(command_mem[i]=='{') && (pzflag==1){ while(command_mem[i] != '}' ) i++; } 
Luego, dejemos dos números almacenados en nuestra memoria
data_mem [0] = 3 y 
data_mem [1] = 5Escribiremos un programa que muestre el número máximo.
 #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.comPara retroceder, agregue la variable 
pz_prev .
Si el carácter actual es 
{ , entonces "levanta la bandera" 
pz_prev if (command_mem[i]=='}') pz_prev=1; 
Si la etiqueta 
} precede al comando 
{ , entonces necesita retroceder
 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } 
Escribiremos un programa que muestre números pares del 
10 al 
0 .
Cargamos los números 
10 y 
2 en la matriz 
data_mem , luego, mientras que el número en 
acc es mayor o igual a cero, restaremos 
2 de 
10 y mostraremos el resultado
 #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.comPara multiplicar dos números 
A y 
B , debes sumar 
B por A a 
B.En el bucle, en cada iteración, restaremos uno de 
A y, mientras 
A no 
es cero, sumaremos 
B a B.
Programa LMCode 
} >>> ^ <+> ~ <<< ^> - <~ {>>> ^. multiplica los números 
A + 1 y 
B , es decir un factor debe reducirse deliberadamente en uno.
Esto se debe a que el ciclo solo terminará cuando 
-1 esté en 
acc .
Por ejemplo, multiplique 
5 por 
5 .
Para hacer esto, primero coloque los valores necesarios en 
data_mem  data_mem[0]=4; data_mem[1]=1; data_mem[2]=5; 
ideone.comAgregue saltos incondicionales 
hacia atrás .
Para hacer esto, agregue la variable 
anterior .
También agregamos transiciones 
hacia adelante / hacia atrás bajo la condición 
acc = 0 . Para tales transiciones, cree la bandera zflag (ZeroFlag) y la variable 
z_prev .
Las transiciones por la condición 
zflag == 1 se llevarán a cabo mediante comandos 
( y 
)Multiplicamos 
5 y 
5 usando la transición incondicional y la transición de acuerdo con la condición 
zflag == 1 .
Primero coloque los valores necesarios en 
data_arr  data_arr[0]=5; data_arr[1]=1; data_arr[2]=5; 
¡Programa LMCode 
! >>> ^ <+> ~ <<< ^> - <~ (?) >>> ^. corresponde al programa ensamblador
  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ódigo C
 #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.comEn general, no se pudieron crear indicadores, pero en lugar de ellos, verifique inmediatamente a qué equivale el número de la batería.
Veamos cómo se calculan los números de Fibonacci.
 #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.comPubliqué una nota sobre el lenguaje LMCode en esolang.org 
aquíPD: un artículo sobre el emulador de ensamblador para Intel-4004 
para entretenimiento aquí