En capitulos anteriores hemos visto como ensamblar nuestros programas en código máquina, bien a mano, con la ayuda de un cargador Basic, o bien con la ayuda de un monitor de CM, como el incluido en el emulador WinVice. Con ello habéis conseguido tener una idea bastante clara de cómo se introducen programas en lenguaje máquina, y a su vez los rudimentos más básicos en los que se basa cualquier compilador de programas en lenguaje ensamblador.
Vimos de paso, unas pocas instrucciones de código máquina y alguna que otra directiva de lenguaje ensamblador (como ORG), pero para poder empezar a trabajar en serio con Kickass (el ensamblador en que se basa el curso) tenemos que conocer a fondo el lenguaje máquina del procesador. De esto precisamente tratará éste y los próximos capitulos.
Aprendamos pues, de una vez, el...
Lenguaje Máquina del 6502
Antes de continuar, una pequeña aclaración: Ya que el 6510 (el chip de la CPU del c64) es una versión levemente modificada del 6502, cuando hablemos del lenguaje máquina en general, veréis que me refiero a la CPU con el nombre del chip "padre" de la familia (la 65xx). El 6510, precisando un poco más, tan sólo es un 6502 con dos patillas extra conectadas a las direcciones RAM 0 y 1, y sirven para configurar la memoria. Sin embargo, todo lo demás es exactamente igual y 100% compatible.
De esto podéis deducir correctamente que programar en lenguaje máquina del 6502, nos servirá para programar Apples, Ataris, BBC Micros, los de la familia Commodore: los PET, los CBM, los TED, el VIC-20, y en definitiva, cualquier ordenador de la familia 65xx (¡incluso la consola NES!). Una vez sabemos el lenguaje máquina de un sistema, tan sólo tendremos que comprender la arquitectura particular de cada uno de ellos, para manejar correctamente sus dispositivos de E/S.
Las instrucciones que usa el 6502 son relativamente muy pocas, en comparación con otros procesadores de su generación, pero como podéis imaginar son más que suficientes, y usadas con ingenio, es posible realizar tareas de lo más complejas, como se puede comprobar sólo echando un vistazo a los numerosos programas hechos para este microprocesador.
Un procesador de 8 bits, está limitado a poder codificar 256 instrucciones diferentes, debido al ancho de su bus de datos. Aunque también se pueden codificar más instrucciones, creando opcodes de 16 bits, simplemente creando una lógica de procesamiento de varios bytes consecutivos, como hace el Z-80, el popular microchip de Zilog. Sin embargo, éste no fue el camino elegido por los ingenieros de los demás microprocesadores de esa generación, incluido el 6502 de MOS.
En el 6502, sólo tenemos códigos de operación de 8 bits, y no se usan las 256 combinaciones posibles para codificar instrucciones, tan sólo se han codificado 151, aunque también hay algunas instrucciones extra, escondidas, no soportadas oficialmente por las especificaciones del 6502, pero que ahi están y algunas pueden resultar útiles. Se verá en capitulos más avanzados.
Digo 151 instrucciones y en realidad no son tantas, pues muchas de esas instrucciones hacen lo mismo, pero tomando los datos a usar mediante almenos uno de 13 modos de direccionamiento distintos. ¿Modos de direccionamiento? Calma, ya lo veremos detenidamente, cuando toque.
De esos códigos de operación, 56 representan comandos únicos especializados en hacer una función determinada. De cara a su estudio, podemos dividirlos en varios grupos dependiendo de las funciones que realizan.
Hoy veremos el grupo de instrucciones destinados a cargar o almacenar datos desde o hacia la memoria.
Instrucciones de Carga / Almacenamiento de Datos
Estas instrucciones se encargarán como decia, de cargar o recuperar un dato en la memoria o hacia esta. Y siempre trabajaremos los datos usando la propia memoria interna de la CPU: Los registros.
Para cargar un dato siempre usaremos uno de los 3 registros (A, X, o Y) y al cargarlos (con un byte), algunas de las banderas del sistema serán modificadas reflejando la naturaleza del dato.
Las instrucciones de carga son:
LDA
LDX
LDY
LD es una abreviatura de LOAD (Carga), y como véis cada mnemónico se explica perfectamente.
En este grupo de instrucciones, se verán afectadas las banderas "Negative" y "Zero" (N y Z).
N será = 1, si el byte cargado es negativo, y cero si es positivo.
Z será = 1, si el byte cargado fue un cero, en caso contrario Z será igual a 0.
Para hacer referencia al byte que queremos cargar en el registro, debemos usar uno de los modos de direccionamiento válidos para cada instrucción (no todos están implementados para cada instrucción).
Por ejemplo si queremos introducir un número directamente en el registro, usaremos el Modo de Direccionamiento INMEDIATO, y esto, en ensamblador, lo expresaremos con el simbolo # precediendo al dato a cargar.
Ejemplo: Cargar el Acumulador con el valor $12
LDA #$12
Que en código máquina puro quedaria en memoria como:
A9 12
si queremos cargar un número, pero necesitamos que éste sea cogido de una determinada dirección, usaremos el Direccionamiento ABSOLUTO, o Direccionamiento de Página Cero, si la dirección de memoria es menor que 256, como precisamente asi sucede en este caso.
Ejemplo: Cargar el Registro A con el valor de la dirección de memoria $0012
LDA $0012
Que en código máquina puro quedaria en memoria como:
A5 12
si hubieramos empleado el direccionamiento Página Cero, o bien:
AD 12 00
en caso del direccionamiento absoluto. Fijaos que al usar éste último gastamos un byte adicional en memoria. Nótese tambien que internamente, en memoria, se almacena la dirección de forma invertida.
Cada modo de direccionamiento tiene un código de operación en lenguaje máquina distinto aún siendo la misma instrucción.
Aqui tenéis una tabla/resumen de lo visto hasta ahora:
Instrucciones de Carga del 6502:
LDA |
Carga acumulador con memoria |
|
(LoaD Accumulator with memory) |
Operación: M => A |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Inmediato | lda # Oper | $a9 | 2 | 2 |
Página Cero | lda Oper | $a5 | 2 | 3 |
Página Cero, x | lda Oper, x | $b5 | 2 | 4 |
Absoluto | lda Oper | $ad | 3 | 4 |
Absoluto, x | lda Oper, x | $bd | 3 | 4* |
Absoluto, y | lda Oper, y | $b9 | 3 | 4* |
(Indirecto, x) | lda (Oper, x) | $a1 | 2 | 6 |
(Indirecto), y | lda (Oper),y | $b1 | 2 | 5* |
LDX |
Carga registro índice x con memoria |
|
(LoaD index X with memory) |
Operación: M => X |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Inmediato | ldx # Oper | $a2 | 2 | 2 |
Página Cero | ldx Oper | $a6 | 2 | 3 |
Página Cero, y | ldx Oper, y | $b6 | 2 | 4 |
Absoluto | ldx Oper | $ae | 3 | 4 |
Absoluto, y | ldx Oper, y | $be | 3 | 4* |
LDY |
Carga registro índice y con memoria |
|
(LoaD index Y with memory) |
Operación: M => Y |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Inmediato | ldy # Oper | $a0 | 2 | 2 |
Página Cero | ldy Oper | $a4 | 2 | 3 |
Página Cero, x | ldy Oper, x | $b4 | 2 | 4 |
Absoluto | ldy Oper | $ac | 3 | 4 |
Absoluto, x | ldy Oper, x | $bc | 3 | 4* |
Las instrucciones de almacenamiento son:
STA
STX
STY
ST viene de STORE (Almacenar). Se usan de forma análoga a las instrucciones de carga, sólo que aqui un dato de un registro es almacenado en la memoria, en lugar de ser cargado. Otra diferencia es que ninguna bandera se ve afectada por estas operaciones, al contrario que sucede con las de carga.
Instrucciones de Almacenamiento del 6502:
STA |
Almacena acumulador en memoria |
|
(STore Accumulator in memory) |
Operación: A => M |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Página Cero | sta Oper | $85 | 2 | 3 |
Página Cero, x | sta Oper, x | $95 | 2 | 4 |
Absoluto | sta Oper | $8d | 3 | 4 |
Absoluto, x | sta Oper, x | $9d | 3 | 5 |
Absoluto, y | sta Oper, y | $99 | 3 | 5 |
(Indirecto, x) | sta (Oper, x) | $81 | 2 | 6 |
(Indirecto), y | sta (Oper),y | $91 | 2 | 6 |
STX |
Almacena registro índice x en memoria |
|
(STore index X in memory) |
Operación: X => M |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Página Cero | stx Oper | $86 | 2 | 3 |
Página Cero, y | stx Oper, y | $96 | 2 | 4 |
Absoluto | stx Oper | $8e | 3 | 4 |
STY |
Almacena registro índice y en memoria |
|
(STore index Y in memory) |
Operación: Y => M |
|
|||||||||||||
Modo de direccionamiento | Sintaxis | Cód. Oper. | Nº. Bytes | Nº. Ciclos |
---|---|---|---|---|
Página Cero | sty Oper | $84 | 2 | 3 |
Página Cero, x | sty Oper, x | $94 | 2 | 4 |
Absoluto | sty Oper | $8c | 3 | 4 |
Como podéis comprobar en las 3 últimas fichas, no hay ninguna "X" que indique que la operación haya afectado las banderas (ó "flags") en la palabra de estado del procesador (registro P). ¡Recordad!, las instrucciones de almacenamiento no afectan para nada las banderas.
También es apreciable que en éste grupo de instrucciones, no se puede emplear el direccionamiento inmediato. Lo cual es totalmente lógico:
Recordad siempre que, para cargar un dato en un registro debemos cargarlo de algún lugar de la memoria, y éste podria ser perfectamente justo la siguiente dirección a la que apunta el registro PC (en esto consiste un direccionamiento inmediato), sin embargo, para almacenar un dato en la memoria, tenemos que ponerlo del contenido de un registro.
Un último punto a observar es que, si os fijáis en los dos grupos de instrucciones hasta aqui presentados, existen un mayor número de modos de direccionamiento para las instrucciones que trabajen con el acumulador. Esto es debido a que, como ya dije en los capitulos introductorios, éste registro es el más usado y el que soporta el peso de la mayor parte de operaciones, además de que varios modos de direccionamiento indexan una dirección de memoria, a través de X ó Y. A nivel de diseño, el rol que se le ha dado a los otros dos registros, los índice X e Y, es el de recorrer tablas, de ahi su nomenclatura también.
9 comentarios:
Gracias por este nuevo capítulo!
No hay de qué!
Enorme. Que trabajazo y como te lo curras.
Me hace mucha ilusión, por eso hago todo lo que puedo.
Mi apoyo haciendo un PDF con todos los cursos sigue en pie!
Hola buenas, por casualidad no conoceréis un modulador del 6502 para practicar el lenguaje ensamblador?,sería de mucha ayuda,gracias. :)
De hecho sí que he visto uno online... a ver...
¿Algo asi? http://www.6502asm.com/
Si es eso, busca "6502 online emulator" en Google
Why casino no deposit bonus is a must for all - Drmcd
It is 파주 출장샵 very simple because it is a no 나주 출장안마 deposit bonus that requires 청주 출장샵 no deposit 구미 출장샵 bonus. 의정부 출장샵 You simply register for an account and play
Publicar un comentario