cursos:ensamblador:lenguaje_1

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cursos:ensamblador:lenguaje_1 [19-01-2024 06:39] sromerocursos:ensamblador:lenguaje_1 [22-01-2024 07:51] (actual) – [Instrucciones LD (instrucciones de carga)] sromero
Línea 225: Línea 225:
  
 <code z80> <code z80>
-LD DESTINO, ORIGEN+ld DESTINO, ORIGEN
 </code> </code>
  
Línea 259: Línea 259:
 </code> </code>
  
- Nótese cómo el operador () nos permite acceder a memoria. En nuestros ejemplos, ''ld a, (12345)'' no significa meter en A el valor 12345 (cosa imposible al ser un registro de 16 bits) sino almacenar en el registro A el valor que hay almacenado en la celdilla número 12345 de la memoria del Spectrum.+ Nótese cómo **el operador ''()'' nos permite acceder a la memoria del Spectrum**. En nuestros ejemplos, ''ld a, (12345)'' no significa meter en A el valor 12345 (cosa imposible al ser un registro de 16 bits) sino almacenar en el registro A el valor que hay almacenado en la celdilla número 12345 de la memoria del Spectrum. 
 + 
 + Este operador indica que se hace referencia a una posición de memoria referenciada por el valor que hay dentro de los paréntesis. Dicho valor referencia a una celdilla de memoria de 8 bits. 
 + 
 + Es decir, si escribiéramos en BASIC del Spectrum (con ''PEEK'' y ''POKE'') las instrucciones de carga de 8 bits que referencian a la memoria, veríamos lo siguiente: 
 + 
 +<code z80> 
 +ld a, (16384)     =>    LET A = PEEK 16384 
 +ld (16384), a     =>    POKE 16384, a 
 + 
 +ld hl, 16384      =>    HL = 16384 
 +ld a, (hl)        =>    LET A = PEEK HL  =>    LET A = PEEK 16384 
 +ld (hl), a        =>    POKE HL, a       =>    POKE (16384), a 
 +</code> 
 + 
 +En el segundo ejemplo hemos utilizado ''ld hl, 16384'', que significa "carga en HL el valor 16384". Como no hay paréntesis en la instrucción, no estamos haciendo una referencia a memoria sino al valor inmediato 16384, el cual metemos en HL. Después, al utilizar los paréntesis en ''ld a, (hl)'', sí que hacemos una referencia a memoria, con la dirección absoluta contenida en HL. 
 + 
 +No sólo podemos leer de o escribir en una dirección de memoria valores de 8 bits, también podemos leer y escribir valores de 16 bits. Evidentemente, como la memoria es un conjunto de "celdillas de 8 bits", para leer o escribir valores de 16 bits lo haremos en 2 celdillas: la celdilla apuntada por la dirección, y la siguiente. 
 + 
 +De nuevo, viéndolo "en instrucciones BASIC", podemos ver la diferencia entre asignar un valor de 16 bits inmediato, o referenciar a una posición de memoria para leer 16 bits: 
 + 
 +<code z80> 
 +ld hl, 16384      =>    HL = 16384 
 + 
 +ld hl, (16384)    =>    HL = (PEEK 16384) + 256*(PEEK 16385) 
 +                           => L = PEEK 16384 
 +                              H = PEEK 16385 
 +</code> 
 + 
 +En ''ld hl, (16384)'', metemos en HL el dato de 16 bits en 16384 y 16385, un valor de 8 bits para cada uno de los 2 registrow de 8 bits de HL (concretamente, H será el valor contenido en 16385 y L el valor en 16384, posteriormente veremos por qué se leen en orden inverso). 
 + 
 +De la misma forma, si hablamos de escribir en memoria un valor de 16 bits: 
 + 
 +<code z80> 
 +ld (16384), hl    =>    POKE 16384, L 
 +                        POKE 16385, H 
 +</code>
  
 En un microprocesador con un juego de instrucciones ortogonal, se podría usar cualquier origen y cualquier destino sin distinción. En el caso del Z80 no es así. El listado completo de operaciones válidas con LD es el siguiente: En un microprocesador con un juego de instrucciones ortogonal, se podría usar cualquier origen y cualquier destino sin distinción. En el caso del Z80 no es así. El listado completo de operaciones válidas con LD es el siguiente:
Línea 338: Línea 374:
 ;  Registro = VALOR en (Posicion de memoria) ;  Registro = VALOR en (Posicion de memoria)
 ld a, (hl)              ; ld r, (rr) ld a, (hl)              ; ld r, (rr)
-ld (bL),              ; ld (rr), r+ld (bc),              ; ld (rr), r
 ld (12345), a           ; ld (NN), a ld (12345), a           ; ld (NN), a
 ld a, (hl)              ; ld r, (rr) ld a, (hl)              ; ld r, (rr)
Línea 362: Línea 398:
                          Flags                          Flags
    Instrucción       |S Z H P N C|    Instrucción       |S Z H P N C|
- ----------------------------------+ ---------------------------------
    ld r, r           |- - - - - -|    ld r, r           |- - - - - -|
    ld r, N           |- - - - - -|    ld r, N           |- - - - - -|
Línea 380: Línea 416:
 Esto quiere decir, y es muy importante, que una operación como ''ld a, 0'', por ejemplo, no activará el flag de Zero del registro F. Esto quiere decir, y es muy importante, que una operación como ''ld a, 0'', por ejemplo, no activará el flag de Zero del registro F.
  
