Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
cursos:ensamblador:lenguaje_1 [19-01-2024 06:27] – sromero | cursos:ensamblador:lenguaje_1 [22-01-2024 07:51] (actual) – [Instrucciones LD (instrucciones de carga)] sromero | ||
---|---|---|---|
Línea 23: | Línea 23: | ||
Además, podemos agrupar algunos de estos registros en pares de 16 bits para determinadas operaciones: | Además, podemos agrupar algunos de estos registros en pares de 16 bits para determinadas operaciones: | ||
\\ | \\ | ||
- | * **AF**: Formado por el registro A como byte más significativo (Byte alto) y por F como byte menos significativo (Byte bajo). Si A vale $ff y F vale $00, AF valdrá automáticamente | + | * **AF**: Formado por el registro A como byte más significativo (Byte alto) y por F como byte menos significativo (Byte bajo). Si '' |
* **BC**: Agrupación de los registros B y C que se puede utilizar en bucles y para acceder a puertos. También se utiliza como " | * **BC**: Agrupación de los registros B y C que se puede utilizar en bucles y para acceder a puertos. También se utiliza como " | ||
* **DE, HL**: Registros de 16 bits formados por D y E por un lado y H y L por otro. Utilizaremos generalmente estos registros para leer y escribir en memoria en una operación única, así como para las operaciones de acceso a memoria como '' | * **DE, HL**: Registros de 16 bits formados por D y E por un lado y H y L por otro. Utilizaremos generalmente estos registros para leer y escribir en memoria en una operación única, así como para las operaciones de acceso a memoria como '' | ||
Línea 31: | Línea 31: | ||
* **IX, IY**: Dos registros de 16 bits pensados para acceder a memoria de forma indexada. Gracias a estos registros podemos realizar operaciones como: '' | * **IX, IY**: Dos registros de 16 bits pensados para acceder a memoria de forma indexada. Gracias a estos registros podemos realizar operaciones como: '' | ||
* **SP**: Puntero de pila, como veremos en su momento apunta a la posición actual de la " | * **SP**: Puntero de pila, como veremos en su momento apunta a la posición actual de la " | ||
- | * **PC**: Program Counter o Contador de Programa. Como ya vimos en la anterior entrega, contiene la dirección de la instrucción actual a ejecutar. No modificaremos PC directamente moviendo valores a este registro, sino que lo haremos mediante instrucciones de salto ('' | + | * **PC**: Program Counter o Contador de Programa. Como ya vimos en la anterior entrega, contiene la dirección de la instrucción actual a ejecutar. No modificaremos PC directamente moviendo valores a este registro, sino que lo haremos mediante instrucciones de salto ('' |
\\ | \\ | ||
Por último, tenemos disponible un banco alternativo de registros, conocidos como **Shadow Registers** o //Registros Alternativos//, | Por último, tenemos disponible un banco alternativo de registros, conocidos como **Shadow Registers** o //Registros Alternativos//, | ||
- | En cualquier momento podemos intercambiar el valor de los registros A, B, C, D, E, F, H y L con el valor de los registros A', B', C', D', E', F', H' y L' mediante las instrucciones de ensamblador '' | + | En cualquier momento podemos intercambiar el valor de los registros A, B, C, D, E, F, H y L con el valor de los registros A', B', C', D', E', F', H' y L' mediante las instrucciones de ensamblador '' |
Ya conocemos los registros disponibles, | Ya conocemos los registros disponibles, | ||
Línea 47: | Línea 47: | ||
<code z80> | <code z80> | ||
- | ld c, $00 | + | ld c, $00 ; C vale 0 |
- | ld b, $01 | + | ld b, $01 ; B vale 1 |
- | ; con esto, BC = $0100 | + | |
- | ld a, b | + | ld a, b ; A ahora vale 1 |
- | ld hl, $1234 ; HL vale $1234 o 4660d | + | ld hl, $1234 |
- | ld a, (hl) ; A contiene el valor de (4660) | + | ld a, (hl) |
- | ld a, (16384) | + | ld a, (16384) |
- | ld (16385), a | + | ld (16385), a ; Escribimos en (16385) el valor de A |
- | add a, b ; Suma: A = A + B | + | add a, b |
- | inc b | + | inc b ; Incrementamos B (B = 1+1 =2) |
- | ; Ahora BC vale $0200 | + | |
- | inc bc | + | inc bc ; Incrementamos BC |
- | ; (BC = $0200+1 = $0201) | + | |
</ | </ | ||
Línea 73: | Línea 73: | ||
ld sp, bc | ld sp, bc | ||
ex de, hl | ex de, hl | ||
- | | + | |
add hl, bc | add hl, bc | ||
add de, bc | add de, bc | ||
Línea 84: | Línea 84: | ||
; sólo se puede cargar un valor inmediato NN | ; sólo se puede cargar un valor inmediato NN | ||
- | EX BC, DE ; NO: Existe ex de, hl, pero no EX BC, DE | + | ex bc, de ; NO: Existe ex de, hl, pero no EX BC, DE |
add de, bc ; NO: Sólo se puede usar HL como operando destino | add de, bc ; NO: Sólo se puede usar HL como operando destino | ||
Línea 154: | Línea 154: | ||
ld b, 100 | ld b, 100 | ||
bucle: | bucle: | ||
- | (...) ; código | + | (...) ; código |
- | dec b ; Decrementamos B (B=B-1) | + | dec b ; Decrementamos B (B=B-1) |
jr nz, bucle | jr nz, bucle | ||
+ | | ||
; Si el resultado de la operación anterior no es cero (NZ = Non Zero), | ; Si el resultado de la operación anterior no es cero (NZ = Non Zero), | ||
; saltar a la etiqueta bucle y continuar. dec b hará que el flag Z | ; saltar a la etiqueta bucle y continuar. dec b hará que el flag Z | ||
Línea 177: | Línea 178: | ||
<code z80> | <code z80> | ||
- | ld a, c ; A = C | + | ld a, c |
; Tenemos que hacer esto porque no existe | ; Tenemos que hacer esto porque no existe | ||
; una instruccion sub b, c . Sólo se puede | ; una instruccion sub b, c . Sólo se puede | ||
; restar un registro al registro A. | ; restar un registro al registro A. | ||
- | sub b ; A = A-B | + | sub b |
- | jp z, Es_Igual | + | jp z, Es_Igual |
- | jp nz, No_Es_Igual | + | jp nz, No_Es_Igual |
(...) | (...) | ||
Línea 224: | Línea 225: | ||
<code z80> | <code z80> | ||
- | LD DESTINO, ORIGEN | + | ld DESTINO, ORIGEN |
</ | </ | ||
Línea 232: | Línea 233: | ||
<code z80> | <code z80> | ||
- | ld a, 10 | + | ld a, 10 ; A = 10 |
- | ld b, 200 ; B = 200 | + | ld b, 200 |
- | ld bc, 12345 | + | ld bc, 12345 ; BC = 12345 |
</ | </ | ||
Línea 240: | Línea 241: | ||
<code z80> | <code z80> | ||
- | ld a, b ; A = B | + | ld a, b |
- | ld bc, de ; BC = DE | + | ld bc, de |
</ | </ | ||
Línea 247: | Línea 248: | ||
<code z80> | <code z80> | ||
- | ld (12345), a ; Memoria[12345] = valor en A | + | ld (12345), a |
- | ld (hl), 10 ; Memoria[valor de HL] = 10 | + | ld (hl), 10 |
</ | </ | ||
Línea 254: | Línea 255: | ||
<code z80> | <code z80> | ||
- | ld a, (12345) | + | ld a, (12345) |
- | ld b, (hl) | + | ld b, (hl) ; B = valor en Memoria[valor de HL] |
</ | </ | ||
- | | + | |
+ | |||
+ | 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 '' | ||
+ | |||
+ | <code z80> | ||
+ | ld a, (16384) | ||
+ | ld (16384), a | ||
+ | |||
+ | ld hl, 16384 => HL = 16384 | ||
+ | ld a, (hl) => LET A = PEEK HL => LET A = PEEK 16384 | ||
+ | ld (hl), a => POKE HL, a | ||
+ | </ | ||
+ | |||
+ | En el segundo ejemplo hemos utilizado '' | ||
+ | |||
+ | 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, | ||
+ | |||
+ | De nuevo, viéndolo "en instrucciones BASIC", | ||
+ | |||
+ | <code z80> | ||
+ | ld hl, 16384 => HL = 16384 | ||
+ | |||
+ | ld hl, (16384) | ||
+ | => L = PEEK 16384 | ||
+ | H = PEEK 16385 | ||
+ | </ | ||
+ | |||
+ | En '' | ||
+ | |||
+ | 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 | ||
+ | </ | ||
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 279: | Línea 316: | ||
ld r, N | ld r, N | ||
ld rr, NN | ld rr, NN | ||
- | LD ri, NN | + | ld ri, NN |
; Copia de un registro a otro | ; Copia de un registro a otro | ||
Línea 293: | Línea 330: | ||
ld a, (NN) | ld a, (NN) | ||
ld rr, (NN) | ld rr, (NN) | ||
- | LD ri, (NN) | + | ld ri, (NN) |
ld (NN), rr | ld (NN), rr | ||
ld (NN), ri | ld (NN), ri | ||
; Acceso indexado a memoria | ; Acceso indexado a memoria | ||
- | LD (ri+N), r | + | ld (ri+N), r |
ld r, (ri+N) | ld r, (ri+N) | ||
- | LD (ri+N), N | + | ld (ri+N), N |
</ | </ | ||
Línea 324: | Línea 361: | ||
; Carga de valores en registros | ; Carga de valores en registros | ||
; registro_destino = valor | ; registro_destino = valor | ||
- | ld a, 100 ; ld r, N | + | ld a, 100 |
- | ld bc, 12345 | + | ld bc, 12345 ; ld rr, NN |
; Copia de registros en registros | ; Copia de registros en registros | ||
; registro_destino = registro_origen | ; registro_destino = registro_origen | ||
- | ld b, c ; ld r, r | + | ld b, c |
- | ld a, b ; ld r, r | + | ld a, b |
- | ld bc, de ; ld rr, rr | + | ld bc, de |
; Acceso a memoria | ; Acceso a memoria | ||
; (Posicion_memoria) = VALOR o bien | ; (Posicion_memoria) = VALOR o bien | ||
; Registro = VALOR en (Posicion de memoria) | ; Registro = VALOR en (Posicion de memoria) | ||
- | ld a, (hl) | + | ld a, (hl) ; ld r, (rr) |
- | ld (bL), b ; ld (rr), r | + | ld (bc), a |
- | ld (12345), a ; ld (NN), a | + | ld (12345), a |
- | ld a, (hl) | + | ld a, (hl) ; ld r, (rr) |
- | ld (de), a | + | ld (de), a ; ld (rr), r |
- | ld (bc), 1234h | + | ld (bc), 1234h ; ld (bc), NN |
- | ld (12345), de | + | ld (12345), de ; ld (NN), rr |
- | ld ix, (12345) | + | ld ix, (12345) |
- | ld (34567), iy | + | ld (34567), iy ; ld (NN), ri |
; Acceso indexado a memoria | ; Acceso indexado a memoria | ||
; (Posicion_memoria) = VALOR o VALOR = (Posicion_memoria) | ; (Posicion_memoria) = VALOR o VALOR = (Posicion_memoria) | ||
; Donde la posicion es IX+N o IY+N: | ; Donde la posicion es IX+N o IY+N: | ||
- | ld (ix+10), a ; LD (ri+N), r | + | ld (ix+10), a |
- | ld a, (iy+100) | + | ld a, (iy+100) |
- | ld (ix-30), 100 ; LD (ri+N), N | + | ld (ix-30), 100 |
</ | </ | ||
Línea 361: | Línea 398: | ||
Flags | Flags | ||
| | ||
- | ---------------------------------- | + | |
ld r, r |- - - - - -| | ld r, r |- - - - - -| | ||
ld r, N |- - - - - -| | ld r, N |- - - - - -| | ||
Línea 367: | Línea 404: | ||
ld (rr), n |- - - - - -| | ld (rr), n |- - - - - -| | ||
ld (rr), n |- - - - - -| | ld (rr), n |- - - - - -| | ||
- | LD ri, (NN) |- - - - - -| | + | ld ri, (NN) |- - - - - -| |
ld (NN), ri |- - - - - -| | ld (NN), ri |- - - - - -| | ||
- | LD (ri+d), N |- - - - - -| | + | ld (ri+d), N |- - - - - -| |
- | LD (ri+d), r |- - - - - -| | + | ld (ri+d), r |- - - - - -| |
ld r, (ri+d) | ld r, (ri+d) | ||
ld a, i |* * 0 * 1 0| | ld a, i |* * 0 * 1 0| | ||
Línea 379: | Línea 416: | ||
Esto quiere decir, y es muy importante, que una operación como '' | Esto quiere decir, y es muy importante, que una operación como '' | ||
- | 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 " | + | \\ |
+ | ===== 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, | ||
+ | |||
+ | 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 '' | ||
+ | |||
+ | En nuestro ejemplo anterior, el '' | ||
+ | |||
+ | 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 '' | ||
\\ | \\ | ||
Línea 389: | Línea 441: | ||
<code z80> | <code z80> | ||
- | ld a, 0 ; A = 0 | + | ld a, 0 ; A = 0 |
- | inc a ; A = A+1 = 1 | + | inc a ; A = A+1 = 1 |
- | ld b, a ; B = A = 1 | + | ld b, a ; B = A = 1 |
- | inc b ; B = B+1 = 2 | + | inc b ; B = B+1 = 2 |
- | inc b ; B = B+1 = 3 | + | inc b ; B = B+1 = 3 |
ld bc, 0 | ld bc, 0 | ||
- | inc bc | + | inc bc |
- | inc b ; BC = 0101h (ya que B=B+1 y es la parte alta) | + | inc b ; BC = $0101 (ya que B=B+1 y es la parte alta) |
- | dec a ; A = A-1 = 0 | + | dec a ; A = A-1 = 0 |
</ | </ | ||
Línea 430: | Línea 482: | ||
<code z80> | <code z80> | ||
- | inc a ; A = A+1 | + | inc a |
- | dec b ; B = B-1 | + | dec b |
- | inc de | + | inc de ; DE = DE+1 |
- | dec ix | + | dec ix ; IX = IX-1 |
- | inc (hl) | + | inc (hl) ; (HL) = (HL)+1 |
- | inc (ix-5) | + | inc (ix-5) |
- | dec (iy+100) | + | dec (iy+100) |
</ | </ | ||
Línea 456: | 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 494: | Línea 546: | ||
<code z80> | <code z80> | ||
- | ADD DESTINO, ORIGEN | + | add DESTINO, ORIGEN |
</ | </ | ||
Línea 500: | Línea 552: | ||
<code z80> | <code z80> | ||
- | ADD A, s | + | add a, s |
- | ADD HL, ss | + | add hl, ss |
- | ADD ri, rr | + | add ri, rr |
</ | </ | ||
Línea 522: | Línea 574: | ||
<code z80> | <code z80> | ||
- | ; ADD A, s | + | ; add a, s |
- | add a, b ; A = A + B | + | add a, b |
- | add a, 100 ; A = A + 100 | + | add a, 100 |
- | ADD A, [HL] ; A = A + [HL] | + | add a, (hl) |
- | ADD A, [IX+10] | + | add a, (ix+10) ; A = A + (IX+10) |
- | ; ADD HL, ss | + | ; add hl, ss |
- | add hl, bc ; HL = HL + BC | + | add hl, bc |
- | add hl, sp ; HL = HL + SP | + | add hl, sp |
- | ; ADD ri, rr | + | ; addri, rr |
- | add ix, bc ; IX = IX + BC | + | add ix, bc |
- | add iy, de ; IY = IY + DE | + | add iy, de |
- | add iy, ix ; IY = IY + IX | + | add iy, ix |
- | add ix, iy ; IX = IX + IY | + | add ix, iy |
</ | </ | ||
Línea 542: | Línea 594: | ||
<code z80> | <code z80> | ||
- | add b, c ; Sólo A puede ser destino | + | add b, c |
- | add bc, de ; Sólo puede ser destino HL | + | add bc, de |
- | add ix, ix ; No podemos sumar un registro índice a él mismo | + | add ix, ix |
</ | </ | ||
La afectación de los flags ante las operaciones de sumas es la siguiente: | La afectación de los flags ante las operaciones de sumas es la siguiente: | ||
- | * Para '' | + | * Para '' |
- | * Para '' | + | * Para '' |
O, en forma de tabla de afectación: | O, en forma de tabla de afectación: | ||
Línea 559: | Línea 611: | ||
| | ||
| | ||
- | ADD A, s |* * * V 0 *| | + | add a, s |* * * V 0 *| |
- | ADD HL, ss |- - ? - 0 *| | + | add hl, ss |- - ? - 0 *| |
- | ADD ri, rr |- - ? - 0 *| | + | add ri, rr |- - ? - 0 *| |
</ | </ | ||
Línea 600: | Línea 652: | ||
==== Resta: SUB (Substract) ==== | ==== Resta: SUB (Substract) ==== | ||
- | En el caso de las restas, sólo es posible realizar (de nuevo gracias a la no ortogonalidad del J.I. del Z80) la operación " | + | En el caso de las restas, sólo es posible realizar (de nuevo gracias a la no ortogonalidad del J.I. del Z80) la operación " |
<code z80> | <code z80> | ||
- | SUB ORIGEN | + | sub ORIGEN |
</ | </ | ||
Línea 609: | Línea 661: | ||
<code z80> | <code z80> | ||
- | 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) |
</ | </ | ||
Línea 620: | 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) |
</ | </ | ||
Línea 642: | Línea 694: | ||
< | < | ||
- | "ADC A, s" | + | "adc a, s" |
- | "ADC HL, ss" | + | "adc hl, ss" |
</ | </ | ||
Línea 654: | Línea 706: | ||
Instrucción | Instrucción | ||
| | ||
- | ADC A,s |* * * V 0 *| | + | adc a,s |* * * V 0 *| |
- | ADC HL,ss |* * ? V 0 *| | + | adc hl,ss |* * ? V 0 *| |
</ | </ | ||
Línea 796: | 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. |
< | < | ||
- | LD B', $10 | + | ld b', $10 |
inc a' | inc a' | ||
- | LD HL', $1234 | + | ld hl', $1234 |
- | LD A', ($1234) | + | ld a', ($1234) |
</ | </ | ||
Línea 833: | Línea 885: | ||
|< 60% >| | |< 60% >| | ||
^ Registro ^ Valor ^ Registro ^ Valor ^ | ^ Registro ^ Valor ^ Registro ^ Valor ^ | ||
- | | A | 01h | A' | 00h | | + | | A | $01 | A' | $00 | |
- | | F | 10h | F' | 00h | | + | | F | $10 | F' | $00 | |
a: | a: | ||
Línea 840: | Línea 892: | ||
|< 60% >| | |< 60% >| | ||
^ Registro ^ Valor ^ Registro ^ Valor ^ | ^ Registro ^ Valor ^ Registro ^ Valor ^ | ||
- | | A | 00h | A' | 01h | | + | | A | $00 | A' | $01 | |
- | | F | 00h | F' | 10h | | + | | F | $00 | F' | $10 | |
Realizando de nuevo un '' | Realizando de nuevo un '' | ||
Línea 868: | Línea 920: | ||
ld ($1236), a | ld ($1236), a | ||
- | ; Recuperamos | + | ; Recuperamos los registros: |
ex af, af' | ex af, af' | ||
exx | exx | ||
Línea 894: | Línea 946: | ||
</ | </ | ||
- | Además de '' | + | Además de '' |
|< 50% >| | |< 50% >| | ||
Línea 901: | Línea 953: | ||
| ex (sp), hl | Intercambiar el valor de HL con el valor de 16 bits\\ de la posición de memoria apuntada por el registro SP\\ (por ejemplo, para intercambiar el valor de HL con el\\ del último registro que hayamos introducido en la pila). | | | ex (sp), hl | Intercambiar el valor de HL con el valor de 16 bits\\ de la posición de memoria apuntada por el registro SP\\ (por ejemplo, para intercambiar el valor de HL con el\\ del último registro que hayamos introducido en la pila). | | ||
| ex (sp), ix | Igual que el anterior, pero con IX. | | | ex (sp), ix | Igual que el anterior, pero con IX. | | ||
- | | EX (SP), IY | Igual que el anterior, pero con IY. | | + | | ex (sp), iy | Igual que el anterior, pero con IY. | |
La primera de estas instrucciones nos resultará muy útil en nuestros programas en ensamblador, | La primera de estas instrucciones nos resultará muy útil en nuestros programas en ensamblador, | ||
- | Como ya hemos comentado cuando hablamos del carácter Low-Endian de nuestra CPU, al escribir en memoria (también en la pila) primero se escribe el Byte Bajo y luego el Byte Alto. Posteriormente lo leeremos de la misma forma, de tal modo que si los bytes apuntados en la pila (en memoria) son "$ff $00", al hacer el EX (SP), hl, el registro HL valdrá | + | Como ya hemos comentado cuando hablamos del carácter Low-Endian de nuestra CPU, al escribir en memoria (también en la pila) primero se escribe el Byte Bajo y luego el Byte Alto. Posteriormente lo leeremos de la misma forma, de tal modo que si los bytes apuntados en la pila (en memoria) son **$ff $00**, al hacer el '' |
Nótese que aprovechando la pila (como veremos en su momento) también podemos intercambiar los valores de los registros mediante: | Nótese que aprovechando la pila (como veremos en su momento) también podemos intercambiar los valores de los registros mediante: | ||
Línea 952: | Línea 1004: | ||
push bc ; Necesitamos salvaguardar BC | push bc ; Necesitamos salvaguardar BC | ||
ld b, 9 ; (porque vamos a usarlo para algo) | ld b, 9 ; (porque vamos a usarlo para algo) | ||
+ | |||
... hacer algo con BC ... | ... hacer algo con BC ... | ||
+ | | ||
pop bc ; recuperar el valor de BC | pop bc ; recuperar el valor de BC | ||
</ | </ | ||
Línea 962: | Línea 1016: | ||
ld (1000), bc ; Necesitamos salvaguardar BC | ld (1000), bc ; Necesitamos salvaguardar BC | ||
ld b,9 ; (porque vamos a usarlo para algo) | ld b,9 ; (porque vamos a usarlo para algo) | ||
+ | | ||
..... | ..... | ||
+ | | ||
ld (1002), bc ; guardamos el resultado | ld (1002), bc ; guardamos el resultado | ||
ld bc, (1000) | ld bc, (1000) | ||
Línea 973: | Línea 1029: | ||
<code z80> | <code z80> | ||
- | | + | |
; opcode "ld bc, NN NN" en memoria | ; opcode "ld bc, NN NN" en memoria | ||
Línea 986: | Línea 1042: | ||
</ | </ | ||
- | El ejemplo anterior es muy interesante. Cuando hacemos el '' | + | El ejemplo anterior es muy interesante. Cuando hacemos el '' |
- | En este caso '' | + | En este caso '' |
- | Con esto, estamos preservando el valor del registro a cambio de una escritura en memoria ('' | + | Con esto, estamos preservando el valor del registro a cambio de una escritura en memoria ('' |
\\ | \\ |