Por DaRKWiZaRDX
Aquí estoy de nuevo (para el lamento de tantos... xDDD), esta vez la lección
será bastante corta, ya que se trata de un tema bastante simple, pero MUY
importante.
Se trata de los modos de direccionamiento, que son las formas que tiene el
programador de decirle al procesador dónde leer/escribir, de forma que el
procesador no termine leyendo o escribiendo datos donde no debe. de hecho, en el
poco código que hemos visto hasta ahora ya vimos algunos modos de
direccionamiento:
LDA #$00 ; carga el valor $00 en A
Este es un modo de direccionamiento, el más simple de todos, denominado "Immediate", carga un valor dado por el programador (una constante) en un registro, sea A, X o Y.
Veámoslos todos juntos:
MODO DE DIRECCIONAMIENTO |
EJEMPLO |
DESCRIPCIÓN |
Immediate | LDA #$80 | El programador le da un valor constante. No debe leer de memoria. |
Accumulator | ASL A | Actúa siempre sobre el acumulador (A). |
Implied | SEI | No recibe parámetros, la instrucción de por sí sabe sobre qué registros actuar (si es que actúa sobre alguno). |
Zero Page | LDA $80 | Actúa sobre el valor contenido en un offset de 8bits (1 byte). |
Absolute | LDA $6100 | Actúa sobre el valor contenido en un offset de 16bits (2 bytes) |
Zero Page indexed X | LDA $80,X | Actúa sobre el valor contenido en un offset de 8bits + X. |
Zero Page indexed Y | LDA $80,Y | Actúa sobre el valor contenido en un offset de 8bits + Y. |
Absolute indexed X | LDA $6100,X | Actúa sobre el valor contenido en un offset de 16bits + X. |
Absolute indexed Y | LDA $6100,Y | Actúa sobre el valor contenido en un offset de 16bits + Y. |
Indexed indirect | LDA ($80,X) | Ver abajo. |
Indirect indexed | LDA ($80),Y | Ver abajo. |
Indirect absolute | JMP ($6100) | Ver abajo. |
Relative | BRA $FE (je) | Ver abajo. |
Como verás hay cuatro modos que usan indexado, ¿Qué significa esto? Que además
de
utilizar la dirección que le da el programador para leer/escribir, le sumarán a
esa
dirección el valor de un registro (sea X o Y) y usarán el resultado de esa
cuenta para
saber en qué dirección realmente van a leer/escribir. Veamos un ejemplo:
Supongamos que quiero poner un valor (supongamos que $10) en 10 direcciones
distintas,
esto podría ser que estoy "limpiando" memoria que usaré luego. El valor lo
pondré en el
acumulador y lo guardaré en 10 direcciones comenzando en $200.
Podría hacer:
LDA #$10 ;cargamos el valor en A
STA $200 ;lo guardamos en la primera
STA $201 ;en la segunda
STA $202 ;etc.
STA $203
STA $204
STA $205
STA $206
STA $207
STA $208
STA $209 ;en la décima
Pero haciendo esto ocuparíamos MUCHÍSIMO espacio de la ROM, cuando es mucho más
simple
hacer una rutina con el modo de direccionamiento indexado.
Al usar indexado sumaremos al offset (que en este ejemplo comienza en $200) el
valor
actual del registro X o Y. Es decir que si por ejemplo tenemos en el registro X
el valor
$16, si hacemos algo como "LDA $10,X" la operación real sería "LDA $10+$16", por
lo que
realmente no estaríamos leyendo de la dirección de memoria $10 sino de la $26.
Pero sigamos entonces con nuestro ejemplo, sabiendo ya lo del indexado haremos
lo
siguiente:
LDA #$10 ;el valor a guardar
LDX #$00 ;X comienza en 0, será nuestro contador
repetir:
STA $200,X ;guardamos en $200+X
INX ;instrucción que incrementa X por 1
CPX #10 ;comparamos X con #10 (decimal) (esto lo veremos en detalle más adelante)
BNE repetir ;si no es igual vuelve al principio (también lo veremos más
adelante)
Cada vez que se llega al INX se incrementa X por 1, y el "CPX #$10 |
BNE
repetir"
verifica si ya se llegó a 10 (nota que no puse #$10 sino #10, ya que no es un
valor
hexadecimal sino uno decimal).
Estos modos no actúan directamente sobre el parámetro que les da el programador, sino sobre el que está contenido EN LA DIRECCIÓN QUE LE DA EL PROGRAMADOR. Por ejemplo:
LDX #$00
LDA ($80,X)
Esta instrucción no leerá el valor que está en $80 y lo guardará en el
acumulador (eso lo haría LDA $80), lo que hará esta
instrucción será sumar el valor del registro X a $80, lo que da como resultado
$80, y entonces leer un valor de 16bits (2 bytes) de $80 - $81, y usar ese
valor para determinar el offset del que debe leer.
Si en el ejemplo anterior en $80-$81 estuviera almacenado (en orden invertido,
claro) $6589 entonces
LDA ($80) sería igual a LDA
$6589.
La razón por la que usaríamos LDA ($80) y no LDA $6589 es porque podríamos volver a utilizar el LDA ($80) para leer de OTRA posición de memoria simplemente cambiando el contenido de $80-$81, lo que no podríamos hacer si hubiéramos utilizado LDA $6589.
LDA ($80),Y
Lo que hace este modo de direccionamiento es leer un valor de 16bits de $80-$81, supongamos que en este caso el valor que leyó era $6589, entonces a ese número le suma el valor del índice Y (supongamos que sea $14), y el valor que se cargue en A será el contenido en la dirección $659D ($6589 + $14). Sólo puede usarse como índice en este modo de direccionamiento el registro Y.
LDA ($80,X)
En este modo de direccionamiento se suma el operando (en este caso es $80) más el contenido del registro X (supongamos que es $14), entonces la operación sería LDA ($94), por lo tanto, el valor que se cargará en A será el contenido en el valor que tenga $94 (si el offset $94 contiene $18, entonces $18 se carga en A). Sólo puede usarse como índice en este modo de direccionamiento el registro X.
Los modos de direccionamiento se basan en la posición actual del PC (el registro que contiene el offset de la instrucción que se está por ejecutar), al valor que le da el programador se le suma 1 para que un BRA $00 no salte hacia sí mismo. Por ejemplo:
LDA #$14
STA $86
BRA $02 ; este #$02 + 1 da #$03, lo que saltea el
LDX #$20
LDX #$20
STX $87
Como señalé en el comentario, en el BRA (instrucción para saltar, que lo hace siempre, sin condición), sabemos que si el parámetro hubiera sido 0 habría seguido hacia el LDX #$20, ya que siempre se le suma 1 al parámetro, pero como el parámetro es #$02, y 2 + 1 = 3, entonces sabemos que el branch adelantará 3 bytes, lo que lo dejará en el STX $87. Espero que haya quedado claro, la verdad es que es bastante simple, pero por mi forma de explicar...
Pero igualmente cuando escribas código probablemente usarás etiquetas. Por ejemplo:
LDA #$00
TAX
loop:
STA $4000,X
INX
CPX #$20
BNE loop
<sigue el código> ; por si no lo entendiste este código
llena con $00 una zona de 32 bytes (20 hex) a partir de $4000.
Como ves en lugar de poner un número puedes poner una etiqueta, todos los ensambladores que conozco soportan etiquetas, si el tuyo no lo hace, pues cambia de ensamblador :P
Vamos, que falta poco, una lección más y ya terminamos xD