Instrucciones de salto incondicional

La única instrucción de salto incondicional es:

  • “jmp”.

“jmp” produce un salto en el contador de programa a la dirección indicada, cuando se utiliza el modo de direccionamiento absoluto (ej. “jmp $c000”). Y produce un salto a la dirección contenida en la dirección indicada (puntero o vector), cuando se utiliza el modo de direccionamiento indirecto (ej. “jmp ($c000)).

En este último caso, puesto que una posición de memoria sólo puede contener un único byte, y una dirección del C64 requiere dos bytes, se aplica la regla de que el LSB de la dirección de destino está en la posición indicada en la instrucción, y el MSB de la dirección de destino está en la posición siguiente (ej. $c000 => LSB destino, $c001 => MSB destino). Esto es así porque el 6510 sigue la arquitectura “Little endian”.

Jmp

“jmp” no soporta más modos de direccionamiento. Sólo el absoluto y el indirecto. Y no modifica ningún flag del registro de estado.

Sus detalles pueden verse aquí: http://www.6502.org/tutorials/6502opcodes.html#JMP.

Instrucciones de rotación de bits

Las instrucciones de rotación de bits son:

  • “rol”.
  • “ror”.

Estas instrucciones son básicamente equivalentes a las ya vistas “asl” y “lsr”, con la única diferencia de que el bit que sale del acarreo se vuelve a introducir en el bit 0, en el caso de “rol”, y en el bit 7, en el caso de “ror”.

Rot bits

Estas instrucciones soportan los mismos modos de direccionamiento que “asl” y “lsr”, es decir, los modos: acumulador, absoluto, página cero, absoluto indexado y página cero indexado. Y afectan a los mismos flags: S – sign, Z – zero y C – carry.

Sus detalles se pueden consultar aquí: http://www.6502.org/tutorials/6502opcodes.html#ROL.


Programa de ejemplo: Prog19

Instrucciones de desplazamiento de bits

Las instrucciones de desplazamiento de bits ya se presentaron al hablar de multiplicaciones y divisiones:

  • “asl”.
  • “lsr”.

La instrucción “asl” mueve los bits del acumulador (o de una posición de memoria) un bit a la izquierda, metiendo el bit más significativo (bit 7) en el flag C – carry, y un bit a 0 en el bit menos significativo (bit 0). Esta operación equivale a multiplicar por dos.

Contrariamente, la instrucción “lsr” mueve los bits del acumulador (o de una posición de memoria) un bit a la derecha, metiendo un bit a 0 en el bit más significativo (bit 7), y el bit menos significativo (bit 0) en el flag C – carry. Esta operación equivale a dividir por dos.

Desp bits

Estas instrucciones son útiles, con carácter general, para manipular bits. Por ejemplo, moviendo cuatro bits a la derecha, se puede pasar de un byte a su nibble más significativo.

Estas instrucciones soportan los modos de direccionamiento acumulador, absoluto, página cero, absoluto indexado y página cero indexado. Y afectan a los flags S – sign, Z – zero y C – carry.

Sus detalles se pueden consultar en http://www.6502.org/tutorials/6502opcodes.html#ASL y http://www.6502.org/tutorials/6502opcodes.html#LSR.


Programa de ejemplo: Prog18

Bucles

Juntando contadores, comparaciones y saltos condicionales es muy fácil hacer bucles, que son construcciones muy típicas en todo tipo de programación consistentes en repetir la ejecución del mismo segmento de programa N veces, hasta que se cumple una condición de fin.

En ensamblador del 6510 hay muchas formas de hacer bucles, pero la forma más típica consiste en utilizar el registro X o el registro Y como contador (creciente o decreciente), comparar X o Y contra un valor de fin y, mientras no se alcance ese valor de fin, incrementar / decrementar el contador y repetir la ejecución.

También es posible hacer bucles con contadores basados en posiciones de memoria (instrucciones “inc” y “dec”). Una ventaja de hacer esto es que, mediante el uso de varios bytes, se pueden superar fácilmente las 256 iteraciones, que es el tope cuando se utiliza un único registro índice (8 bits).


Ejemplo de bucle basado en el registro X: Prog08
Ejemplo de bucle basado en posiciones de memoria: Prog10

Instrucciones de comparación

Las instrucciones de comparación son:

  • “cmp”.
  • “cpx”.
  • “cpy”.

La primera compara el acumulador con el operando. La segunda compara el registro X con el operando. Y la última compara el registro Y con el operando.

En los tres casos, la comparación se articula como la resta registro – operando, y los flags del registro de estado se activan o desactivan en función de esa resta. Por ello, si la comparación/resta arroja la igualdad, se activa el flag Z – zero; en caso contrario, se desactiva el flag Z – zero. Igualmente, si la comparación/resta arroja que el registro es mayor que el operando (resta positiva), se activa el flag C – carry; en caso contrario (resta negativa), se desactiva el flag C – carry.

