VEC EQU $0040
ORG 0000
MENOR RMB 1 Aqui quedara el menor
DIRINI FDB VEC Direccion inicial del vector
CANT FCB 07 Cantidad de elementos del vector
* El vector lo estoy ubicando en otro lugar de memoria R/W
ORG VEC
VECTOR FCB $14,$33,$FF,$E0,$09,$11,$10
* Notar que la dir inicial del programa es la que cargo en el vector de reset al final, para que inicialice el PC.
ORG $C000
main LDX DIRINI * Cargo IX con la direccion inicial
LDAA 0,X * Cargo el primer elemento del vector en A
DEC CANT * Decremento la cant directamente en memoria
SIGO INX
LDAB 0,X * Cargo el segundo elemento del vector
CBA * y los comparo
BLS Amenor * Si el primero ya era menor, no lo cambio
TBA * Copio B en A
Amenor DEC CANT * Decremento la cant directamente en memoria
BNE SIGO * Si aun quedan elementos, sigue
STAA MENOR * Sino guarda el menor en donde se pidió
FIN BRA FIN
ORG $FFFE
RESET FDB main
Esta es la tabla de símbolos como la dejamos:
identificador valor (hexadecimal)
VEC 0040
MENOR 0000
DIRINI 0001
CANT 0003
VECTOR 0040
main C000
Amenor
SIGO
FIN
RESET FFFE
y hasta aquí habíamos llegado ensamblando:
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 DEC CANT
Para continuar tenemos que ensamblar la instrucción DEC. Observemos los modos de direccionamiento que soporta:
En este caso DEC no admite modo directo, sino solo indexado y extendido. No estamos usando indexado porque la referencia CANT es una dirección de memoria, así que el código de operación es 7A. Observe que el operando se debe expresar en 16 bits, por eso en el set de instrucciones aparece como "hh ll", o sea parte alta (High) y parte baja (Low) de la dirección. En la tabla de símbolos vemos que CANT es 0003, por tanto al ensamblarlo queda así:
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 SIGO INX
Dado que la instrucción DEC CANT ensamblada ocupa tres bytes, la dirección de la siguiente instrucción es $C007 ($C0004 + 3). Seguramente ya habrá comprendido la dinámica del cálculo de la dirección de la siguiente instrucción. También habrá concluido que no es posible "predecir" la dirección de una instrucción cualquiera sin antes ensamblar todas las anteriores. Hay que tener especial cuidado de no asumir que podemos usar modo directo con todas las instrucciones, ya que existen algunas que no lo admiten (DEC, INC, CLR por ejemplo).
La siguiente instrucción tiene una etiqueta (SIGO) por tanto podemos completar esa entrada de la tabla de símbolos: SIGO equivale a $C007. El código de operación de INX es fácil de determinar porque opera solo en modo inherente. Las dos instrucciones que siguen (LDAB en modo indexado y CBA, que solo admite inherente) no representan mayor dificultad, así que también las ensamblamos sin mayor inconveniente. Llegamos a este punto, donde BLS también admite un solo modo de direccionamiento: relativo.
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 ?? BLS Amenor
TBA
Amenor DEC CANT
BNE SIGO
STAA MENOR
FIN BRA FIN
La cuestión es: ¿cómo completamos lo marcado con signos de interrogación? El modo relativo de BLS (o de cualquier branch) utiliza un operando de 8 bits, por eso en el set de instrucciones vemos que dice rr:
Por tanto aunque aun no calculamos el operando, sabemos que es de 8 bits. En un post anterior sobre Direccionamiento relativo hemos visto cómo operan las instrucciones de salto (tal vez merezca un repaso). Como tenemos que calcular el salto a la etiqueta Amenor pero aun no la completamos en la tabla de símbolos, continuemos el ensamblado dejando el lugar para el operando que nos falta. Luego volveremos a ella. Dejaremos también pendientes los otros saltos relativos.
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 08 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 ?? BLS Amenor
$C00D 17 TBA
$C00E 7A 00 03 Amenor DEC CANT
$C011 26 ?? BNE SIGO
$C013 97 00 STAA MENOR
$C015 20 ?? FIN BRA FIN
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 SIGO INX
Dado que la instrucción DEC CANT ensamblada ocupa tres bytes, la dirección de la siguiente instrucción es $C007 ($C0004 + 3). Seguramente ya habrá comprendido la dinámica del cálculo de la dirección de la siguiente instrucción. También habrá concluido que no es posible "predecir" la dirección de una instrucción cualquiera sin antes ensamblar todas las anteriores. Hay que tener especial cuidado de no asumir que podemos usar modo directo con todas las instrucciones, ya que existen algunas que no lo admiten (DEC, INC, CLR por ejemplo).
La siguiente instrucción tiene una etiqueta (SIGO) por tanto podemos completar esa entrada de la tabla de símbolos: SIGO equivale a $C007. El código de operación de INX es fácil de determinar porque opera solo en modo inherente. Las dos instrucciones que siguen (LDAB en modo indexado y CBA, que solo admite inherente) no representan mayor dificultad, así que también las ensamblamos sin mayor inconveniente. Llegamos a este punto, donde BLS también admite un solo modo de direccionamiento: relativo.
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 ?? BLS Amenor
TBA
Amenor DEC CANT
BNE SIGO
STAA MENOR
FIN BRA FIN
La cuestión es: ¿cómo completamos lo marcado con signos de interrogación? El modo relativo de BLS (o de cualquier branch) utiliza un operando de 8 bits, por eso en el set de instrucciones vemos que dice rr:
Por tanto aunque aun no calculamos el operando, sabemos que es de 8 bits. En un post anterior sobre Direccionamiento relativo hemos visto cómo operan las instrucciones de salto (tal vez merezca un repaso). Como tenemos que calcular el salto a la etiqueta Amenor pero aun no la completamos en la tabla de símbolos, continuemos el ensamblado dejando el lugar para el operando que nos falta. Luego volveremos a ella. Dejaremos también pendientes los otros saltos relativos.
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 08 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 ?? BLS Amenor
$C00D 17 TBA
$C00E 7A 00 03 Amenor DEC CANT
$C011 26 ?? BNE SIGO
$C013 97 00 STAA MENOR
$C015 20 ?? FIN BRA FIN
$C017
Aunque todavía nos faltan determinar tres operandos de los branch del ejercicio, ya podemos completar la tabla de símbolos:
identificador valor (hexadecimal)
VEC 0040
MENOR 0000
DIRINI 0001
CANT 0003
VECTOR 0040
main C000
Amenor C00E
SIGO C007
FIN C015
RESET FFFE
¿Cómo calculamos el direccionamiento relativo de los saltos? Tal como vimos en el post sobre ese tema, lo que acompaña la instrucción de salto es el offset que se aplica al PC (claro está, cuando se cumple la condición del branch). Este offset puede ser positivo, lo que provocaría un salto hacia adelante, o negativo, que se traduce en un salto hacia atrás.
En el ejemplo tenemos los dos tipos de saltos. La línea BLS Amenor es un salto hacia adelante. Cuando CPU haya leído la instrucción completa (pero aun antes de ejecutarla) el PC tendrá el valor de la siguiente instruccion $C00D. La etiqueta Amenor corresponde a la dirección C00E -tal como apuntamos en la tabla de símbolos-. Haciendo la resta, C00E - C00D (donde queremos estar menos donde estamos) obtenemos el offset, en este caso 01.
Consideremos otro de los saltos: BNE SIGO. Este salto -de ejecutarse- es hacia atrás. Luego de leer la instrucción completa "BNE SIGO", el valor del PC es C013. La etiqueta SIGO segun la tabla de símbolos corresponde a la dirección C007. El offset lo obtenemos entonces restando donde queremos estar de donde estamos: C007-C013. Esta cuenta en hexadecimal nos da un valor negativo (podemos restar al revés y recordar aplicarle el signo negativo): -12 (en decimal). Nos queda expresar -12 en negativo como complemento a la base, lo cual equivale a 11110100 en binario, o F4 en hexadecimal.
Finalmente hay un salto en la última instrucción: FIN BRA FIN. En este caso el PC queda con el valor C017 y queremos que salte a C015, por tanto el offset es -2 (en decimal). Expresado en hexadecimal sería FE (negativo en complemento a la base).
Completemos el programa:
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 08 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 01 BLS Amenor
$C00D 17 TBA
$C00E 7A 00 03 Amenor DEC CANT
$C011 26 F4 BNE SIGO
$C013 97 00 STAA MENOR
$C015 20 FE FIN BRA FIN
Aunque todavía nos faltan determinar tres operandos de los branch del ejercicio, ya podemos completar la tabla de símbolos:
identificador valor (hexadecimal)
VEC 0040
MENOR 0000
DIRINI 0001
CANT 0003
VECTOR 0040
main C000
Amenor C00E
SIGO C007
FIN C015
RESET FFFE
¿Cómo calculamos el direccionamiento relativo de los saltos? Tal como vimos en el post sobre ese tema, lo que acompaña la instrucción de salto es el offset que se aplica al PC (claro está, cuando se cumple la condición del branch). Este offset puede ser positivo, lo que provocaría un salto hacia adelante, o negativo, que se traduce en un salto hacia atrás.
En el ejemplo tenemos los dos tipos de saltos. La línea BLS Amenor es un salto hacia adelante. Cuando CPU haya leído la instrucción completa (pero aun antes de ejecutarla) el PC tendrá el valor de la siguiente instruccion $C00D. La etiqueta Amenor corresponde a la dirección C00E -tal como apuntamos en la tabla de símbolos-. Haciendo la resta, C00E - C00D (donde queremos estar menos donde estamos) obtenemos el offset, en este caso 01.
Consideremos otro de los saltos: BNE SIGO. Este salto -de ejecutarse- es hacia atrás. Luego de leer la instrucción completa "BNE SIGO", el valor del PC es C013. La etiqueta SIGO segun la tabla de símbolos corresponde a la dirección C007. El offset lo obtenemos entonces restando donde queremos estar de donde estamos: C007-C013. Esta cuenta en hexadecimal nos da un valor negativo (podemos restar al revés y recordar aplicarle el signo negativo): -12 (en decimal). Nos queda expresar -12 en negativo como complemento a la base, lo cual equivale a 11110100 en binario, o F4 en hexadecimal.
Finalmente hay un salto en la última instrucción: FIN BRA FIN. En este caso el PC queda con el valor C017 y queremos que salte a C015, por tanto el offset es -2 (en decimal). Expresado en hexadecimal sería FE (negativo en complemento a la base).
Completemos el programa:
ORG $C000
$C000 DE 01 main LDX DIRINI
$C002 A6 00 LDAA 0,X
$C004 7A 00 03 DEC CANT
$C007 08 SIGO INX
$C008 E6 00 LDAB 0,X
$C00A 11 CBA
$C00B 23 01 BLS Amenor
$C00D 17 TBA
$C00E 7A 00 03 Amenor DEC CANT
$C011 26 F4 BNE SIGO
$C013 97 00 STAA MENOR
$C015 20 FE FIN BRA FIN
Note que la última dirección la anotamos para guiarnos en el cálculo del último offset, pero realmente no es parte de la respuesta a la consigna.
¿Qué les pareció el procedimiento? ¿Alguna duda?
En otro post les cuento el método más práctico -a mi criterio- para obtener rápidamente la representación en complemento a la base de un número.
Profeee en el caso que tenga que ensamblar la instruccion SUBD en modo directo, qué quieren decir las jj kk que hay en la parte de operando?
ResponderBorrarMicaela Ramos
Me corrijo, en modo directo noN Inmediato*
BorrarHola Micaela! SUBD resta en 16 bits (D menos memoria). Lo que le vas a restar lo podés indicar en modo inmediato, con el numeral. Ahora bien, si vas a restar en 16 bits, tenés que poner un operando de 16 bits. Por ejemplo:
BorrarSUBD #10FA
o tan siquiera
SUBD #0078
si es que el operando "cabe" en 8 bits. El asunto es que debés expresarlo en 16. Habría que ver qué hace el THRSim si en el fuente podés:
SUBD #78
probablemente le agregue los dos ceros delante del 78.
Muchas gracias profee! Saludos!
Borrarhola profe! estoy haciendo un ejercicio parecido a este pero además de guardar el numero mas grande me pide que guarde su dirección en DIR. No se como guardar su dirección del numero.
ResponderBorrarHola Griselda! Si estás recorriendo un vector usando el índice IX, por ejemplo habiendo leido el valor con algo asi como un "LDAA 0,x" entonces en el registro IX tenes la direccion. Bastará con hacer un "STX dir" para guardar la dirección. Obviamente dir es una palabra de 2 bytes.
BorrarGracias profe! le hago otra preg, si me pide el complemento de 16 bits, y me da la dirección del valor a complementar y la direccionen donde guardarlo. Lo que hice fue:
ResponderBorrarldd #0
subd dato
stad resul
mi duda esta en que según el ejercicio me da la "Dirección" del valor a complementar, por que no se si esta bien restarle Dato.