Subrutinas

Las subrutinas son una herramienta de programación muy potente. Permiten sacar “factor común” de aquellos trozos de código que se ejecutan muchas veces y reutilizarlo, además de permitir la creación de diferentes niveles de abstracción.

Las instrucciones relacionadas con subrutinas son:

  • “jsr”.
  • “rts”.

La instrucción “jsr” salta a la subrutina, es decir, la ejecuta. La instrucción “rts” termina la ejecución de la subrutina, es decir, devuelve la ejecución a la instrucción siguiente al “jsr”. Esto es posible gracias a que al ejecutar “jsr” se guarda la dirección de retorno en la pila.

Si un programa en código máquina se ejecuta desde BASIC con SYS 49152 (o la dirección que proceda), entonces “rts” también se utiliza para terminar ese programa en código máquina y volver a BASIC.

Una cuestión importante es cómo pasar información o parámetros a las subrutinas. Las dos formas principales son:

  • Mediante los registros del microprocesador.
  • Mediante posiciones de memoria.

Por ejemplo, las rutinas del Kernal utilizan con frecuencia los registros del microprocesador (acumulador, registro X o registro Y) para recibir los parámetros con los que trabajar. Por ejemplo, la rutina “chrout”, que pinta un carácter en pantalla, recibe el código de ese carácter mediante el acumulador.

Otra posibilidad es utilizar posiciones de memoria. El programa principal, que es el que llama a la subrutina, deposita la información en una o varias posiciones de memoria (que pueden ser de memoria general o de la página cero en particular), y la subrutina obtiene la información de esas mismas posiciones.

A mí particularmente me gusta más esta segunda opción (posiciones de memoria), porque los registros del microprocesador me parecen herramientas para trabajar de forma temporal o transitoria, cargando la información de una posición de memoria, procesando esa información, generando otra, devolviéndola a memoria, y así sucesivamente.

Los razonamientos anteriores (cómo pasar información o parámetros) aplican tanto a los parámetros de entrada, es decir, la información que el programa principal pasa a la rutina, como a los parámetros de salida, es decir, la información que la rutina podría devolver al programa principal.

Y por supuesto una subrutina podría llamar a otra, y así sucesivamente, mientras no se agote la pila. Precisamente esta es la forma de crear diferentes niveles de abstracción, desde rutinas más básicas, que hacen funciones sencillas, hasta rutinas que, a base de combinar otras, hacen funciones más complejas.

Y todo lo anterior nos lleva a otro debate importante: una rutina puede modificar los registros del microprocesador y/o posiciones de memoria. Es decir, salvo que el programador tome medidas para evitarlo (por ejemplo, salvaguardar los registros en la pila o en posiciones de memoria y recuperarlos al final de la rutina), lo más probable es que una rutina modifique los registros. Por tanto, con carácter general, el programador no puede confiar en que las rutinas que usa, que pueden ser propias o de terceros, dejen los registros del microprocesador como estaban antes de la llamada.

De hecho, cuando se documentan rutinas es muy habitual documentar el nombre, la función, la dirección de llamada (directa o a través de una “jump table”), cómo se pasan los parámetros de entrada y salida, y qué registros se modifican. Como ejemplo se puede consultar esta página que documenta las rutinas del Kernal: http://sta.c64.org/cbm64krnfunc.html.

“jsr” utiliza el modo de direccionamiento absoluto, porque debe ir acompañada de la dirección de la subrutina (primero el LSB y después en MSB). “rts”, en cambio, utiliza el modo de direccionamiento implícito ya que, al obtenerse la dirección de retorno de la pila, no necesita ningún operando.

Ninguna de estas instrucciones modifica los flags del registro de estado de forma directa. Ahora bien, igual que ocurre con el acumulador, el registro X o el registro Y, la ejecución de una rutina (digamos, el cuerpo de la misma) por supuesto que puede modificar los flags del registro de estado. De hecho, lo más habitual será que lo haga.

Los detalles de estas instrucciones pueden consultarse en http://www.6502.org/tutorials/6502opcodes.html#JSR y http://www.6502.org/tutorials/6502opcodes.html#RTS.


Programa de ejemplo: Prog20

Un comentario en «Subrutinas»

  1. Hola.

    En algún libro he leído que se puede utilizar la pila para pasar parámetros desde un programa / rutina llamante a una rutina llamada.

    Seguramente es cierto, pero no me parece muy cómodo. El programa llamante tendrá que insertar los parámetros en la pila con «pha», y luego hacer «jsr» para saltar a la rutina.

    De este modo, la dirección de retorno de la rutina quedará en la pila por encima de los parámetros. O por debajo, como queramos verlo, puesto que la pila del C64 va desde posiciones más altas hacia posiciones más bajas de la página 1. Lo que está claro es que a la hora de sacar los parámetros de la pila con «pla» la dirección de retorno de la rutina va por delante de los parámetros.

    Total, que ya te metes en fregados de manipular el puntero de la pila con «txs» y similares. No me parece muy práctico. Al contrario, me parece propenso a errores.

    Saludos.

    Me gusta

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s