Monday, May 01, 2006

Primeros pasos en la generación de código MIPS...

En esta ocasión presentaremos la resolución del laboratorio #2, en el cual se nos solicito realizar la traducción a código MIPS del calculo de algunas operaciones aritméticas básicas, de las cuales hicimos un laboratorio en la clase de Compiladores I.

La práctica de laboratorio consiste en leer un archivo de texto .txt como el siguiente:


En el cual se encuentran una serie de operaciones aritméticas separadas por el caracter “;”. Al realizar el análisis léxico y sintáctico de este archivo, se generara en un archivo aparte con extensión .s, el código MIPS concerniente al calculo del resultado de cada una de esas expresiones. En este caso particular, el código MIPS generado es el siguiente:


La programación de la generación de las instrucciones MIPS lo hicimos en el archivo minimal.cup. Además quiero comentarles que hicimos una clase llamada cRegisterS, para que nos controlara los registros libres de la CPU. A continuación les colocamos una parte del código que efectúa el trabajo de la traducción a código MIPS:

terminal SEMI, PLUS, TIMES, DIV, MINUS, LPAREN, RPAREN;
terminal Integer NUMBER;

non terminal expr_list, expr_part;
non terminal String expr;

precedence left PLUS;
precedence left TIMES;

expr_list ::= expr_list expr_part expr_part;
expr_part ::= expr:e {:

strMipsCode.append("#Mostrar mensaje personalizado\n");
strMipsCode.append("addi $v0, $zero, 4\n");
strMipsCode.append("la $a0, mensaje0\n");
strMipsCode.append("syscall\n");
strMipsCode.append("#Mostrar el resultado de la operación\n");
strMipsCode.append("li $v0, 1\n");
strMipsCode.append("move $a0, "+e+"\n");
strMipsCode.append("syscall\n");
strMipsCode.append("#Mostrar newline\n");
strMipsCode.append("addi $v0, $zero, 4\n");
strMipsCode.append("la $a0, newline\n");
strMipsCode.append("syscall\n");
cRegistrosS.freeRegisterS(e);
:} SEMI;
expr ::= NUMBER:n
{:
String freeRegister=cRegistrosS.getFreeRegisterS();
if(!freeRegister.equals("0")){
strMipsCode.append("li "+freeRegister+", "+n.intValue()+"\n");
RESULT=freeRegister;
}else{
System.out.println("Error: Insuficientes registros de la CPU");
}
System.out.println("expr ::= NUMBER");
:}
expr:l PLUS expr:r
{:
strMipsCode.append("add "+l+", "+l+", "+r+"\n");
cRegistrosS.freeRegisterS(r);
RESULT=l;
System.out.println("expr ::= expr PLUS expr");
:}
expr:l MINUS expr:r
{:
strMipsCode.append("sub "+l+", "+l+", "+r+"\n");
cRegistrosS.freeRegisterS(r);
RESULT=l;
System.out.println("expr ::= expr MINUS expr");
:}
expr:l TIMES expr:r
{:
strMipsCode.append("mul "+l+", "+l+", "+r+"\n");
cRegistrosS.freeRegisterS(r);
RESULT=l;
System.out.println("expr ::= expr TIMES expr");
:}
expr:l DIV expr:r
{:
strMipsCode.append("div "+l+", "+l+", "+r+"\n");
cRegistrosS.freeRegisterS(r);
RESULT=l;
System.out.println("expr ::= expr DIV expr");
:}
LPAREN expr:e RPAREN
{:
RESULT=e;
System.out.println("expr ::= LPAREN expr RPAREN");
:}
;


La idea principal para poder realizar la generación de las instrucciones MIPS, fue colocar en la producción expr, como atributo sintetizado, el numero de registro en el cual estaba alojado el resultado de expr, de esta manera cuando en el consecuente existía una expr, para poder realizar una operación con ella, lo hacíamos sin ningún problema, porque sabíamos en qué registro estaba el resultado de la misma.

Además, programamos algunas funciones útiles, por ejemplo, para generar tanto el prólogo del archivo .s como su respectivo epílogo. A continuación, citamos dichas funciones:

public String generarPrologo(){
StringBuffer strPrologo=new StringBuffer();
strPrologo.append("\n");
strPrologo.append("#Código MIPS para Laboratorio #2\n");
strPrologo.append("#Programado por: Rafael Alejandro Acosta Sandoval\n");
strPrologo.append(".data\n");
strPrologo.append("mensaje0: .asciiz \"Resultado: \"\n");
strPrologo.append("newline: .asciiz \"\\n\" \n");
strPrologo.append(".text\n");
strPrologo.append(".globl main\n");
strPrologo.append("main:\n");
strPrologo.append("#Establecer Stack Frame\n");
strPrologo.append("sub $sp, $sp, 32\n");
strPrologo.append("sw $ra, 28($sp)\n");
strPrologo.append("sw $fp, 24($sp)\n");
strPrologo.append("add $fp, $sp, 20\n");
strPrologo.append("\n");
return strPrologo.toString();
}

public String generarEpilogo(){
StringBuffer strPrologo=new StringBuffer();
strPrologo.append("\n");
strPrologo.append("#Quitar Stack Frame\n");
strPrologo.append("lw $fp, 24($sp)\n");
strPrologo.append("lw $ra, 28($sp)\n");
strPrologo.append("add $sp, $sp, 32\n");
strPrologo.append("li $v0, 10 #Exit\n");
strPrologo.append("syscall\n");
strPrologo.append("\n");
return strPrologo.toString();
}

Para finalizar, les quiero colocar el resultado de ejecutar el archivo MIPS, que colocamos anteriormente en este blog, en nuestro simulador PCSpim.


Gracias amigos, espero les haya resultado interesante el blog del día de hoy, y espero publicar la próxima semana otro blog en relación al avance del micro-C. Que tengan un buen día!

0 Comments:

Post a Comment

<< Home