Volver
Capítulo 3: Modos de Direccionamiento

Por Dark-N: hernaldog@gmail.com
http://darknromhacking.com


Versiones

  • 1.2:
       -Pasado a HTML.
  • 1.1:
       -Revisado y corregido algunos errores de explicación en algunos MD complicados.
  • 1.0:
       -Versión original.


    Introducción

    ¡Hola a todos! Si me he demorado en sacar este capítulo es que ahora realmente estoy aprendiendo bien este asunto del asm y no quería hacer una guía simplona donde liste los modos de direccionamiento en no mas de 3 páginas, sino que quise profundizar en los temas de como obtener la Dirección Efectiva y otras cosas.

    Los Modos de Direccionamiento (MD desde ahora) es la forma como el procesador interpreta un comando o un estilo de escribir una dirección, así si escribimos LDA #$20 no es lo mismo que poner LDA $20, el procesador entiende diferente ambas instrucciones.

    En este capitulo enseñare los MD básicos, como leerlos y escribirlos. También dejaré en la sección Gusto a Poco, algunos ejercicios con sus respuestas.

    Nota: en este capítulo las cosas se empiezan a complicar, así que no avancen hasta que entendieron o creen que entendieron.


    Los Modos de Direccionamiento de la SNES

    Estos son los modos de direccionamiento básicos usados por la SNES, quizás no lo entiendan simplemente mirando la lista, pero mas abajo enseñare como leerlos y escribir cualquier MD:
    Modo de DirEjemplo
    ImmediateLDA #$12
    AbsoluteLDA $1234
    Absolute LongLDA $123456
    Absolute Long IndirectLDA ($123456)
    Absolute Long Indexed XLDA $123456,X
    Absolute Long Indexed YLDA $123456,Y
    Absolute Indexed X IndirectJMP ($1234,X)
    Absolute Indexed Y IndirectLDA ($1234,Y)
    Absolute Indirect LongJMP [$1234]
    Direct PageLDA $12
    Direct Page IndirectLDA ($12)
    Direct Page Indirect Indexed,YSTA ($12), Y
    Direct Page Indirect Indexed,XSTA ($1234), X
    Direct Page Indirect LongLDA [$12]
    Direct Page Indexed,XLDA $12,X
    Direct Page Indexed,YLDA $12,Y
    Direct Page Indirect Long Indexed,XLDA [$1C],X
    Direct Page Indirect Long Indexed,YLDA [$1C],Y
    Program Counter RelativeBEQ $04
    Program Counter Relative LongBRL $1234
    Stack RelativeLDA 15,S
    Stack Relative Indirect Indexed XLDA (09,S),X
    Stack Relative Indirect Indexed YLDA (2B,S),Y
    Block MoveMVP 0,0
    AccumulatorASL A



    Notaciones de los MD

    Lo primero es saber las notaciones de Long, Indirect, Indexed, Indirect Long y Stack Relative que son las más usadas en los Modos de Direccionamiento.

  • Indirect = ( )
       Indirecto quiere decir que accedemos al contenido de una dirección de 1/2 bytes.

  • Indexed X = ,X
       A un Dirección le agregamos el Índice que en este caso es X, se escribe con una ‘,‘ antes de la X.

  • Indirect Long = [ ]
       Este significa que accedemos a una dirección de 3 bytes y no de 2, es decir: Banco + Offset (ejemplo $FF:$1234).

  • Stack Relative = ,S
       Se le agrega a la dirección una S que es el Stack o Pila con una coma ‘,’ antes.

  • Dirección Efectiva (Efective Address o EA)
       Es la dirección final que se procesa, es como la “ecuación” o “código” que indica la dirección donde debe acceder la CPU para realizar la operación. Su notación es:    EA= Mem< num_bytes dir leer/escribir > [< dirección >].



    Los MD más Comunes

    Los MD se usan en cada cargada de un registro (algún LDA) o de un guardado/store en la memoria (STA).

    Ahora explicare los MD, algunos son iguales que otros, solo cambia el uso del registro X o Y.


    Immediate (Immediato)

    Aquí cargamos DATOS en la instrucción. Aquí no hay Dirección Efectiva o EA.
    Effective Adress(EA) = no hay
    Esto de EA quedará mas claro con otros MD.

    Ejemplo 1:
    LDA #$05 ; cargamos el valor/dato 5 en A. Si A esta seteado en modo de 8 bits entonces el valor a almacenar no puede ser mayor a 8 bits. Y si A esta seteado en modo de 16 bits, no puede almacenar un valor mayor a 0xFFFF.

    Recuerda esto:

    -Un valor/dirección de 8 bits puede ser de 00 a FF.
    -Un valor/dirección de 16 bits puede ser de 0000 a FFFF.
    -Un valor/dirección de 24 bits puede ser de 000000 a FFFFFF.



    Absolute (Absoluto)

    EA = Dir

    En este caso, EA = dir, ya que la dirección efectiva es la dirección a la que se accede. Aquí siempre la dirección es siempre de 2 bytes.

    Ejemplo:
    LDA $123C ; Carga UN byte de la dirección 123C en caso que el BIT del Modo del CPU del registro P, esta 8 bits y carga DOS bytes si el Bit de estado del CPU esta en 16. Esta dirección puede ser en la RAM o Rom según el Banco, en este caso como no se dice nada, se asume el banco del registro PBR.

    Entonces la EA para este ejemplo sería: (lo haré paso a paso para que lo entiendan):
    EA= $123C


    Absolute Long (Absoluto Largo)

    EA = Dir

    En Absolute Long/Indirect Long la dirección es de 3 bytes, así que podemos en una sola instrucción acceder al mapa completo de instrucciones ya que podemos hacer LDA $AB3456 (banco $AB y dirección $3456).

    Ejemplo1:
    LDA $808000 ; Carga en A 1 o 2 bytes de $80:8000 (banco 80, dirección 8000). Recuerda 1 o 2 bytes debido a como este seteado el bit de Modo del CPU.
    EA=$808000


    Absolute Long Indirect (Aboluto Largo Indirecto)

    EA=Mem2[dir]

    Accedemos a una dirección de 3 bytes y esa dirección contiene otra de 2 bytes.

    Ejemplo1:
    LDA ($123456) ; Dentro de la dirección $123456 esta la dirección $1234 y dentro de $1234 esta al valor que se asigna a A.

    ¿Mem2?
    EA=vamos por paso...
    EA= $123456 -> ir a memoria y ubicar la dirección de 3 bytes
    EA= Mem2[$123456] ->dentro de esa dirección encontrar la siguiente dirección de 2 bytes, pero ¿Por qué de 2 bytes? Es así ya que hablamos de Absolute Long Indirect y no Absolute Long Indirect Long, El “Indirect” es siempre de 2 bytes, el “Indirect Long” es de 3 bytes, por eso usamos un Mem2 y no Mem3.


    Absolute Long Indexed X/Y (Absoluto Largo Indexado X/Y)

    EA=dir+X/Y, simplemente la dirección efectiva es la dirección mas el valor del índice X/Y.

    El índice X/Y aparece aquí por primera vez, ya que en los modos indexados se ocupan para hacer un “recorrido” de direcciones o asignaciones, es como hacer un “ciclo for”.
    ¿Qué pasa si queremos asignar a A los valores que estan desde una cierta dirección de memoria a otra dirección, con unas pocas instrucciones?
    Fácil, con el índice X/Y podemos incrementarlos y usarlos con LDA, luego con un Salto (recuerden capítulo 2) podemos hacer que se ejecute de nuevo LDA con X/Y pero con el X/Y incrementado y así sucesivamente.

    Ejemplo1:
    LDA $7E8000, X ; Carga en A 1/2 bytes de $7E:8000 + X.
    El CPU lo traduce así: “cargar 1 /2 bytes en Acumulador lo que esta en la dirección [8000 + el valor del registro X], del banco 7E, es decir de la RAM. ¿fácil, no?

    EA=$7E8000+X

    Ejemplo2:
    LDA $FF9090,Y ; Carga A con 1/2 bytes que estan en $FF:9090 + Y


    Absolute Indexed X/Y Indirect (Absoluto Indexado Indirecto)

    EA= Mem2[dir+X/Y]

    Aquí se empieza a complicar la cosa un poco, ya que aquí hablamos de una Dirección de una Dirección Indexada, veamos como es esto con ejemplos.

    Ejemplo1:
    LDA ($1238,X) ; Accedemos a la dirección 1238 + X y dentro hay otra dirección, y en esta ultima dirección hay 1 o 2 bytes que se asigna a A. ¿Quieren un ejemplo grafico de esta situación? Aprovecharé para enseñar varias cosas que utilizare de aquí en adelante.
    Asumamos que tenemos esto en memoria RAM:

    Asumiendo que X=4hex o 0x4 que es lo mismo, tenemos que 1238 + 4 = 123C y dentro de esta dirección esta el valor hex 0x14F0. Desde ahora los valores hex dentro de una dirección de memoria, le pondremos un “0x” antes. Es la notación usada por los editores hex. Bueno, dentro de 123C esta el valor 0x14F0, pero el MD que estamos analizando dice la dirección de la dirección indexada, por lo que el 0x14F0 pasa a ser una dirección. La buscamos y contiene el valor 0x15C1. Este es el valor que se le asigna al acumulador.

    EA=Mem2[$1238+X], y si dijimos que X = 4hex => EA = Mem2[$123C]


    Absolute Indirect Long (Absoluto Indirecto Largo)

    EA= Mem3[dir]

    El concepto es simple: dentro de una dirección de 2 byte hay otra dirección de 3 bytes.

    Ejemplo1:
    LDA [$123A] ; En la dirección 123A hay otra dirección de 3 bytes (long) y esa dirección contiene el valor de 1/2 bytes que se cargará en A.
    Ejemplo grafico, si tenemos en memoria:

    En 123A hay un dirección de 3 bytes, $8014F0, al ir hacia ella y examinamos el valor que contiene es 0x15C1, este se le asigna a A.

    EA= Mem3[$123A]


    Direct Page (Pagina Directa)

    EA = dir

    Este modo es igual al Absoluto pero aquí la dirección es de 1 byte siempre.

    Ejemplo1:
    LDA $2C ; se carga en A lo que esta en la dirección 2C.

    EA=$2C


    Direct Page Indexed, X/Y

    EA=dir + X/Y

    Dentro de la dirección de 1 byte + índice X/Y hay un valor.

    Ejemplo1:
    LDA $3B,X ;Se carga en A lo que hay en la dirección 3B + X.

    EA=$3B+X


    Direct Page Indirect Long

    EA=Mem3[dir]

    Aquí dentro de una dirección de 1 byte hay otra dirección de 3 bytes.

    Ejemplo:
    LDA [$12] ; dentro de la dirección 12 hay una dirección 123456 y dentro de esa dirección esta el valor que se asigna a A.

    EA=Mem3[$12]


    Direct Page Indirect Long Indexed, X/Y

    EA=dir -> Direct Page
    EA=Mem3[dir] ->Indirect Long
    EA=Mem3[dir] +X -> indexed X


    Dentro de la dirección de 1 byte hay una dirección de 3 bytes, le sumamos X/Y a esa dirección y nos da la dirección final, la Dirección Efectiva.

    Ejemplo:
    LDA [$CC],X

    EA = Mem3[$CC] + X


    Program Counter Relative

    EA = dir

    Este modo de direccionamiento se usa en los SALTOS (recuerden capitulo anterior) pero de direcciones de 1 byte, estos saltos pueden ser:

    BCC - branch if carry clear (Carry=0)
    BCS - branch if carry set (Carry=1)
    BEQ - branch if equal
    BMI - branch if minus
    BNE - branch if not equal
    BPL - branch if plus
    BRA - branch always
    BVC - branch if overflow clear
    BVS - branch if overflow set

    Ejemplo1
    BCC $E5 ; salta a la dirección indicada dentro de $E5 si el Flag Carry es 0. Para saber como operan los demás Flag, ver capítulo 1.

    EA = $E5


    Program Counter Relative Long

    EA = dir

    Igual que antes, pero ahora las direcciones son de 2 bytes.

    Ejemplo:
    BRA $123C ;salta a $123C siempre, es decir sin condiciones (no le importa el carry, ni ningún otro Flag).


    Stack Relative

    EA= dir 1/2 byte ->contenido Stack + dirección de 1 bytes.

    Este MD está basado en operaciones que se hacen a la Pila o Stack, que es un registro (ocupa por lo tanto un área en la memoria) y que se usa para almacenar datos de los registros de la CPU de la Snes como A, X o Y que NO DEBEN perderse durante la ejecución de una rutina determinada.
    En una Pila los datos se “apilan”. Para meter (copiar) un valor del acumulador a la Pila se ocupa la instrucción PHA, y para sacar un valor de la Pila y dejarlo en el acumulador se usa PLA. La imagen muestra como son estos simples procesos:

    Como se fijaron la Pila la ASUMIMOS por ahora de tamaño 1 byte. Ahora que saben más o menos como trabaja una pila.

    Ejemplo:
    LDA $01,S ; El contenido del Tope del Stack ($01 indica la primera posición, un $02 la segunda, etc…) forma la Dirección Efectiva donde esta contenido el dato que se asignara a A.

    EA= $01


    Stack Relative Indirect Indexed X/Y

    EA=Mem2[$01,S] + X -> Lo que se hace es ir sumar la dirección de 1 byte dada en el operando al contenido del Stack, luego buscamos esa dirección en memoria y el contenido es otra dirección que sumada a X nos da la dirección Efectiva.

    Ejemplo: LDA ($01,S),X ; si el stack tiene el valor 0x05 en el tope ($01 indica TOPE) y X tiene 0x2, entonces se pasa a A lo que esta en el Tope de la pila (0x05)+ X(0x02) = 0x07=>buscamos valor que esta dentro de dirección $07.


    Acumulator (Accumulador)

    EA = no tiene

    Simplemente cualquier instrucción que opere directamente el acumulador estaría dentro del Modo de D. Acumulador.

    Ejemplo:
    ASL A ;multiplica A por 2





    Gusto a Poco

    Esta vez les pongo los ejercicios. Las respuestas están al final.

    1. Dado el MD escribe un ejemplo de:

    a) absolute indirect indexed X
    b) absolute indexed indirect
    c) direct page indexed indirect long stack relative
    d) absolute long indirect indexed indirect stack relative
    e) stack relative indirect indexed,X indirect long indexed,Y (Asume que el stack relative es de 1 byte)
    f) direct page indirect indirect long indexed Y indirect indexed X
    g) direct page indexed indirect
    h) stack relative indirect long indexed X indirect indexed Y indirect long

    2. Responde:

    a) En una traza obtenida con Snes9x Debugger del juego Mystical Ninja se tiene esta linea:
        $00/A08A 91 03 STA ($03),y[$7E:2155] A:00FF X:0155 Y:0155 P:envMxdIzc
        Explicar que hace e indicar el MD.
    b) ¿Cual es la diferencia entre Indirect address de una Indirect long address?
    c) ¿Qué hace: [$123456],Y ? Explique.
    d) Defina brevemente Modo de Direccionamiento.

    3. Escribe el código de EA de las siguientes MD:
        (Recuerda: Mem[..] para el Indirect y usa +X o +Y para Indexed)

    a) [$123456],Y:
    b) direct page indirect indexed X indirect long indexed Y
    c) Abolute indirect
    d) absolute indexed x indirect long indirect stack relative

    4. Dado el código EA escribe el MD:

    a) EA = Mem2[$12+X]+Y
    b) EA = Mem3[Mem2[$12 + Y] + Y] + S
    c) EA = Mem2[$12+S]+X+Y

    5. Programación básica en ASM. Realiza rutinas dado el seudo-código (Si no pueden no se preocupen ya que el capitulo siguiente será de este puro tema, pero deberían poder hacerlo usando este capitulo y el anterior, y obviamente…sus neuronas.

    a) X = A – 3
    b) X = Y + 2
    c) A = A – 5 + 1
    d) Si carry=0 salta a lo que haya en $12, sino, retorna y sale de la actual subrutina


    Respuestas

    1.

    a) ($421C),X
    b) ($02FC,X)
    c) dirección de 1 byte: $12
        indexed X : $12,X (mas adelante sabrás que X es mejor que Y)
        y luego usa [] en vez de ( ): [$12,x],S
    d) (([$1234]),x),s
    e) ($01,S),X
        [($01,S),X],Y
    f) ($12)
        [($12)],Y
        ([($08)],y),x
    g) ($08,x)
    h) [([$01,S],X), Y]


    2.

    a) $00/A08A: dirección de memoria
        STA ($03),y: Modo de Direccionamiento es Direct Page Indirect Indexed,Y. Explicación: Dentro de la dirección de 1 byte ($03) hay una dirección de 3 bytes, le sumamos Y=0x155 (ver traza Y:0155) a esa dirección y nos da la dirección final o la Dirección Efectiva $7E:2155.
        [$7E:2155] es la dirección efectiva o final donde se guardará el dato, el Log lo muestra para que uno no se pierda.
        P:envMxdIzc: nos dice que Flags e,n,v,x,d,z,c están en 0, y M,I en 1.

    b) Indirect long address es una indirect address que lee un puntero de 3 bytes en vez de 2 bytes.

    c) Va a $123455, lee 3 bytes y añade Y a ese valor, y luego toma la información de esa dirección.

    d) Es una manera para describir una dirección que nos ayuda a determinar una dirección final o dirección efectiva.


    3.

    a) EA = Mem3[$123456] + Y
    b) EA = Mem3[Mem2[$12]+X]+Y
    c) EA = Mem2[$1234]
    d) EA = Mem2[Mem3[$1234+X]]+S


    4.

    a) Direct page indexed x indirect indexed y
    b) DP indexed Y indirect indexed Y indirect long stack relative
    c) DP stack relative indirect indexed x indexed Y


    5.

    a) X = A – 3
    SEC ; deja el carry en 1, siempre debe ir antes de SBC
    SBC #$03 ; A=A-3 + carry (vale 1 por SEC) – 1 => A = A - 3
    TAX ; X vale lo de A

    b) X = Y + 2
    INY
    INY
    TYX ; x vale lo que vale Y

    c) A = A – 5 + 1
    SEC ;(próximo capítulo mas del uso de SEC)
    SBC #$04

    d) Si carry=0 salta a lo que haya en $12, sino, retorna y sale de la actual subrutina
    BCC $12
    RTS ; Return from Subroutine


    Volver
    blog comments powered by Disqus
    2003 - 2018    La Web de Dark-N