Post on 30-Sep-2018
Sesión 8Subrutinas
Computadores IIRodrigo Santamaría
Índice
● Subrutinas● Documentación● Llamada (JSR, BSR, LBSR)● Retorno (RTS, PUL)
– Uso de registros en subrutinas● Interferencias de memoria● Anidamiento
Subrutinas
● No es recomendable repetir trozos de código cada vez que se utilizan● El código ocupa mucho más● El código es difícilmente mantenible● No se fomenta la modularidad:
– “Un programa complejo debe dividirse en subtareas simples, autocontenidas y con interfaces bien definidas”
Subrutinas
● Subrutina: fragmento de código donde se realiza una tarea y después ejecuta la siguiente instrucción a la que la llamó
● Es fundamental que las subrutinas tenga objetivos bien definidos y nombres explicativos
nombreSubrutina: instruccionS1 ... instruccionSN
rts
...bsr nombreSubrutina...
Documentación de subrutinas
● Una subrutina no se distingue de una etiqueta● Usar indicativos para nombres de subrutinas
– Por ejemplo, saltos de línes● Añadir cabeceras de subrutina que indiquen
– Nombre– Función– Registros o variables de entrada– Registros o variables de salida– Registros modificados por la subrutina
Documentación de subrutinas
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; imprime_cadena ;; saca por la pantalla la cadena acabada en '\0 apuntada por X ;; ;; Entrada: X-direcciOn de comienzo de la cadena ;; Salida: ninguna ;; Registros afectados: X, CC. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; imprime_cadena:
pshs asgte: lda ,x+ beq return sta pantalla bra sgtereturn: puls a rts
Llamada a subrutinas
● Similar a los saltos● JMP → JSR● BRA → BSR● LBRA → LBSR
● El 6809 cambia el PC a la dirección de la subrutina● Pero justo antes, guarda en S el PC actual● Cuando termina la ejecución de la subrutina (rts),
carga S en el PC
Retorno de subrutinas
● Una subrutina retorna con el nemónico RTS (ReTurn Subroutine)● Transfiere S al PC● Equivalente a PULS PC, pero ocupa sólo 1 byte
● Si queremos retornar un valor, es mejor con PULS:● Por ejemplo, si queremos retornar A: PULS A,PC
● Si hay registros que no queremos alterar:● PSHS registros al comienzo de la subrutina● PULS registros para terminar
Interferencia de direcciones
● Debemos controlar en todo momento nuestros punteros a direcciones, teniendo en cuenta:● Las direcciones de la máquina simple: 0xFF00,
0xFF01, 0xFF02● El contador de programa (generalmente en 0x0100
y siguientes)– Modificable al comienzo con .org 0xHHHH
● La pila S (si no la iniciamos, en 0x0000)– Modificable con lds #0xHHHH
Ejecución y retorno: ejemplo
.org 0x0100 ...0x010B lbsr imprime_cadena0x010E ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0100
PC
0000
S
Ejecución y retorno: ejemplo
.org 0x0100 ...0x010B lbsr imprime_cadena0x010E ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
010B
PC
0000
S
Ejecución y retorno: ejemplo
.org 0x0100 ...0x010B lbsr imprime_cadena0x010E ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
010E
PC
0002
S
Ejecución y retorno: ejemplo
.org 0x0100 ...0x010B lbsr imprime_cadena0x010E ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S0000...
...
010x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
0E
subrutina
0000
PC
0002
S
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0100
PC
0000
S
...
...
... pila
0xF000
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0110
PC
F000
S
...
...
... pila
0xF000
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0113
PC
F002
S
01
13
... pila
0xF000
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0000
PC
F002
S
01
13
... pila
0xF000
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts 0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina000E
PC
F002
S
01
13
... pila
0xF000
Ejecución y retorno: ejemplo 2
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts 0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina0113
PC
F000
S
01
13
... pila
0xF000
Registros y subrutinas
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
0002
PC
F003
S
01
13
XX pila
0xF000
XX
A
...
Registros y subrutinas
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 bucle: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra bucle0x000B return: puls a0x000D rts
0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina
000D
PC
F003
S
01
13
XX pila
0xF000
YY
A
...
Registros y subrutinas
.org 0x0100 ...0x010B lds #0xF0000x0110 lbsr imprime_cadena0x0113 ldb #'\n ...0x0121 sta 0xFF01
0x0000 imprime_cadena: pshs a0x0002 sgte: lda ,x+0x0004 beq return0x0006 sta pantalla0x0009 bra sgte0x000B return: puls a0x000D rts 0100
PC
0000
S
0000...
...
340x0000
0x0100
...
B70x0121
programa
FF
01
...
390x000D
04
subrutina000E
PC
F002
S
01
13
XX pila
0xF000
XX
A
...
Equivale a puls a,pc
Anidamiento
● Recurso por el que una estructura se repite dentro de sí misma● Bucle anidado: bucle cuyo cuerpo se encuentra
dentro de otro bucle● Subrutina anidada: subrutina que se invoca dentro
de otra subrutina
● El anidamiento es la razón para usar una pila para almacenar la dirección a la que volver tras una llamada a subrutina● Si hay varias, se vuelve a la siguiente instrucción
de la última que llamó.
Anidamiento: ejemplo
Ejercicio 2 (obligatorio)
● Codificad y documentad con su cabecera las siguientes subrutinas basándoos en el código que ya habéis realizado:
1. imprime_cadena: saca por la pantalla la cadena apuntada por X, que ha de acabar en \0. Registros afectados: X y CC
2. imprime_decimal: saca por la pantalla, en decimal, el número contenido en D, interpretado como sin signo. Registros afectados: D y CC
Ejercicio 2 (obligatorio)
● Utilizadlas en un programa que imprima una cadena y un decimal almacenados en variables● Para la cadena:
– cadena: .ascii “Hola mundo\0”
– ldx #cadena
● Para el número– numero: .word #27
– ldd numero
Ejercicio 4 (opcional)● Haced lo mismo que en el ejercicio anterior con
estas funciones:● lee_cadena: lee del teclado y escribe, a partir de la
posición marcada por X, caracteres hasta que el usuario pulse intro (\n). El carácter \n no se almacena en la memoria y la cadena acaba en \0 en la memoria. A la salida X apunta a la posición donde se almacenó el carácter \0. Registros afectados: X y CC
● lee_cadena_n: igual que el caso anterior, pero admite una entrada más en el registro A que será el número máximo de caracteres que se almacenarán en la memoria contando el \0 del final, que siempre se escribe. En A devuelve el número de caracteres leídos. Registros afectados: X y CC
Ejercicio 4 (continúa)
● lee_decimal: igual que el segundo caso, pero lo que se lee se interpreta como un número decimal. El número se devuelve en D. En caso de error, por haber caracteres que no sean números ni espacios o por pasarse de la capacidad del registro D, se devuelve en D cero y se activa el bit de acarreo. Si hay espacios al principio, se ignoran. Si aparece un espacio después de haber leído varias cifras, se acaba la lectura, pero no es un error. Si no hay error, el bit de acarreo vuelve desactivado. Registros afectados: CC
● CUIDADO con las direcciones de memoria