“cmp” soporta los modos de direccionamiento inmediato, absoluto, página cero, absoluto indexado, página cero indexado, indirecto – indexado e indexado – indirecto. Por su parte, “cpx” y “cpy” sólo soportan los modos de direccionamiento inmediato, absoluto y página cero.

Todas estas instrucciones modifican los flags S – sign, Z – zero y C – carry. Sus detalles se pueden consultar aquí: http://www.6502.org/tutorials/6502opcodes.html#CMP.

Instrucciones de incremento/decremento

Las instrucciones de incremento/decremento son:

  • “inx”.
  • “dex”.
  • “iny”.
  • “dey”.
  • “inc”.
  • “dec”.

Las dos primeras valen incrementar/decrementar el índice X. Las dos segundas valen para incrementar/decrementar el índice Y. Y las dos últimas valen para incrementar/decrementar una posición de memoria.

Incrementar/decrementar el índice X o el índice Y es útil para recorrer zonas de memoria (modos de direccionamiento indexados) y para implementar contadores. Incrementar/decrementar posiciones de memoria también es útil para recorrer zonas de memoria (modos de direccionamiento indirectos) y para implementar contadores. Y una aplicación obvia de los contadores son los bucles.

Las instrucciones “inx”, “dex”, “iny” y “dey” utilizan el modo de direccionamiento implícito y afectan a los flags S – sign y Z – zero.

Las instrucciones “inc” y “dec” soportan los modos de direccionamiento absoluto, página cero, absoluto indexado y página cero indexado, y también modifican los flags S – sign y Z – zero.

Los detalles de estas instrucciones se pueden consultar en http://www.6502.org/tutorials/6502opcodes.html#INX, http://www.6502.org/tutorials/6502opcodes.html#INC y http://www.6502.org/tutorials/6502opcodes.html#DEC.

Instrucciones de salto condicional

Las instrucciones de salto condicional o “branches” (bifurcaciones) son:

  • “beq” = branch on equal
  • “bne” = branch on not equal
  • “bcs” = branch on carry set
  • “bcc” = branch on carry clear
  • “bpl” = branch on plus
  • “bmi” = branch on minus
  • “bvs” = branch on overflow set
  • “bvc” = branch on overflow clear

Estas instrucciones dan un salto a la dirección indicada (en realidad usan el modo de direccionamiento relativo, es decir, un offset) cuando se cumple una determinada condición, y continúan con la siguiente instrucción cuando no se cumple. Las condiciones se basan en los flags del registro de estado.

“beq” y “bne”

Estas instrucciones se basan en el flag Z – zero. “beq” salta cuando Z está activado y “bne” cuando no lo está.

El hecho de hablar de “equal” o “not equal” viene de que, como veremos más adelante, el microprocesador realiza las comparaciones mediante una resta, lo que significa que la igualdad equivale a una resta cero, y la no igualdad a una resta distinta de cero.

“bcs” y “bcc”

Estas instrucciones se basan en el flag C – carry. “bcs” salta cuando C está activado y “bcc” cuando no lo está.

Como ya vimos, el flag C se activa cuando una suma (“adc”) desborda la capacidad del acumulador (“me llevo una”). Y se desactiva cuando una resta (“sbc”) es negativa (“tomo una”).

“bvs” y “bvc”

Estas instrucciones se basan en el flag V – overflow. “bvs” salta cuando V está activado y “bvc” cuando no lo está.

El flag V se activa cuando al sumar dos números positivos el resultado es negativo. Si se está trabajando con números con signo hay que detectar esta situación para evitar interpretar el resultado de forma incorrecta.

“bmi” y “bpl”

Estas instrucciones se basan en el flag N – negative o, lo que es lo mismo, el flag S – sign. “bmi” salta cuando N está activado y “bpl” cuando no lo está.

El flag N se activa cuando, como resultado de una instrucción, el bit de signo (bit 7) está activado.

Modos de direccionamiento y flags

Todas estas instrucciones utilizan el modo de direccionamiento relativo. Es decir, aunque el programador utilice como destino una dirección de memoria o una etiqueta (ej. “beq iguales”), el ensamblador al ensamblar sustituye esa dirección o etiqueta por un offset, es decir, un salto hacia delante o hacia atrás de N posiciones de memoria. Ese N puede oscilar entre 127 y -128 posiciones de memoria, y se cuenta respecto del primer byte de la instrucción siguiente.

Respecto a los flags, estas instrucciones no los modifican. Al contrario, y como ya se ha visto, utilizan los flags como información de entrada para determinar su funcionamiento (salto o no salto).

Los detalles de estas instrucciones pueden consultarse aquí: http://www.6502.org/tutorials/6502opcodes.html#BRA.

Otras instrucciones relacionadas

Las instrucciones de salto condicional se suelen usar conjuntamente con instrucciones de incremento/decremento y comparaciones, que se verán en las entradas que siguen. Se usan conjuntamente para implementar bucles.


Programa de ejemplo: Prog17