Información del microprocesador 6502
Escrito el Sábado 21 de Marzo del 2009 por Ealdor
La mayoría de la información de este documento ha sido tomada del manual "Commodore 64 Programmers Reference Manual", simplemente porque estaba disponible en formato electrónico y no hay diferencia entre esta documentación y la documentación del 6502. He hecho algunos cambios y adiciones donde he considerado apropiado.
En teoría deberías ser capaz de poder usar cualquier codigo que puedas encontrar aquí para emular el 6510 (el procesador de la C64).
[A] Los registros dentro del microprocesador 6502
La mayoría de los cálculos se hacen en el microprocesador. Los registros son piezas especiales de memoria las cuales serán usadas para cargar hacia afuera, y para almacenar información de los cálculos. El 6502 tiene los siguientes registros:
(1) El acumulador
Este es el registro MAS importante del microprocesador. Varias instrucciones en lenguaje máquina te permiten copiar el contenido de una localización de memoria al acumulador, copiar el contenido del acumulador en una localización de memoria, modificar el contenido del acumulador o algún otro registro directamente sin que afecte a la memoria. Y el acumulador es el único registro que dispone de intrucciones para realizar cálculos matemáticos.
Todas la operaciones entre localizaciones de memoria deben ser comunicadas a traves del acumulador o de uno de los registros auxiliares indexados. El acumulador es usado como almacenamiento temporal en operaciones demovimiento de datos de una localización de memoria a otra. Luego, el primer uso del acumulador es simplemente el de mover datos de la memoria al acumulador o del acumulador a la memoria. Uno puede traer datos al acumulador, ejecutar operaciones tales como AND/OR, testear el resultado de esas operaciones, activar nuevos bits en el, o transferirlo hacia el mundo de afuera. Sirve como almacenamiento intermedio para una serie de operaciones tales como sumar 2 valores; donde uno de ellos es cargado en el acumulador, el segundo sumado a el, y el resultado almacenado en el acumulador. El acumulador realmente tiene dos funciones:
1.- Es uno de los principales puntos de almacenamiento de la máquina.
2.- Es el punto en el cual resultados intermedios son normalmente almacenados.
(2) El registro indexado X
Este es un registro muy importante. Hay instrucciones para la mayoría de las transformaciones que puedes realizar con el acumulador. Pero hay otras instrucciones para operaciones que solo el registro X puede realizar. Varias instrucciones en lenguaje máquina te permiten copiar el contenido de una localización de memoria en el registro X, copiar el contenido del registro X en una localización de memoria, y modificar el contenido del registro X o de cualquier otro registro directamente.
(3) El registro indexado Y
Este es un registro muy importante. Hay instrucciones para la mayoría de las transformaciones que puedes realizar con el acumulador y el registro indexado X. Pero hay otras instrucciones para operaciones que solo el registro Y puede realizar. Varias instrucciones en lenguaje máquina te permiten copiar el contenido de una localización de memoria en el registro Y, copiar el contenido del registro Y en una localización de memoria, y modificar el contenido del registro Y o de cualquier otro registro directamente.
(3) El registro de estados
Este registro consiste en ocho "flags" o señales (un flag = algo que indica si algo a ocurrido o no). Los bits de este registro son alterados dependiendo de el resultado de las operaciones aritméticas y lógicas). Los bits están descritos a continuación:

Diagrama del registro de estados del MCS650X

Registro de estados del MCS650X
Bit 0 - "C" - Señal de acarreo (carry flag): este mantiene el carry expulsado del bit más significativo en una operación aritmética. En operaciones de substracción (resta) en cambio, esta señal está desactivada (puesta a 0) si la llevada es necesaria y activada (puesta a 1) si no es necesaria. La señal de acarreo también es usada en operaciones lógicas de desplazamiento y rotación.
Bit 1 - "Z" - Señal cero (zero flag): este bit se pone a 1 cuando una operación aritmética o lógica produce un resultado cero, y se pone a 0 si el resultado no es cero. Esta señal es automáticamente activada por el microprocesador durante cualquier movimiento de datos o cálculos cuando los 8 bits del resultado de la operación son 0.
Bit 2 - "I" - Este bit es una señal interruptor desactivado (interrupt disable flag). Si está puesto a 1, el interruptor está descativado. Si está puesto a 0, el interruptor está activado. Es usada por el programador y por el microprocesador para controlar las operaciones del pin de petición de interrupción.
Bit 3 - "D" - Este bit es una señal de estado modo decimal (decimal mode flag). Cuando está puesto a 1 y una instrucción de adición (suma) o susbtración (resta) con carry es ejecutada, los valores de origen son tratados como números BCD (Binary Coded Decimal, ej. 0x00-0x99 = 0-99). El resultado generado es también un número BCD.
Bit 4 - "B" - Este bit se pone a 1 cuando una interrupción software (instrucción BRK) es ejecutada (break command). Solo puede ser activado por el microprocesador y es usado para determinar, durante un secuencia de interrupción, si la interrupción fué causada por un comando BRK o por una interrupción real. Este bit debería tener significado solo durante un análisis de una secuencia de interrupción normal.
Bit 5 - No usado (expansion bit). Se supone un 1 lógico todo el tiempo.
Bit 6 - "V" - Señal de desborde (overflow): cuando una operación aritmética produce un resultado demasiado grande para ser representado en un byte, se pone a 1.
Bit 7 - "S" - Señal signo (negative flag): este bit se pone a 1 si el resultado de una operación es negativo y 0 si es positivo. Uno de los usos del microprocesador es la de realizar operaciones aritméticas con números con signo. Para facilitar al usuario una mejor lectura del estado del bit de signo (bit 7), la señal N se pone con el mismo valor que el bit 7.
Las señales que comunmente más se usan son "C, Z, V, S".
[B] El contador de programa
Este contiene la dirección de la instrucción en lenguaje máquina actual que está siendo ejecutada. El contador de programa está continuamente cambiando. Solo puede ser parado deteniendo el microprocesador de alguna manera.
[C] El puntero de pila
Este registro contiene la localización de el primer sitio vacío en la pila. La pila es usada para el almacenamiento temporal por los programas en lenguaje máquina, y por la computadora.

