Llamado a subrutinas anidadas
Las subrutinas o subprogramas son fragmentos de código diseñados para realizar determinadas tareas, que pueden ser invocados desde diferentes puntos del programa principal o desde otras subrutinas. Es una herramientas que los programadores usan para estructurar programas, haciéndolos más sencillos de entender y permitiendo codificarlos para ser reutilizados.
Las subrutinas normalmente reciben un conjunto de parámetros que son las variables con cuyos valores realizan los cálculos u operaciones adecuadas.
Se tienen dos tipos de subrutinas:
- Aquellas donde el resultado de las operaciones es un valor, son conocidas como "funciones" y debe devolver este valor al finalizar la subrutina.
- Si solamente se ejecuta una secuencia de instrucciones sin devolver ningún valor, se le llama "procedimiento".
En todo momento, las subrutinas tienen un punto de entrada y un punto de retorno a la función que hizo la llamada y se ejecutan de manera independiente al programa principal.
En la ejecución de un procedimiento o función, el programa debe seguir los siguientes seis pasos:
- 1. Situar los parámetros de la subrutina en los registros $a0, $a1, $a2, $a3 o en la pila.
- 3. Reservar espacio para variables locales (registros $t) y/o en pila.
- 5. Si es una función, colocar el resultado en los registros $v0, $v1 y/o en pila.
- 6. Devolver el control a la función que realiza la llamada con la instrucción "jr $ra", una subrutina puede ser llamada desde varios puntos en un mismo programa.
La subrutina tiene la obligación de devolver intactos al programador los siguientes registros (salvaguardándolos en pila si es preciso):
- Los registros $s0-$s7, ya que contienen variables de larga duración.
- $sp: puntero de pila.
- $fp: puntero a bloque de activación.
- $ra: dirección de retorno.
- $gp: puntero a zona de datos globales (la subrutina no debería modificarlo).
La función o subrutina no tiene la obligación de devolver intactos al programador los siguientes registros (si el programador quiere confiar en sus contenidos, debe salvaguardarlos en pila él mismo):
- Los registros $t0 ... $t9, ya que contienen datos de vida corta.
- Los registros $a0 ... $a3, que contienen los argumentos de entrada.
El programa modifica los registros $v0 y $v1 poniendo su valor de retorno, por lo que evidentemente el programador no los salvaguarda en pila.
En la idea del almacenamiento del programa está implícita la necesidad de tener un registro que mantenga la dirección de la instrucción actual que está siendo ejecutada. Por razones históricas, este registro es casi siempre llamado el "Program Counter", abreviado "PC" en la arquitectura MIPS, aunque un nombre más sensible podría ser registro de instrucción de la dirección. La instrucción "jal" guarda PC+4 en un registro $ra para enlazar la siguiente instrucción estableciendo el retorno del procedimiento.