Funciones 

en MIPS





Ciencias de la Computación III
Diego José Figueroa




¿Cómo llamo a una función?



¿Cómo le envío argumentos?



¿Cómo obtengo su resultado?



¿Cómo administro los registros?




Primero, un recordatorio...

Stack


Stack


  • El stack siempre crece hacia abajo.

  • $sp apunta al tope del stack.
    • Siempre mantengan $sp en el tope del stack.
    • Todo lo que esté arriba (>= $sp) es espacio ocupado.
    • Todo lo que esté abajo (< $sp) es espacio libre.

  • $sp siempre debe estar alineado en múltiplos de 4.

Stack



¿Cómo obtengo espacio libre en el stack?


addi $sp $sp -4   # reservo 1 word

Stack


addi $sp $sp -8  # reservo 2 words

Stack


¿Cómo uso ese espacio?

sw $s0 0($sp)    # *($sp + 0) <- $s0sw $s1 4($sp)    # *($sp + 4) <- $s1

Utilizamos cualquier instrucción para escribir a memoria, según sea apropiado (sb, sw, etc.), y usamos $sp como la base de la dirección.

Stack


¿Cómo libero ese espacio?


addi $sp $sp 8  # sumo 8


Regresamos $sp a su lugar inicial.

Stack


¿Para qué nos puede servir?

  • Valores temporales
  • Variables locales
  • Copias de registros
  • Paso de parámetros

Llamadas a funciones



  1. Cargar los argumentos a $a0 - $a3
  2. Hacer jal a la función (etiqueta)
  3. La función, antes de terminar hace jr $ra.
  4. Al regresar de la función, buscamos el valor de retorno en $v0 (y $v1).

Llamadas a funciones


  • Según el convenio de MIPS, dentro de la función:
    • $s0 - $s7, $sp, $fp, no deben cambiar.
    • $t0 - $t9, $a0 - $a3, pueden cambiar.
    • $ra no debe cambiar.
    • Cualquier valor arriba de $sp no debe cambiar.

Llamadas a funciones


  • El convenio de MIPS no presenta mayor complicación para funciones simples.

  • Pero, ¿qué implica si dentro de una función queremos llamar a otra función?

  • ¿Qué pasa con $ra? 
    • ¿$a0 - $a3? 
    • ¿$t0 - $t9? 
    • ¿$s0 - $s7?

Procedimiento general 

al entrar a una función


  1. Reservar espacio necesario en el stack
    1. 1 word para cada registro que no deba cambiar
    2. $ra
    3. argumentos
  2. Guardar los registros necesarios
  3. Copiar $aX a un lugar seguro ($sX o al stack)
  4. Guardar $ra

Procedimiento general 

al salir de una función


  1. Poner valor de retorno en $v0 (y $v1).
  2. Restaurar registros que no deben cambiar.
  3. Restaurar $ra,
  4. Liberar el stack (regresar $sp a su estado inicial).
  5. jr $ra.

Ejemplo


fibn:
  addi $sp $sp -12 # reservar 
  sw $s0 0($sp)    # guardar $s0
  sw $s1 4($sp)    # guardar $s1
  sw $ra 8($sp)    # guardar $ra
...

Ejemplo

li $v0 0                  # caso base,
beq $a0 $v0 fibn_done     # devolver 0 

li $v0 1 # caso base beq $a0 $v0 fibn_done # devolver 1
move $s0 $a0 # mover $a0 a $s0
addi $a0 $s0 -1 jal fibn # call fibn n-1 mov $s1 $v0 # almacena el result
addi $a0 $s0 -2 jal fibn # call fibn n-2 add $v0 $v0 $s1 # resultado final

Ejemplo


fibn_done:
  lw $s0 0($sp)    # restaurar los
  lw $s1 4($sp)    # registros
  lw $ra 8($sp)
  addi $sp $sp 12  # restaurar $sp
    jr $ra           # regresar

07 - Functions

By Diego Figueroa

07 - Functions

  • 1,098