Diagrama del MCS650X incluyendo el puntero de pila, S
[D] Modos de direccionamiento
Las instrucciones necesitan operandos para trabajar. Aquí se muestran varias maneras de indicar al microprocesador de donde cojer esos operandos. Los diferentes modos usados para esto se denominan modos de direccionamiento. El 6502 ofrece 11 modos, los cuales se describen a continuación:
(1) Inmediato
En este modo el valor de los operandos se dá en la propia instrucción. En lenguaje ensamblador este es indicado por "#" antes del operador. Ejemplo:
LDA #$0A (significa "carga el acumulador con el valor hexadecimal 0A").
En código máquina los diferentes modos se indican por diferentes códigos. Así que LDA podría ser traducido en diferentes códigos dependiendo del modo de direccionamiento. En este modo, es: $A9 $0A.
(2,3) Absoluto y pagina-cero absoluto
En estos modos la dirección de los operandos ese dada. Ejemplo:
LDA $31F6 (ensamblador).
$AD $31F6 (código máquina).
Si la dirección está en la página cero (ej: cualquier dirección donde el byte alto es 00, solo 1 byte es necesario para la direccion). El microprocesador automaticamente llena el byte alto con 00. Ejemplo:
LDA $FA (ensamblador, equivaldría a LDA $00FA).
$A5 $FA (código máquina).
(4) Implícito
La dirección del operando no es requerida en este modo. Ya que está implícita en la propia instrucción. Ejemplo:
TAX (ensamblador, transfiere el contenido del acumulador al registro X).
$AA (código máquina).
(5) Acumulador
En este modo la instrucción opera con datos dentro del propio acumulador, así que los operandos no son necesarios. Ejemplo:
LSR (ensamblador, desplazamiento a la derecha).
$4A (código máquina).
(6,7) Indexado y pagina-cero indexado
En estos modos la dirección dada es añadida al valor o bien del registro X o del Y para dar la dirección actual del operando. Ejemplo:
LDA $31F6, Y
$D9 $31F6
LDA $31F6, X
$DD $31F6
En la versión página cero, los registros X e Y no son intercambiables. La mayoría de las instrucciones que son usadas con página cero indexado lo hacen con el registro X solamente. Ejemplo
LDA $20, X
$B5 $20
(8) Indirecto
Este modo se aplica solo a la instrucción JMP (saltar a una nueva localización). Se indica mediante paréntesis alrededor del operando. El operando es la dirección de los bytes cuyo valor es la nueva localización. Ejemplo
JMP ($215F)
Asume lo siguiente:
byte valor $215F $76 $2160 $30
Esta instrucción toma el valor del byte $215F, $2160 y lo usa como dirección a saltar (en el ejemplo - $3076). Recuerda que las direcciones son guardadas con el byte bajo primero y se necesitan dos direcciones de memoria para almacenar un byte.
(9) Pre-indexado indirecto
En este modo una dirección página-cero es añadida al contenido del registro X para dar la dirección de los bytes que tienen la dirección del operando. El indireccionamiento es indicado por paréntesis en lenguaje ensamblador. Ejemplo:
LDA ($3E, X)
$A1 $3E
Asume lo siguiente:
byte valor X-reg $05 $0043 $15 $0044 $24 $2415 $6E
Luego las instrucciones son ejecutadas por:
(i) añadiendo $3E + $05 = $0043
(ii) cogiendo la dirección contenida en bytes $0043, $0044 = $2415
(iii) cargando el contenido de $2415 (en el ejemplo - $6E en el acumulador)
Nota: Solo el registro X es usado en este modo.
(10) Post-indexado indirecto
En este modo el contenido de la dirección de la página-cero (y el siguiente byte) dan la dirección indirecta la cual es añadida al conenido del registro Y para producir la dirección actual del operando. Denuevo, en lenguaje ensamblador, la instrucción es indicada por paréntesis. Ejemplo:
LDA ($4C), Y
Nótese que los paréntesis están solo alrededor del segundo byte de la instrucción ya que es la parte que hace la indirección.
Asume lo siguiente:
byte valor $004C $00 $004D $21 Y-reg $05 $2105 $6D
Luego las instrucciones son ejecutadas por:
(i) cogiendo la dirección en bytes $4C, $4D = $2100
(ii) añadiendo el contenido del registro Y = $2105
(iii) cargando el contenido del byte $2105 (en el ejemplo - $6D en el acumulador).
Nota: Solo el registro Y es usado en este modo.
(11) Relativo
Este modo es usado con instrucciones "Branch-on-Condition". Probablemente será el modo que usarás en la mayoría de los casos. Un valor de 1 byte es añadido al contador de programa, y el programa continúa ejecutandose desde esa dirección. El número de 1 byte es considerado como un número con signo (en el ejemplo - si el bit 7 es 1, el número dado por los bits 0-6 es negativo; si el bit 7 es 0, el número es positivo). Esto activa un desplazamiento de hasta 127 bytes en cualquier dirección. Ejemplo:
bit num. 7 6 5 4 3 2 1 0 valor con signo valor sin signo valor 1 0 1 0 0 1 1 1 -39 $A7 valor 0 0 1 0 0 1 1 1 +39 $27
BEQ $A7
$F0 $A7
Esta instrucción chequeará el estado del bit cero. Si está puesto a 1, un 39 decimal será substraido desde el contador de programa y la ejecución continuará desde esa dirección. Si el bit cero está puesto a 0, la ejecución continua desde la instrucción siguiente.
[E] La unidad aritmética
Una de las funciones esperadas por cualquier computador es la habilidad de computar o realizar operaciones aritméticas. Incluso en un simple problema de control, uno suele encontrar útil sumar dos números para determinar que un valor ha sido alcanzado, o restar dos números para calcular un nuevo valor que debe ser obtenido. El MCS650X tiene una unidad aritmética de 8-bit que interactua con el acumulador como se muestra en la siguiente imagen:

