CURSO DE ASSEMBLER
Por Willy Soft
4. Instrucciones LDA, LDX, LDY y JSR.
Ahora vamos a ver las instrucciones básicas de Assembler del procesador 6502, el cerebro de nuestro Atari 8-bits. Para ello, es necesario que tengamos claro el concepto de registro de procesador y registro de memoria.
El procesador 6502 tiene tres registros principales:
* El Acumulador: es el registro más utilizado, ya que la mayoría de las instrucciones del procesador utiliza este registro. Se conoce también como “A”.
* El registro X.
* El registro Y.
Cada uno de estos registros almacena un valor de 8 bits (un byte), es decir, un número entre 0 y 255 (00000000 a 11111111 en binario, recuerden el capítulo 2).
Un registro de memoria consiste en un número de 8 bits (0 a 255) almacenado en la memoria del computador. Cada registro de memoria está identificado a través de una dirección. Para el caso del Atari 8-bits, existen 65.536 direcciones para almacenar y/o manipular datos de memoria.
¿Cuál es la diferencia entre un registro de procesador y uno de memoria? En que el primero está ubicado internamente en el 6502, mientras que el segundo está fuera. Esto significa que si el 6502 quiere utilizar alguna de las posiciones de memoria, está obligado a hacer un llamado a la memoria para que ésta le traiga el dato. Esquemáticamente sería así:
Ahora, lo interesante de todo este asunto es que el procesador trabaja más bien con sus registros. Cada operación interna lo hace a través de ellos. La memoria lo utiliza para leer o escribir datos. El procesador tiene formas muy útiles en todo caso de cómo puede acceder a la memoria, pero en un principio nos abocaremos a maneras simples. Después iremos subiendo de nivel.
Instrucción LDA
La instrucción para cargar un valor cualquiera en el Acumulador se llama LDA. (LoaD Accumulator). Esta instrucción te carga dicho registro con un valor entre 0 y 255. La forma de trabajar esta instrucción, para efectos de este capítulo, son las siguientes:
LDA #VALOR
LDA POSICION_DE_MEMORIA
Existen otras formas de utilizar esta instrucción, pero no las veremos hasta después.
¿Cuál es la diferencia entre el primer LDA y el segundo? La diferencia radica en el “#”. La primera forma lo que hace es cargar el valor en sí, mientras que la segunda forma lo que hace es cargar el valor contenido en la posición de memoria respectiva.
Ejemplos:
LDA #100
Carga el acumulador con el valor 100
LDA 100
Carga el valor de la posición de memoria 100.
¿Qué significa lo segundo? Si el valor de la posición de memoria 100 tiene un cero (0), el acumulador va a quedar con el valor 0. Si dicha posición tiene un valor 50, el acumulador va a tener el valor 50.
Es muy importante que tengan claro la diferencia. Por eso insisto mucho en ello.
Para cargar valores en el acumulador, ustedes pueden escribir un mismo valor ya sea como valores decimales, hexadecimales o bien el valor de un carácter equivalente en ASCII. Ejemplos:
LDA #65
: Carga el valor 65 en decimal.
LDA #$41
: Carga el valor $41 en hexadecimal, 65 decimal.
LDA #’A
: Carga el valor ASCII de la letra “A”, en este caso, 65. Noten el apóstrofe.
Estas nomenclaturas son las más utilizadas. En el listado al final de este capítulo veremos un ejemplo.
Como ya imaginarán ustedes, los registros X e Y se cargan con las instrucciones LDX y LDY, respectivamente. Su utilización es exactamente igual. Lo importante es que sepan que se cargan de la misma manera.
Esto es lo más importante hasta ahora respecto a esas instrucciones. Ahora veremos la otra instrucción, la JSR.
Instrucción JSR
La instrucción JSR significa (Jump SubRoutine). Lo que hace es llamar a una subrutina dentro de un programa, para después volver con la ejecución principal. Esta instrucción es muy parecida a la instrucción GOSUB desde Basic. O, también considerarse, a una llamada a algún procedimiento. Lo interesante de esta instrucción es que vuelve automáticamente a la instrucción siguiente del gosub, después de terminar la subrutina. La forma de utilizar dicha instrucción es la siguiente:
JSR dirección_de_memoria.
Ejemplos:
JSR 8192
JSR $2000
: En hexadecimal.
? JSR $F2B0
Ahora, como pueden ver, lo que utiliza el assembler son direcciones de memoria fijas. Esto es porque las instrucciones de procesador se encuentran contenidas en posiciones de memoria fijas. Lo interesante es que el assembler además te permite trabajar con etiquetas (labels) que después se convierten en números cuando se compilan, según la posición de memoria en que se corre en ese instante.
Para entender esto, escriban lo siguiente en su IDE de preferencia:
* = $6000
inicio
lda #'H
jsr $f2b0
lda #'O
jsr $f2b0
lda #'L
jsr $f2b0
lda #'A
jsr $f2b0
loop
jmp loop
*=$2e0
.word inicio
La primera línea indica a qué dirección de memoria va a compilar, en hexadecimal. En este caso $6000
. La segunda línea, “inicio
”, le indica al assembler que esa dirección $6000
se va a identificar con la etiqueta nombrada. En este caso, “inicio
” va a tomar el valor $6000
en hexadecimal. La tercera línea (LDA #’H
) carga el acumulador con el valor ASCII de la letra
“H
” (72
). La cuarta línea (JSR $F2B0
) carga una subrutina ubicada en la dirección de memoria $F2B0
en hexadecimal. Esta dirección es de la ROM del Atari 8-bits, y corresponde a una rutina que imprime en pantalla el carácter ASCII
equivalente al valor que contiene el acumulador. En este caso, como tiene el valor del carácter de “H
”, va a imprimir un “H
”.
Luego repite otras 3 veces, pero con valores distintos del acumulador (“O”, “L”, “A”).
Finalmente, hace un loop infinito. No les comento qué hace en particular ese conjunto de instrucciones, ya que lo veremos posteriormente en otro capítulo.
Compilen el programa con CONTROL-1, y ejecuten el ejecutable en el emulador. Tendrá que salir lo siguiente:
Bueno, hemos testeado las primeras instrucciones, con más comentarios.
PREGUNTA TUS DUDAS O DANOS TUS SUGERENCIAS EN EL FORO
IR a capítulo 1 2 3 4 5 6 7 8 9