-Al respecto de escritura y lectura de valores de 16 bits utilizando instrucciones que trabajan con 8 bits, queremos recordar en este punto que el Z80 es una CPU LITTLE-ENDIAN por lo que los valores de 16 bits aparecerán en memoria "invertidos", es decir, primero el byte menos significativo y en la celdilla siguiente el byte más significativo.+\\  
 +===== Tamaños y ciclos ===== 
 + 
 +Hay otros dos datos que, como la afectación de flags, son muy importantes sobre las diferentes instrucciones que iremos viendo. 
 + 
 +Uno es el tamaño en bytes de cada instrucción, que viene determinado por los opcodes que ocupa. Así, un ''ld a, b'' ocupa un sólo byte (**$78**), ''ld a, $ff'' ocupa 2 bytes (al opcode **$3E** le sigue el operando **$ff**) y ''ld bc, $1234'' ocupa 3 bytes (al opcode **01** le siguen los 2 bytes de $1234). 
 + 
 +Del mismo modo, tenemos el tiempo que tarda en ejecutarse cada una de ellas, lo que se conoce como el número de **ciclos** (o **t-estados** / **t-states**). Este es el tiempo que tarda el procesador Z80 en leer de memoria, decodificar y ejecutar cada instrucción. Cada lectura de byte de memoria requiere en general de 3 t-estados extra, así que no lo es lo mismo una instrucción sencilla de un sólo byte de opcode como ''ld a, b'' que una con 3 bytes como ''ld bc, $1234''
 + 
 +En nuestro ejemplo anterior, el ''ld a, b'' de un sólo byte se ejecuta en 4 ciclos de reloj (3 para leer de memoria el opcode y 1 para ejecutarlo), el ''ld a, $ff'' son 7 ciclos de reloj o t-estados (los 3 de leer de memoria el primer byte, 3 de leer el segundo byte, y uno más para la ejecución) y ''ld bc, $1234'' que ocupa 3 bytes requiere 3+3+3+1 = 10 ciclos de reloj. 
 + 
 +En estos capítulos iniciales del curso no nos deben de preocupar tanto lo que ocupan las instrucciones y cuánto tardan en ejecutarse como el saber qué instrucciones existen, la manera en que operan y cómo se utilizan. No obstante, sí que necesitaremos más adelante tener un buen conocimiento de tamaño y tiempo de ejecución de cada instrucción para desarrollar programas. 
 + 
 +En el último capítulo dedicado a las diferentes instrucciones veremos una tabla donde se detallan todos los tamaños y tiempos de las diferentes instrucciones. 
 + 
 +Un apunte sobre ''ld bc, $1234'': Al respecto de escritura y lectura de valores de 16 bits utilizando instrucciones que trabajan con 8 bits, queremos recordar en este punto que el Z80 es una CPU LITTLE-ENDIAN por lo que los valores de 16 bits aparecerán en memoria "invertidos", es decir, primero el byte menos significativo y en la celdilla siguiente el byte más significativo. Es decir, que el opcode correspondiente a ''ld bc, $1234'' en memoria no es "**$01 $12 $34**" sino "**$01 $34 $12**";
  
 \\  \\ 
Línea 457: Línea 508:
  ----------------------------------  ----------------------------------
    inc r             |* * * V 0 -|    inc r             |* * * V 0 -|
-   INC (HL)          |* * * V 0 -| +   inc (hl)          |* * * V 0 -| 
-   INC [ri+N       |* * * V 0 -|+   inc (ri+N       |* * * V 0 -|
    inc rr            |- - - - - -|    inc rr            |- - - - - -|
    dec r             |* * * V 1 -|    dec r             |* * * V 1 -|
Línea 612: Línea 663:
 sub r                ; A = A - r sub r                ; A = A - r
 sub N                ; A = A - N sub N                ; A = A - N
-sub (HL)             ; A = A - (HL)+sub (hl)             ; A = A - (HL)
 sub (rr+d)           ; A = A - (rr+d) sub (rr+d)           ; A = A - (rr+d)
 </code> </code>
Línea 621: Línea 672:
 sub b           ; A = A - B sub b           ; A = A - B
 sub 100         ; A = A - 100 sub 100         ; A = A - 100
-sub (HL)        ; A = A - (HL)+sub (hl)        ; A = A - (HL)
 sub (ix+10)     ; A = A - (IX+10) sub (ix+10)     ; A = A - (IX+10)
 </code> </code>
Línea 797: Línea 848:
 Como ya se ha explicado, disponemos de un banco de registros alternativos (los Shadow Registers), y podemos conmutar los valores entre los registros estándar y los alternativos mediante unas determinadas instrucciones del Z80. Como ya se ha explicado, disponemos de un banco de registros alternativos (los Shadow Registers), y podemos conmutar los valores entre los registros estándar y los alternativos mediante unas determinadas instrucciones del Z80.
  
-El Z80 nos proporciona una serie de registros de propósito general (así como un registro de flags), de nombres A, B, C, D, E, F, H y L. El micro dispone también de unos registros extra (set alternativo conocido como Shadow Registers) de nombre A', B', C', D', E', F', H' y L', que aprovecharemos en cualquier momento de nuestro programa. No obstante, no podremos hacer uso directo de estos registros en instrucciones en ensamblador. **No es posible**, por ejemplo, ninguna de las siguientes instrucciones:+El Z80 nos proporciona una serie de registros de propósito general (así como un registro de flags), de nombres A, B, C, D, E, F, H y L. El micro dispone también de unos registros extra (set alternativo conocido como Shadow Registers) de nombre A', B', C', D', E', F', H' y L', que aprovecharemos en cualquier momento de nuestro programa. No obstante, no podremos hacer uso directo de estos registros en instrucciones en ensamblador. **No es posible**, por ejemplo, usar ninguna de las siguientes instrucciones (porque no existen):
  
 <code> <code>
  • cursos/ensamblador/lenguaje_1.1705646344.txt.gz
  • Última modificación: 19-01-2024 06:39
  • por sromero