Diagrama de la unidad artimética lógica del MCS650X
Una descripción rápida sobre el acarreo: el mayor rango que puede ser representado en un número de 8-bit es 256 cuyos valores están entre 0 y 255. Si sumamos cualquiera 2 números cuyo resultado de su suma es mayor que 255, representamos el resultado con un noveno bit ademas de los 8 bits, como el exceso sobre 255. El noveno bit es llamado "carry" (acarreo).
[F] Conceptos de secuencia de programa
El microprocesador contiene un reloj interno y un contador de control de estado. Este contador, junto con la matriz decodificada, goviernan la operación del microprocesador en cada ciclo de reloj. Cuando el estado del microprocesador indica que una nueva instrucción es necesaria, el contador de programa (puntero de direcciones de programa) es usado para elegir la nueva localización de memoria y el valor que la memoria devuelve es decodificado para determinar que operación va a ser ejecutada por el MCS650X.

Diagrama del MCS650X incluyendo el contador de programa y el bus interno de direcciones
En la familia de los MCS650X, el contador de programa es activado con el valor de la dirección de una instrucción. El microprocesador después pone el valor del contador de programa en el bus de direcciones, transfiriendo los 8 bits de datos de esa dirección de memoria en el decodificador de instrucciones. Luego el contador de programa se incrementa automaticamente por uno y el microprocesador trae los datos necesarios para completar la instrucción.
El procesador MCS650X usualmente requiere más de un byte para interpretar correctamente una instrucción. El primer byte de una instrucción es llamado OP CODE y es codificado para contener las operaciones básicas como LDA (carga acumulador con memoria) y también los datos necesarios para permitir al microprocesador interpretar las direcciones de los datos que van a ser afectados por la operación. En la mayoría de los casos, estas direcciones aparecerán en memoria justo dspues que el byte de OP CODE.
[G] Definición de desplazamiento y rotación
La instrucción de desplazamiento (shift) toma un registro como el acumulador y mueve todos los bits en el acumulador 1 posición a la derecha o a la izquierda. Ejemplos de instrucciones de desplazamiento y rotación en el MCS650X:
Carry
_______________________________________ ____
| | | | | | | | | | |
Desplazamiento Derecha Antes | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | | C |
|----|----|----|----|----|----|----|----| |----|
Después | 0 | B7 | B6 | B5 | B4 | B3 | B2 | B1 |-->| B0 |
|____|____|____|____|____|____|____|____| |____|
_______________________________________ ____
| | | | | | | | | | |
Desplazamiento Izquierda Antes | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | | C |
|----|----|----|----|----|----|----|----| |----|
Después | B6 | B5 | B4 | B3 | B2 | B1 | B0 | 0 | | B7 |<--
|____|____|____|____|____|____|____|____| |____|
_______________________________________ ____
| | | | | | | | | | |
Rotación Izquierda Antes | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | | C |
|----|----|----|----|----|----|----|----| |----|
Después | B6 | B5 | B4 | B3 | B2 | B1 | B0 | C |<--| B7 |<--
|____|____|____|____|____|____|____|____| |____|