cursos:ensamblador:lenguaje_2

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_2 [17-01-2024 08:31] – [Resumen de instrucciones de rotación y desplazamiento] sromerocursos:ensamblador:lenguaje_2 [26-03-2024 08:13] (actual) – [Desplazamiento de bits] sromero
Línea 10: Línea 10:
 Para poder continuar con éste y posteriores capítulos del curso será imprescindible haber comprendido y asimilado todos los conocimientos de las entregas anteriores, de modo que si no es así, recomendamos al lector que relea las entregas 1, 2 y 3, y que se asegure de comprender todos los conceptos explicados. Para poder continuar con éste y posteriores capítulos del curso será imprescindible haber comprendido y asimilado todos los conocimientos de las entregas anteriores, de modo que si no es así, recomendamos al lector que relea las entregas 1, 2 y 3, y que se asegure de comprender todos los conceptos explicados.
  
-En esta entrega trataremos las operaciones con bits (''NEG'', ''CPL'', ''BIT'', ''SET'' y ''RES''), las operaciones lógicas (''AND'', ''OR'' y ''XOR'') y las operaciones de desplazamiento de bits (''RR'', ''RL'', ''RLC'', ''RRC'', ''SLA'', ''SRA'' ''SRL'').+En esta entrega trataremos las operaciones con bits (''NEG'', ''CPL'', ''BIT'', ''SET'' y ''RES''), las operaciones lógicas (''AND'', ''OR'' y ''XOR'') y las operaciones de desplazamiento de bits (''RR'', ''RL'', ''RLC'', ''RRC'', ''SLA'', ''SRA''''SRL'' y ''SLI'').
  
 No obstante, antes de pasar a hablar de las operaciones con bits finalizaremos con la descripción de las instrucciones de carga (en este caso las repetitivas), y veremos 4 instrucciones muy sencillas: ''SCF'', ''CCF'', ''NOP'' y ''DAA''. No obstante, antes de pasar a hablar de las operaciones con bits finalizaremos con la descripción de las instrucciones de carga (en este caso las repetitivas), y veremos 4 instrucciones muy sencillas: ''SCF'', ''CCF'', ''NOP'' y ''DAA''.
Línea 39: Línea 39:
  
 <code> <code>
-LDI:    Copiar [HLen [DE]+ldi:    Copiar (HLen [DE]
         DE=DE+1         DE=DE+1
         HL=HL+1         HL=HL+1
         BC=BC-1         BC=BC-1
  
-LDD:    Copiar [HLen [DE]+ldd:    Copiar (HLen [DE]
         DE=DE-1         DE=DE-1
         HL=HL-1         HL=HL-1
Línea 53: Línea 53:
  
 <code z80> <code z80>
-LD HL, 16384 +ld hl, 16384 
-LD DE, 40000 +ld de, 40000 
-LDI+ldi
 </code> </code>
  
Línea 63: Línea 63:
  
 <code> <code>
-LDIR = Repetir LDI hasta que BC valga 0+ldir = Repetir ldi hasta que BC valga 0
      = Repetir:      = Repetir:
-          Copiar [HLen [DE]+          Copiar (HLen [DE]
           DE=DE+1           DE=DE+1
           HL=HL+1           HL=HL+1
Línea 71: Línea 71:
        Hasta que BC = 0        Hasta que BC = 0
  
-LDDR = Repetir LDD hasta que BC valga 0+lddr = Repetir ldd hasta que BC valga 0
      = Repetir:      = Repetir:
-          Copiar [HLen [DE]+          Copiar (HLen [DE]
           DE=DE-1           DE=DE-1
           HL=HL-1           HL=HL-1
Línea 83: Línea 83:
  
 <code z80> <code z80>
-LD HL, 16384 +ld hl, 16384 
-LD DE, 50000 +ld de, 50000 
-LD BC, 6912 +ld bc, 6912 
-LDIR+ldir
 </code> </code>
  
Línea 94: Línea 94:
  
 <code z80> <code z80>
- ; Ejemplo de LDIR donde copiamos 6144 bytes de la ROM+ ; Ejemplo de ldir donde copiamos 6144 bytes de la ROM
  ; a la videomemoria. Digamos que "veremos la ROM" :)  ; a la videomemoria. Digamos que "veremos la ROM" :)
     ORG 40000     ORG 40000
  
-    LD HL, 0         ; Origen: la ROM +    ld hl, 0         ; Origen: la ROM 
-    LD DE, 16384     ; Destino: la VideoRAM +    ld de, 16384     ; Destino: la VideoRAM 
-    LD BC, 6144      ; toda la pantalla +    ld bc, 6144      ; toda la pantalla 
-    LDIR             ; copiar+    ldir             ; copiar
  
-    RET+    ret
 </code> </code>
  
Línea 116: Línea 116:
 <code basic> <code basic>
 10 REM Copiamos la ROM en la VideoRAM 10 REM Copiamos la ROM en la VideoRAM
-20 FOR I=0 TO 6144 : POKE (16384+I), (PEEK I) : NEXT I+20 For i=0 TO 6144 : POKE (16384+I), (PEEK I) : NEXT I
 30 PAUSE 0 30 PAUSE 0
 RUN RUN
 </code> </code>
  
-Concluímos pues que en todas estas instrucciones de copia de memoria o transferencia, HL es el origen, DE el destino y BC el número de bytes a transferir. Con ''LDI'' y ''LDD'' sólo copiaremos 1 byte (independientemente del valor de BC, aunque lo decrementará), y con LDIR LDDR copiaremos tantos bytes como valga BC, decrementando BC hasta que su valor llega a cero. Los flags quedarán afectados, especialmente con ''LDI'' y ''LDD'' para indicarnos mediante el registro P/V si BC ha llegado a cero.+Concluímos pues que en todas estas instrucciones de copia de memoria o transferencia, HL es el origen, DE el destino y BC el número de bytes a transferir. Con ''LDI'' y ''LDD'' sólo copiaremos 1 byte (independientemente del valor de BC, aunque lo decrementará), y con ldir lddr copiaremos tantos bytes como valga BC, decrementando BC hasta que su valor llega a cero. Los flags quedarán afectados, especialmente con ''LDI'' y ''LDD'' para indicarnos mediante el registro P/V si BC ha llegado a cero.
  
 <code> <code>
Línea 127: Línea 127:
    Instrucción       |S Z H P N C|    Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-   LDI               |- - 0 * 0 -| +   ldi               |- - 0 * 0 -| 
-   LDD               |- - 0 * 0 -| +   ldd               |- - 0 * 0 -| 
-   LDDR              |- - 0 0 0 -| +   lddr              |- - 0 0 0 -| 
-   LDIR              |- - 0 0 0 -|+   ldir              |- - 0 0 0 -|
 </code> </code>
  
Línea 150: Línea 150:
  
 <code z80> <code z80>
-LD HL, 25000 +ld hl, 25000 
-LD DE, 25100 +ld de, 25100 
-LD BC, 1000 +ld bc, 1000 
-LDIR+ldir
 </code> </code>
  
Línea 162: Línea 162:
   * etc...   * etc...
  
-¿Qué ocurrirá cuando ''LDIR'' llegue al byte número 25100 y lo intente copiar a 25200? Sencillamente, que hemos perdido el contenido REAL del byte número 25100, porque fue machacado al principio de la ejecución del LDIR por el byte contenido en [25000]. No estamos moviendo el bloque correctamente, porque las zonas se superponen y cuando llegamos a la zona destino, estamos copiando bytes que movimos desde el origen.+¿Qué ocurrirá cuando ''LDIR'' llegue al byte número 25100 y lo intente copiar a 25200? Sencillamente, que hemos perdido el contenido REAL del byte número 25100, porque fue machacado al principio de la ejecución del ldir por el byte contenido en [25000]. No estamos moviendo el bloque correctamente, porque las zonas se superponen y cuando llegamos a la zona destino, estamos copiando bytes que movimos desde el origen.
  
 Para ello, lo correcto sería utilizar el siguiente código de "copia hacia atrás": Para ello, lo correcto sería utilizar el siguiente código de "copia hacia atrás":
  
 <code z80> <code z80>
-LD HL, 25999 +ld hl, 25999 
-LD DE, 25099 +ld de, 25099 
-LD BC, 1000 +ld bc, 1000 
-LDDR+lddr
 </code> </code>
  
Línea 198: Línea 198:
     ORG 40000     ORG 40000
  
-    LD HL, 50000     ; Origen: 50000 +    ld hl, 50000     ; Origen: 50000 
-    LD DE, 16384     ; Destino: la VideoRAM +    ld de, 16384     ; Destino: la VideoRAM 
-    LD BC, 6912      ; toda la pantalla +    ld bc, 6912      ; toda la pantalla 
-    LDIR             ; copiar +    ldir             ; copiar 
-    RET+    ret
 </code> </code>
  
Línea 217: Línea 217:
 20 CLEAR 39999 20 CLEAR 39999
 30 DATA 33, 80, 195, 017, 0, 64, 1, 0, 27, 237, 176, 201 30 DATA 33, 80, 195, 017, 0, 64, 1, 0, 27, 237, 176, 201
-40 FOR I=0 TO 11 : READ OPCODE : POKE 40000+I, OPCODE : NEXT I+40 For i=0 TO 11 : READ OPCODE : POKE 40000+I, OPCODE : NEXT I
 50 LOAD "" CODE 50000, 6912 50 LOAD "" CODE 50000, 6912
 60 RANDOMIZE USR 40000 60 RANDOMIZE USR 40000
Línea 237: Línea 237:
 Antes de comenzar con las instrucciones de manipulación de registros y datos a nivel de bits vamos a ver una serie de instrucciones difíciles de encuadrar en futuros apartados y que pueden sernos de utilidad en nuestros programas: Antes de comenzar con las instrucciones de manipulación de registros y datos a nivel de bits vamos a ver una serie de instrucciones difíciles de encuadrar en futuros apartados y que pueden sernos de utilidad en nuestros programas:
  
-    * **SCF: Set Carry Flag** : Esta instrucción (que no admite parámetros) pone a 1 el Carry Flag del registro F. Puede sernos útil en determinadas operaciones aritméticas.+    * ''scf'': **Set Carry Flag** : Esta instrucción (que no admite parámetros) pone a 1 el Carry Flag del registro F. Puede sernos útil en determinadas operaciones aritméticas.
  
-    * **CCF: Complement Carry Flag** : Esta instrucción (que tampoco admite parámetros) invierte el estado del bit de Carry Flag: si está a 1 lo pone a 0, y viceversa. Puede servirnos para poner a 0 el carry flag mediante la combinación de SCF CCF, aunque esta misma operación se puede realizar con un simple ''AND A''.+    * ''ccf'': **Complement Carry Flag** : Esta instrucción (que tampoco admite parámetros) invierte el estado del bit de Carry Flag: si está a 1 lo pone a 0, y viceversa. Puede servirnos para poner a 0 el carry flag mediante la combinación de ''scf'' ''ccf'', aunque esta misma operación se puede realizar con un simple ''and a'' u ''or a''.
  
-    * **NOP: No OPeration** :  Esta instrucción especial del microprocesador ocupa un byte en el código (opcode $00) y no efectúa ninguna operación ni afecta a ningún flag. En cambio, se toma 4 t-states (t-estados, o ciclos del procesador) para ejecutarse, debido al ciclo de fetch/decode/execute del procesador. ¿Para qué puede servir una instrucción que no realiza ninguna acción y que requiere tiempo del procesador (aunque sea muy poco) para ejecutarse? Por un lado, podemos utilizarla en bucles de retardos (varios ''NOP''s ejecutados en un bucle que se repita varias veces) para poner retardos en nuestros programas o juegos. Por otro, como ocupa un byte en memoria (en el código) y no realiza ninguna operación, podemos utilizarla para rellenar zonas de nuestro código, y así alinear código posterior en una determinada dirección que nos interese.+    * ''nop'': **No OPeration** :  Esta instrucción especial del microprocesador ocupa un byte en el código (opcode $00) y no efectúa ninguna operación ni afecta a ningún flag. En cambio, se toma 4 t-states (t-estados, o ciclos del procesador) para ejecutarse, debido al ciclo de fetch/decode/execute del procesador. ¿Para qué puede servir una instrucción que no realiza ninguna acción y que requiere tiempo del procesador (aunque sea muy poco) para ejecutarse? Por un lado, podemos utilizarla en bucles de retardos (varios ''NOP''s ejecutados en un bucle que se repita varias veces) para poner retardos en nuestros programas o juegos. Por otro, como ocupa un byte en memoria (en el código) y no realiza ninguna operación, podemos utilizarla para rellenar zonas de nuestro código, y así alinear código posterior en una determinada dirección que nos interese.
  
-    * **DAA: Decimal Adjust Accumulator** : Esta instrucción permite realizar ajustes en los resultados de operaciones con números BCD (tras operaciones aritméticas). ¿Qué son los números en formato BCD? Es una manera de representar números en los registros (o memoria) de forma que de los 8 bits de un byte se utilizan los 4 bits del 0 al 3 para representar un número del 0 al 9 (4 bits = desde 0000 hasta 1111), y los 4 bits del bit 4 al 7 para representar otro número del 0 al 9. A los 2 números BCD juntos se les llama "Byte BCD" o "números en formato BCD". Un número BCD puede estar formado por varios bytes BCD, siendo cada byte 2 cifras del mismo. Así, para representar un número de 10 cifras en BCD sólo es necesario utilizar 5 bytes. Además, podemos utilizar un byte extra que indique la posición de la "coma decimal" para así poder trabajar con números decimales en ensamblador. Si queremos realizar operaciones entre este tipo de números deberemos programarnos nosotros mismos las rutinas para realizarlas. \\ \\ A lo largo del curso no utilizaremos números en BCD y por lo tanto es muy probable que no lleguemos a utilizar DAA, pero conviene saber que el Z80 nos brinda la oportunidad de utilizar números más grandes de 16 bits, operando con números en BCD. Para realizar juegos normalmente no necesitaremos de estas instrucciones.+    * ''daa'': **Decimal Adjust Accumulator** : Esta instrucción permite realizar ajustes en los resultados de operaciones con números BCD (tras operaciones aritméticas). ¿Qué son los números en formato BCD? Es una manera de representar números en los registros (o memoria) de forma que de los 8 bits de un byte se utilizan los 4 bits del 0 al 3 para representar un número del 0 al 9 (4 bits = desde 0000 hasta 1111), y los 4 bits del bit 4 al 7 para representar otro número del 0 al 9. A los 2 números BCD juntos se les llama "Byte BCD" o "números en formato BCD". Un número BCD puede estar formado por varios bytes BCD, siendo cada byte 2 cifras del mismo. Así, para representar un número de 10 cifras en BCD sólo es necesario utilizar 5 bytes. Además, podemos utilizar un byte extra que indique la posición de la "coma decimal" para así poder trabajar con números decimales en ensamblador. Si queremos realizar operaciones entre este tipo de números deberemos programarnos nosotros mismos las rutinas para realizarlas. \\ \\ A lo largo del curso no utilizaremos números en BCD y por lo tanto es muy probable que no lleguemos a utilizar daa, pero conviene saber que el Z80 nos brinda la oportunidad de utilizar números más grandes de 16 bits, operando con números en BCD. Para realizar juegos normalmente no necesitaremos de estas instrucciones.
  
 Todas estas instrucciones afectan a los flags de la siguiente manera: Todas estas instrucciones afectan a los flags de la siguiente manera:
Línea 251: Línea 251:
    Instrucción       |S Z H P N C|    Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-   SCF               |- - 0 - 0 1| +   scf               |- - 0 - 0 1| 
-   CCF               |- - ? - 0 *| +   ccf               |- - ? - 0 *| 
-   NOP               |- - - - - -| +   nop               |- - - - - -| 
-   DAA               |* * * P - *|+   daa               |* * * P - *|
 </code> </code>
  
Línea 268: Línea 268:
  
 <code z80> <code z80>
-LD A, %10000001 +ld a, %10000001 
-CPL                 ; A = %01111110+cpl                 ; A = %01111110
 </code> </code>
  
Línea 278: Línea 278:
    Instrucción       |S Z H P N C|    Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-   CPL               |- - 1 - 1 -|+   cpl               |- - 1 - 1 -|
 </code> </code>
  
Línea 288: Línea 288:
  
 <code z80> <code z80>
-LD A, 1        ; A = +1 +ld a, 1        ; A = +1 
-NEG            ; A = -1 = %11111111+neg            ; A = -1 = %11111111
 </code> </code>
  
Línea 298: Línea 298:
    Instrucción       |S Z H P N C|    Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-   NEG               |* * * V 1 *|+   neg               |* * * V 1 *|
 </code> </code>
  
Línea 310: Línea 310:
  
 <code z80> <code z80>
-SET bit, DESTINO+set bit, DESTINO
 </code> </code>
  
-donde Bit es un número entre 0 (el bit menos significativo o bit 0) y 7 (el de más valor o más significativo), y destino puede ser cualquier registro de 8 bits (A, B, C, D, E, H y L), una dirección de memoria apuntada por HL (es decir, el destino puede ser [HL]), o una dirección de memoria indexada por [IX+N[IY+N]. Con esto, las siguientes instrucciones serían válidas:+donde Bit es un número entre 0 (el bit menos significativo o bit 0) y 7 (el de más valor o más significativo), y destino puede ser cualquier registro de 8 bits (A, B, C, D, E, H y L), una dirección de memoria apuntada por HL (es decir, el destino puede ser (HL)), o una dirección de memoria indexada por (IX+N(IY+N). Con esto, las siguientes instrucciones serían válidas:
  
 <code z80> <code z80>
-SET 5,         ; Activar el bit 5 del registro A +set 5,         ; Activar el bit 5 del registro A 
-SET 0,         ; Activar el bit 0 del registro H +set 0,         ; Activar el bit 0 del registro H 
-SET 7, [HL]      ; Activar el bit 7 del dato contenido en+set 7, (hl)      ; Activar el bit 7 del dato contenido en
                  ; la dirección de memoria apuntada por HL                  ; la dirección de memoria apuntada por HL
-SET 1, [IX+10  ; Activar el bit 1 del dato en [IX+10]+set 1, (ix+10  ; Activar el bit 1 del dato en (IX+10)
 </code> </code>
  
Línea 326: Línea 326:
  
 <code z80> <code z80>
-RES bit, DESTINO+res bit, DESTINO
  
-RES 0,         ; Desactivar el bit 0 del registro H +res 0,         ; Desactivar el bit 0 del registro H 
-RES 7, [HL]      ; Desactivar el bit 7 del dato contenido en+res 7, (hl)      ; Desactivar el bit 7 del dato contenido en
                  ; la dirección de memoria apuntada por HL                  ; la dirección de memoria apuntada por HL
-RES 1, [IX-5   ; Desactivar el bit 0 del dato en [IX-5]+res 1, (ix-5   ; Desactivar el bit 0 del dato en (IX-5)
 </code> </code>
  
Línea 340: Línea 340:
   Instrucción       |S Z H P N C|   Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-  SET b, s          |- - - - - -| +  set b, s          |- - - - - -| 
-  RES b, s          |- - - - - -|+  res b, s          |- - - - - -|
 </code> </code>
  
Línea 354: Línea 354:
  
 <code z80> <code z80>
-BIT bit, DESTINO+bit bit, DESTINO
 </code> </code>
  
Línea 362: Línea 362:
  
 <code z80> <code z80>
-LD A, 8       ; A = %00001000 +ld a, 8              ; A = %00001000 
-BIT 7, A      ; El flag Z vale 1 +bit 7, a             ; El flag Z vale 1 
-              ; porque el bit 7 es 0 +                     ; porque el bit 7 es 0 
-BIT 3, A      ; El flag Z vale 0 +bit 3, a             ; El flag Z vale 0 
-              ; porque el bit 3 no es 0 +                     ; porque el bit 3 no es 0 
-              ; (es 1).+                     ; (es 1).
 </code> </code>
  
Línea 375: Línea 375:
  
 <code z80> <code z80>
-BIT 0, A      ; Que valor tiene el bit 0? +bit 0, a             ; Que valor tiene el bit 0? 
-              ; Ahora Z = NEG del bit 0 de A. +                     ; Ahora Z = neg del bit 0 de A. 
-JP Z es_par   ; Saltar si esta Z activado +jp z, es_par         ; Saltar si esta Z activado 
-              ; (si Z=1 -> salta a es_par) +                     ; (si Z=1 -> salta a es_par) 
-              ; ya que si Z=1, es porque el bit era 0+                     ; ya que si Z=1, es porque el bit era 0
 </code> </code>
  
Línea 388: Línea 388:
   Instrucción       |S Z H P N C|   Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-  BIT b, s          |? * 1 ? 0 -|+  bit b, s          |? * 1 ? 0 -|
 </code> </code>
  
Línea 404: Línea 404:
  
 <code z80> <code z80>
-RLC +rlc 
-RLC (HL+rlc (hl
-RLC (IX+d) +rlc (ix+d) 
-RLC (IY+d)+rlc (iy+d)
  
-RRC +rrc 
-RRC (HL+rrc (hl
-RRC (IX+d) +rrc (ix+d) 
-RRC (IY+d)+rrc (iy+d)
  
-RL +rl 
-RL (HL+rl (hl
-RL (IX+d) +rl (ix+d) 
-RL (IY+d)+rl (iy+d)
  
-RR +rr 
-RR (HL+rr (hl
-RR (IX+d) +rr (ix+d) 
-RR (IY+d)+rr (iy+d)
 </code> </code>
  
Línea 449: Línea 449:
  
 <code z80> <code z80>
-LD B, %10000001   ; B = 10000001 +ld b, %10000001   ; B = 10000001 
-RLC B             ; B = 00000011+rlc b             ; B = 00000011
  
-LD B, %10000001   ; B = 10000001 +ld b, %10000001   ; B = 10000001 
-RRC B             ; B = 11000000+rrc b             ; B = 11000000
 </code> </code>
  
-No sólo podemos rotar registros: en general el destino de la rotación podrá ser un registro, el contenido de la dirección de memoria apuntada por [HL], o bien el contenido de la memoria apuntada por un registro índice más desplazamiento ([IX+No [IY+N]). Más adelante veremos la tabla de afectación de flags de esta y otras instrucciones que veremos a continuación.+No sólo podemos rotar registros: en general el destino de la rotación podrá ser un registro, el contenido de la dirección de memoria apuntada por (HL), o bien el contenido de la memoria apuntada por un registro índice más desplazamiento ((IX+No [IY+N]). Más adelante veremos la tabla de afectación de flags de esta y otras instrucciones que veremos a continuación.
  
 Además de ''RLC'' y ''RRC'' (rotación circular), tenemos disponibles 2 instrucciones más que nos permiten apoyarnos en el Carry Flag del registro F como si fuera un bit más de nuestro registro, comportándose como el noveno bit (de más valor) del registro: hablamos de las instrucciones ''RL'' y ''RC'': Además de ''RLC'' y ''RRC'' (rotación circular), tenemos disponibles 2 instrucciones más que nos permiten apoyarnos en el Carry Flag del registro F como si fuera un bit más de nuestro registro, comportándose como el noveno bit (de más valor) del registro: hablamos de las instrucciones ''RL'' y ''RC'':
Línea 482: Línea 482:
  
 <code z80> <code z80>
-SCF              ; Set Carry Flag (hace C=1) +scf                  ; Set Carry Flag (hace C=1) 
-LD B, %00000010  ; B = 00000010 +ld b, %00000010      ; B = 00000010 
-RL B             ; B = 00000101 y C=0 (del bit 7)+rl b                 ; B = 00000101 y C=0 (del bit 7)
  
-SCF              ; Set Carry Flag (hace C=1) +scf                  ; Set Carry Flag (hace C=1) 
-LD B, %01000001  ; B = 01000000 +ld b, %01000001      ; B = 01000000 
-RR B             ; B = 10100000 y C=1 (del bit 0)+rr b                 ; B = 10100000 y C=1 (del bit 0)
 </code> </code>
  
-Así pues, RLC y RRC son circulares y no utilizan el Carry Flag, mientras que ''RR'' y ''RL'' sí que lo utilizan, como un bit extra. Utilizando ''RR''/''RL'' 9 veces o bien ''RLC''/''RRC'' 8 veces sobre un mismo registro obtenemos el valor original antes de comenzar a rotar.+Así pues, ''RLC'' ''RRC'' son circulares y no utilizan el Carry Flag, mientras que ''RR'' y ''RL'' sí que lo utilizan, como un bit extra. 
 + 
 +Utilizando ''RR''/''RL'' 9 veces o bien ''RLC''/''RRC'' 8 veces sobre un mismo registro obtenemos el valor original antes de comenzar a rotar.
  
 Veamos la tabla de afectación de flags de estas nuevas instrucciones: Veamos la tabla de afectación de flags de estas nuevas instrucciones:
Línea 499: Línea 501:
   Instrucción       |S Z H P N C|         Significado   Instrucción       |S Z H P N C|         Significado
  -----------------------------------------------------------------  -----------------------------------------------------------------
-  RLC s             |* * 0 P 0 *|         Rotate Left Circular +  rlc s             |* * 0 P 0 *|         Rotate Left Circular 
-  RRC s             |* * 0 P 0 *|         Rotate Right Circular +  rrc s             |* * 0 P 0 *|         Rotate Right Circular 
-  RL s              |* * 0 P 0 *|         Rotate Left (con Carry) +  rl s              |* * 0 P 0 *|         Rotate Left (con Carry) 
-  RR s              |* * 0 P 0 *|         Rotate Right (con Carry)+  rr s              |* * 0 P 0 *|         Rotate Right (con Carry)
 </code> </code>
  
Línea 514: Línea 516:
  
 <code z80> <code z80>
-RLCA +rlca 
-RRCA +rrca 
-RLA +rla 
-RRA+rra
 </code> </code>
  
-diferencia entre estas 4 instrucciones y su versión con un espacio en medio (''RLC A'', ''RRC A'', ''RL A'' y ''RR A'') radica simplemente en que las nuevas 4 instrucciones trabajan con A y alteran los flags de una forma diferente:+diferencia entre estas 4 instrucciones y su versión con un espacio en medio (''rlc a'', ''rrc a'', ''rl a'' y ''rr a'') radica simplemente en que las nuevas 4 instrucciones trabajan con A y alteran los flags de una forma diferente:
  
 <code> <code>
Línea 526: Línea 528:
   Instrucción       |S Z H P N C|       Significado   Instrucción       |S Z H P N C|       Significado
  -----------------------------------------------------------------  -----------------------------------------------------------------
-  RLA               |- - 0 - 0 *|       Rotate Left Accumulator +  rla               |- - 0 - 0 *|       Rotate Left Accumulator 
-  RRA               |- - 0 - 0 *|       Rotate Right Accumulator +  rra               |- - 0 - 0 *|       Rotate Right Accumulator 
-  RLCA              |- - 0 - 0 *|       Rotate Left Circular Acc. +  rlca              |- - 0 - 0 *|       Rotate Left Circular Acc. 
-  RRCA              |- - 0 - 0 *|       Rotate Right Circular Acc.+  rrca              |- - 0 - 0 *|       Rotate Right Circular Acc.
 </code> </code>
  
Línea 540: Línea 542:
  
 <code z80> <code z80>
-RLD +rld 
-RRD+rrd
 </code> </code>
  
Línea 568: Línea 570:
  
 \\  \\ 
-{{ :cursos:ensamblador:rld-nibbles.png |RLD}}+{{ :cursos:ensamblador:rld-nibbles.png |rld}}
 \\  \\ 
  
Línea 574: Línea 576:
  
 \\  \\ 
-{{ :cursos:ensamblador:rrd-nibbles.png |RRD}}+{{ :cursos:ensamblador:rrd-nibbles.png |rrd}}
 \\  \\ 
  
Línea 591: Línea 593:
  
 <code> <code>
- RLD:  (HL) = ((HL)<<4) | (A & $0F+ rld:  (HL) = ((HL)<<4) | (A & $0f
-          A = ((HL)>>4) | (A & $F0+          A = ((HL)>>4) | (A & $f0
- RRD:  (HL) = ( A<<4 )  | ((HL)>>4) + rrd:  (HL) = ( A<<4 )  | ((HL)>>4) 
-          A = ((HL)<<4) | (A & $F0)+          A = ((HL)<<4) | (A & $f0)
 </code> </code>
  
-Resultado de **RLD**:+Resultado de **rld**:
  
 <code> <code>
     A     (HL)               (HL)     A     (HL)               (HL)
   ----   -----           ----- -----   ----   -----           ----- -----
-  A2-A1  M2-Ml => RLD => A2-M2 M1-A1+  A2-A1  M2-Ml => rld => A2-M2 M1-A1
  
           <--A2--><--A1-->                 <--M2--><--M1-->            <--A2--><--A1-->                 <--M2--><--M1--> 
Línea 610: Línea 612:
 </code> </code>
  
-Resultado de **RRD**:+Resultado de **rrd**:
  
 <code> <code>
     A     (HL)               (HL)     A     (HL)               (HL)
   ----   -----           ----- -----   ----   -----           ----- -----
-  A2-A1  M2-Ml => RRD => A2-M1 Al-M2+  A2-A1  M2-Ml => rrd => A2-M1 Al-M2
  
          <--A2--><--A1-->                 <--M2--><--M1-->           <--A2--><--A1-->                 <--M2--><--M1--> 
Línea 629: Línea 631:
   Instrucción       |S Z H P N C|         Significado   Instrucción       |S Z H P N C|         Significado
  -----------------------------------------------------------------  -----------------------------------------------------------------
-  RLD               |* * 0 P 0 -|         Rotate Left 4 bits +  rld               |* * 0 P 0 -|         Rotate Left 4 bits 
-  RRD               |* * 0 P 0 -|         Rotate Right 4 bits+  rrd               |* * 0 P 0 -|         Rotate Right 4 bits
 </code> </code>
  
Línea 655: Línea 657:
  
 <code z80> <code z80>
-SLA +sla 
-SLA (HL+sla (hl
-SLA (IX+d) +sla (ix+d) 
-SLA (IY+d)+sla (iy+d)
  
-SRA +sra 
-SRA (HL+sra (hl
-SRA (IX+d) +sra (ix+d) 
-SRA (IY+d)+sra (iy+d)
 </code> </code>
  
Línea 755: Línea 757:
  
 <code z80> <code z80>
-SRL +srl 
-SRL (HL+srl (hl
-SRL (IX+d) +srl (ix+d) 
-SRL (IY+d)+srl (iy+d)
 </code> </code>
  
Línea 779: Línea 781:
 \\  \\ 
  
- Finalmente, se da la curiosidad de que existe una serie de opcodes que no están documentados en el manual de Z80 y que dan lugar a una operación de desplazamiento nueva llamada ''SLL'' ("Shift Left Logical"):+ No existe una instrucción oficial ''SLL'' ("Shift Left Logical") porque literalmente sería lo mismo que ''SLA'', aunque existen como instrucciones no documentadas, desde **$CB $30** hasta **$CB $37** (actuando respectivamente sobre los registros B, C, D, E, H, L, (HL) y A), así como variantes con (IX/IY+d). 
 + 
 + Finalmente, se da la curiosidad de que existe una serie de opcodes que no están documentados en el manual de Z80 y que dan lugar a una operación de desplazamiento nueva llamada ''SLI'' ("Shift Left And Increment") o ''SL1'' (según el ensamblador que utilicemos):
  
 <code z80> <code z80>
-SLL +sli 
-SLL (HL+sli (hl
-SLL (IX+d) +sli (ix+d) 
-SLL (IY+d)+sli (iy+d)
 </code> </code>
  
Línea 792: Línea 796:
 <code> <code>
  Bit 7 6 5 4 3 2 1 0                C    7 6 5 4 3 2 1 0  Bit 7 6 5 4 3 2 1 0                C    7 6 5 4 3 2 1 0
-    ----------------- -> SLL ->  ------------------------+    ----------------- -> SLI ->  ------------------------
      a b c d e f g h                a    b c d e f g h 1      a b c d e f g h                a    b c d e f g h 1
 </code> </code>
Línea 801: Línea 805:
                         Flags                         Flags
   Instrucción       |S Z H P N C|        Significado   Instrucción       |S Z H P N C|        Significado
- ----------------------------------------------------------------- + ------------------------------------------------------------------------------ 
-  SLA s             |* * 0 P 0 *|        Shift Left Arithmetic (s=s*2) +  SLA s             |* * 0 P 0 *|        Shift Left Arithmetic (s = s<<= s*2) 
-  SRA s             |* * 0 P 0 *|        Shift Right Arithmetic (s=s/2) +  SRA s             |* * 0 P 0 *|        Shift Right Arithmetic (s = s/2) 
-  SRL s             |* * 0 P 0 *|        Shift Right Logical (s=s>>1) +  SRL s             |* * 0 P 0 *|        Shift Right Logical (s = s>>1) 
-  SLL s             |* * 0 P 0 *|        Shift Left Logical+  SLI s             |* * 0 P 0 *|        Shift Left and Increment s = (s<<1)+1 
 </code> </code>
  
Línea 833: Línea 837:
  
 <code z80> <code z80>
-  SLA E +sla e 
-  RL  D+rl  d
 </code> </code>
  
-Lo que hacemos con ''SLA E'' es desplazar el byte más bajo del registro de 16 bits DE hacia la izquierda, dejando el bit 7 de "E" en el Carry Flag, y después realizar una rotación de "D" hacia la izquierda introduciendo el carry flag de la operación anterior en el bit 0 de "D".+Lo que hacemos con ''sla e'' es desplazar el byte más bajo del registro de 16 bits DE hacia la izquierda, dejando el bit 7 de "E" en el Carry Flag, y después realizar una rotación de "D" hacia la izquierda introduciendo el carry flag de la operación anterior en el bit 0 de "D".
  
  
Línea 850: Línea 854:
 </code> </code>
  
-Primero con ''SLA E'' rotamos la parte baja, metiendo el bit "i" en el Carry Flag:+Primero con ''sla e'' rotamos la parte baja, metiendo el bit "i" en el Carry Flag:
  
 <code> <code>
- SLA E:+ sla e:
  
                                      E                                      E
Línea 863: Línea 867:
 </code> </code>
  
-Ahora con ''RL D'' rotamos D introduciendo el bit "i" en su bit 0:+Ahora con ''rl d'' rotamos D introduciendo el bit "i" en su bit 0:
  
 <code> <code>
- RL D:+ rl d:
  
                                      E                                      E
Línea 880: Línea 884:
  
 <code z80> <code z80>
-SRL D +srl d 
-RR E+rr e
 </code> </code>
  
Línea 889: Línea 893:
  
 <code z80> <code z80>
-LD IX, 16384 +ld ix, 16384 
-SLA (IX+sla (ix
-RL (IX+01H)+rl (ix+$01)
 </code> </code>
  
Línea 900: Línea 904:
  
 ^ Instrucción ^ Acción ^ Resultado (X=valor del CF) ^ Flags afectados ^ ^ Instrucción ^ Acción ^ Resultado (X=valor del CF) ^ Flags afectados ^
-| **RLC ** | Rotate Left Circular.\\ Rota el registro o dato en un bit a la izquierda.\\ El CF no entra en el registro.\\ El CF se ve afectado: CF = copia del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RLC ** | **Rotate Left Circular**\\ Rota el registro o dato en un bit a la izquierda.\\ El CF no entra en el registro.\\ El CF se ve afectado: CF = copia del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      b c d e f g h a</code> | <code>|S Z H P N C|     a b c d e f g h   =>      b c d e f g h a</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **RRC** | Rotate Right Circular.\\ Rota el registro o dato en un bit a la derecha.\\ No interviene el CF. \\ El CF se ve afectado: CF = copia del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RRC** | **Rotate Right Circular**\\ Rota el registro o dato en un bit a la derecha.\\ No interviene el CF. \\ El CF se ve afectado: CF = copia del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      h a b c d e f g</code> | <code>|S Z H P N C|     a b c d e f g h   =>      h a b c d e f g</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **RL** | Rotate Left.\\ Rota el registro o dato en un bit a la izquierda.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0.\\ El CF se ve afectado: CF = valor del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RL** | **Rotate Left**\\ Rota el registro o dato en un bit a la izquierda.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0.\\ El CF se ve afectado: CF = valor del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      b c d e f g h X</code> | <code>|S Z H P N C|     a b c d e f g h   =>      b c d e f g h X</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **RR** | Rotate Right.\\ Rota el registro o dato en un bit a la derecha.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0. \\ El CF se ve afectado: CF = valor del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RR** | **Rotate Right**\\ Rota el registro o dato en un bit a la derecha.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0. \\ El CF se ve afectado: CF = valor del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      X a b c d e f g </code> | <code>|S Z H P N C|     a b c d e f g h   =>      X a b c d e f g </code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **RLCA** | Rotate Left Circular Accumulator.\\ Rota el registro A en un bit a la izquierda.\\ Igual que **RLC** pero con diferente afectación de Flags.\\ El CF no entra en el registro.\\ El CF se ve afectado: CF = copia del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RLCA** | **Rotate Left Circular Accumulator**\\ Rota el registro A en un bit a la izquierda.\\ Igual que **RLC** pero con diferente afectación de Flags.\\ El CF no entra en el registro.\\ El CF se ve afectado: CF = copia del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      b c d e f g h a</code> | <code>|S Z H P N C|     a b c d e f g h   =>      b c d e f g h a</code> | <code>|S Z H P N C|
 ------------- -------------
 |- - 0 - 0 *|</code> | |- - 0 - 0 *|</code> |
-| **RRCA** | Rotate Right Circular Accumulator.\\ Rota el registro A en un bit a la derecha.\\ Igual que **RRC** pero con diferente afectación de Flags.\\ No interviene el CF. \\ El CF se ve afectado: CF = copia del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RRCA** | **Rotate Right Circular Accumulator**\\ Rota el registro A en un bit a la derecha.\\ Igual que **RRC** pero con diferente afectación de Flags.\\ No interviene el CF. \\ El CF se ve afectado: CF = copia del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      h a b c d e f g</code> | <code>|S Z H P N C|     a b c d e f g h   =>      h a b c d e f g</code> | <code>|S Z H P N C|
 ------------- -------------
 |- - 0 - 0 *|</code> | |- - 0 - 0 *|</code> |
-| **RLA** | Rotate Left Accumulator.\\ Rota el registro Aen un bit a la izquierda.\\ Igual que **RL** pero con diferente afectación de Flags.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0.\\ El CF se ve afectado: CF = valor del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RLA** | **Rotate Left Accumulator**\\ Rota el registro Aen un bit a la izquierda.\\ Igual que **RL** pero con diferente afectación de Flags.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0.\\ El CF se ve afectado: CF = valor del bit 7 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      b c d e f g h X</code> | <code>|S Z H P N C|     a b c d e f g h   =>      b c d e f g h X</code> | <code>|S Z H P N C|
 ------------- -------------
 |- - 0 - 0 *|</code> | |- - 0 - 0 *|</code> |
-| **RRA** | Rotate Right Accumulator.\\ Rota el registro A en un bit a la derecha.\\ Igual que **RR** pero con diferente afectación de Flags.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0. \\ El CF se ve afectado: CF = valor del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **RRA** | **Rotate Right Accumulator**\\ Rota el registro A en un bit a la derecha.\\ Igual que **RR** pero con diferente afectación de Flags.\\ El CF es un bit más (el 8) del registro.\\ Inserta el CF en el bit 0. \\ El CF se ve afectado: CF = valor del bit 0 | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      X a b c d e f g </code> | <code>|S Z H P N C|     a b c d e f g h   =>      X a b c d e f g </code> | <code>|S Z H P N C|
 ------------- -------------
 |- - 0 - 0 *|</code> | |- - 0 - 0 *|</code> |
-| **SLA** | Shift Left Arithmetic.\\ Desplaza el registro o dato en un bit a la izquierda.\\ Introduce un 0 por la derecha (bit 0).\\ Equivalente a multiplicar por 2.\\ El bit saliente (bit 7) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **SLA** | **Shift Left Arithmetic**\\ Desplaza el registro o dato en un bit a la izquierda.\\ Introduce un 0 por la derecha (bit 0).\\ Equivalente a multiplicar por 2.\\ El bit saliente (bit 7) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      b c d e f g h 0</code> | <code>|S Z H P N C|     a b c d e f g h   =>      b c d e f g h 0</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **SRA** | Shift Right Arithmetic.\\ Desplaza el registro o dato en un bit a la derecha.\\ Deja el bit 7 sin tocar (se queda como copia del bit 6).\\ Equivalente a dividir por 2 (con signo).\\ El bit saliente (bit 0) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **SRA** | **Shift Right Arithmetic**\\ Desplaza el registro o dato en un bit a la derecha.\\ Deja el bit 7 sin tocar (se queda como copia del bit 6).\\ Equivalente a dividir por 2 (con signo).\\ El bit saliente (bit 0) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      a a b c d e f g</code> | <code>|S Z H P N C|     a b c d e f g h   =>      a a b c d e f g</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **SRL** | Shift Right Logical.\\ Desplaza el registro o dato en un bit a la derecha.\\ Introduce un 0 por la izquierda (bit 7).\\ Equivalente a dividir por 2 en números positivos.\\ El bit saliente (bit 0) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **SRL** | **Shift Right Logical**\\ Desplaza el registro o dato en un bit a la derecha.\\ Introduce un 0 por la izquierda (bit 7).\\ Equivalente a dividir por 2 en números positivos.\\ El bit saliente (bit 0) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
     a b c d e f g h   =>      0 a b c d e f g</code> | <code>|S Z H P N C|     a b c d e f g h   =>      0 a b c d e f g</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
-| **SLL** | Shift Left Logical.\\ Desplaza el registro o dato en un bit a la izquierda.\\ Introduce un 1 por la derecha (bit 0).\\ El bit saliente (bit 7) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0+| **SLI** | **Shift Left And Increment**\\ Desplaza el registro o dato en un bit a la izquierda.\\ Introduce un 1 por la derecha (bit 0).\\ El bit saliente (bit 7) se copia al CF. | <code> C    7 6 5 4 3 2 1 0        C    7 6 5 4 3 2 1 0
 ----------------------      ---------------------- ----------------------      ----------------------
-    a b c d e f g h   =>      b c d e f g h 0</code> | <code>|S Z H P N C|+    a b c d e f g h   =>      b c d e f g h 1</code> | <code>|S Z H P N C|
 ------------- -------------
 |* * 0 P 0 *|</code> | |* * 0 P 0 *|</code> |
Línea 963: Línea 967:
  
 \\  \\ 
-Por último, tenemos **RLD** y **RRD** sin operando), que realizan una rotación de 4 bits entre A y el contenido de la memoria apuntada por HL. Esta operación existe para permitir realizar una rotación de 4 bits a derecha o izquierda del número de 12 bits cuyos bits más significativos (bits 8-11) son los 4 bits menos significativos de A, y sus 8 bits más bajos están contenidos en (HL).+Por último, tenemos **rld** y **rrd** sin operando), que realizan una rotación de 4 bits entre A y el contenido de la memoria apuntada por HL. Esta operación existe para permitir realizar una rotación de 4 bits a derecha o izquierda del número de 12 bits cuyos bits más significativos (bits 8-11) son los 4 bits menos significativos de A, y sus 8 bits más bajos están contenidos en (HL).
  
 \\  \\ 
-  * **RLD** deja en el nibble alto de A los 4 bits más altos de (HL) y el nibble bajo los 4 bits más bajos de A. Es decir, rota 4 bits a la izquierda los 3 nibbles formados por ''A-parte-baja + (HL)-parte-alta + (HL)-parte-baja'' sin modificar ''A-parte-alta''.+  * **rld** deja en el nibble alto de A los 4 bits más altos de (HL) y el nibble bajo los 4 bits más bajos de A. Es decir, rota 4 bits a la izquierda los 3 nibbles formados por ''A-parte-baja + (HL)-parte-alta + (HL)-parte-baja'' sin modificar ''A-parte-alta''.
  
 \\  \\ 
-  * **RRD** deja en el nibble alto de A los 4 bits más bajos de A y en el nibble bajo los 4 bits más altos de (HL). Es decir, rota 4 bits a la derecha los 3 nibbles formados por ''A-parte-baja + (HL)-parte-alta + (HL)-parte-baja'' sin modificar ''A-parte-alta''.+  * **rrd** deja en el nibble alto de A los 4 bits más bajos de A y en el nibble bajo los 4 bits más altos de (HL). Es decir, rota 4 bits a la derecha los 3 nibbles formados por ''A-parte-baja + (HL)-parte-alta + (HL)-parte-baja'' sin modificar ''A-parte-alta''.
  
 \\  \\ 
Línea 979: Línea 983:
 </code> </code>
  
-Resultado **RLD**:+Resultado **rld**:
  
 <code> <code>
     A     (HL)               (HL)     A     (HL)               (HL)
   ----   -----           ----- -----   ----   -----           ----- -----
-  A2-A1  M2-Ml => RLD => A2-M2 M1-A1+  A2-A1  M2-Ml => rld => A2-M2 M1-A1
  
           <--A2--><--A1-->                 <--M2--><--M1-->            <--A2--><--A1-->                 <--M2--><--M1--> 
Línea 992: Línea 996:
 </code> </code>
  
-Resultado **RRD**:+Resultado **rrd**:
  
 <code> <code>
     A     (HL)               (HL)     A     (HL)               (HL)
   ----   -----           ----- -----   ----   -----           ----- -----
-  A2-A1  M2-Ml => RRD => A2-M1 Al-M2+  A2-A1  M2-Ml => rrd => A2-M1 Al-M2
  
          <--A2--><--A1-->                 <--M2--><--M1-->           <--A2--><--A1-->                 <--M2--><--M1--> 
Línea 1011: Línea 1015:
   Instrucción       |S Z H P N C|         Significado   Instrucción       |S Z H P N C|         Significado
  -----------------------------------------------------------------  -----------------------------------------------------------------
-  RLD               |* * 0 P 0 -|         Rotate Left 4 bits +  rld               |* * 0 P 0 -|         Rotate Left 4 bits 
-  RRD               |* * 0 P 0 -|         Rotate Right 4 bits+  rrd               |* * 0 P 0 -|         Rotate Right 4 bits
 </code> </code>
 +
 +A continuación podemos ver un resumen gráfico de las diferentes instrucciones de desplazamiento obtenido del libro "//Inside your Spectrum//", de //Jeff Naylor// y //Diane Rogers//, al cual se le ha añadido la instrucción ''SLI'' (también conocida como ''SL1'' la cual no está contemplada en el libro):
 +
 +\\ 
 +{{ :cursos:ensamblador:resumen-instrucciones-rotacion-y-desplazamiento.jpg }}
 +\\ 
  
 \\  \\ 
Línea 1052: Línea 1062:
  
 <code> <code>
- 10010101 AND 0000111  = 00000101+ 10010101 and 0000111  = 00000101
  
- 00000101 OR  1100000  = 11000101+ 00000101 or  1100000  = 11000101
  
- 11000011 XOR 10011001 = 01011010+ 11000011 xor 10011001 = 01011010
 </code> </code>
  
Línea 1062: Línea 1072:
  
 <code z80> <code z80>
-AND ORIGEN +and ORIGEN 
-OR ORIGEN +or ORIGEN 
-XOR ORIGEN+xor ORIGEN
 </code> </code>
  
-Donde ''ORIGEN'' puede ser cualquier registro de 8 bits, valor inmediato de 8 bits, contenido de la memoria apuntada por [HL], o contenido de la memoria apuntada por un registro índice más un desplazamiento. El formato de la instrucción no requiere 2 operandos, ya que el registro destino sólo puede ser A.+Donde ''ORIGEN'' puede ser cualquier registro de 8 bits, valor inmediato de 8 bits, contenido de la memoria apuntada por (HL), o contenido de la memoria apuntada por un registro índice más un desplazamiento. El formato de la instrucción no requiere 2 operandos, ya que el registro destino sólo puede ser A.
  
  La operación ''CPL'', que vimos al principio de este capítulo, también se considera una operación lógica, equivalente a NOT (0->1 y 1->0).  La operación ''CPL'', que vimos al principio de este capítulo, también se considera una operación lógica, equivalente a NOT (0->1 y 1->0).
Línea 1074: Línea 1084:
  
 <code z80> <code z80>
-AND B +and b 
-OR C +or c 
-OR [HL] +or (hl) 
-XOR [IX+10] +xor (ix+10) 
-AND 45+and 45
 </code> </code>
  
Línea 1092: Línea 1102:
  
  
-Recordemos que ''AND'', ''OR'' y ''XOR'' son operaciones lógicas de un sólo bit, de modo que al trabajar con registros (o memoria, o valores inmediatos), en realidad estamos realizando 8 operaciones AND, OR o XOR, entre los diferentes bits de los operandos. Por ejemplo, al hacer un AND entre los registros A y B con ''AND B'' (A=A&B), realizamos las siguientes operaciones:+Recordemos que ''AND'', ''OR'' y ''XOR'' son operaciones lógicas de un sólo bit, de modo que al trabajar con registros (o memoria, o valores inmediatos), en realidad estamos realizando 8 operaciones AND, OR o XOR, entre los diferentes bits de los operandos. Por ejemplo, al hacer un AND entre los registros A y B con ''and b'' (A=A&b), realizamos las siguientes operaciones:
  
 <code> <code>
Línea 1105: Línea 1115:
  Resultado:  Resultado:
  
- A7 = A7 AND B7 + A7 = A7 and b7 
- A6 = A6 AND B6 + A6 = A6 and b6 
- A5 = A5 AND B5 + A5 = A5 and b5 
- A4 = A4 AND B4 + A4 = A4 and b4 
- A3 = A3 AND B3 + A3 = A3 and b3 
- A2 = A2 AND B2 + A2 = A2 and b2 
- A1 = A1 AND B1 + A1 = A1 and b1 
- A0 = A0 AND B0+ A0 = A0 and b0
 </code> </code>
  
Línea 1122: Línea 1132:
  
 <code z80> <code z80>
-RES 7, A +res 7, a 
-RES 6, A +res 6, a 
-RES 5, A +res 5, a 
-RES 4, A+res 4, a
 </code> </code>
  
Línea 1131: Línea 1141:
  
 <code z80> <code z80>
-AND %00001111+and %00001111
 </code> </code>
  
Línea 1137: Línea 1147:
  
 <code> <code>
-A = A AND 00001111b+A = A and 00001111b
 </code> </code>
  
Línea 1163: Línea 1173:
  
 <code> <code>
-RES 0,  =>  AND %11111110 +res 0,  =>  and %11111110 
-RES 1,  =>  AND %11111101 +res 1,  =>  and %11111101 
-RES 2,  =>  AND %11111011+res 2,  =>  and %11111011
 (...) (...)
-RES 7,  =>  AND $01111111+res 7,  =>  and $01111111
  
-SET 0,  =>   OR %00000001 +set 0,  =>   or %00000001 
-SET 1,  =>   OR %00000010 +set 1,  =>   or %00000010 
-SET 2,  =>   OR %00000100+set 2,  =>   or %00000100
 (...) (...)
-SET 7,  =>   OR %10000000+set 7,  =>   or %10000000
 </code> </code>
  
Línea 1185: Línea 1195:
   Instrucción       |S Z H P N C|   Instrucción       |S Z H P N C|
  ----------------------------------  ----------------------------------
-  AND s             |* * * P 0 0| +  and s             |* * * P 0 0| 
-  OR s              |* * * P 0 0| +  or s              |* * * P 0 0| 
-  XOR s             |* * * P 0 0|+  xor s             |* * * P 0 0|
 </code> </code>
  
Línea 1193: Línea 1203:
  
 <code> <code>
-BIT 0,  =>  AND %00000001 +bit 0,  =>  and %00000001 
-BIT 1,  =>  AND %00000010 +bit 1,  =>  and %00000010 
-BIT 2,  =>  AND %00000100+bit 2,  =>  and %00000100
 (...) (...)
-BIT 7,  =>  AND $10000000+bit 7,  =>  and $10000000
 </code> </code>
  
-Por ejemplo, si queremos saber si el bit 7 de A está a 1 o a 0, podemos hacer un ''AND %10000000''. Este AND dejará a 0 todos los bits menos el 7, que lo dejará sin modificar, con el valor que tuviera antes de la operación AND. Por lo tanto, se quedará a 0 o a 1. Si era 0, el resultando del AND de todo el byte será igual a zero y se activará el Zero Flag, mientras que si estaba a 1, el byte valdrá 128 (bit 7 activo) por lo que el Zero Flag se quedará inactivo. Hemos simulado así un ''BIT'' pero alterando A:+Por ejemplo, si queremos saber si el bit 7 de A está a 1 o a 0, podemos hacer un ''and %10000000''. Este AND dejará a 0 todos los bits menos el 7, que lo dejará sin modificar, con el valor que tuviera antes de la operación AND. Por lo tanto, se quedará a 0 o a 1. Si era 0, el resultando del AND de todo el byte será igual a zero y se activará el Zero Flag, mientras que si estaba a 1, el byte valdrá 128 (bit 7 activo) por lo que el Zero Flag se quedará inactivo. Hemos simulado así un ''BIT'' pero alterando A:
  
 <code z80> <code z80>
-AND %10000000 +and %10000000 
-JP NZ bit_7_activo      ; Saltar si no esta Z activado => bit 7 es 0+jp nz, bit_7_activo      ; Saltar si no esta Z activado => bit 7 es 0
 </code> </code>
  
  Hay otros usos imaginativos de las operaciones lógicas:  Hay otros usos imaginativos de las operaciones lógicas:
  
- Para empezar, ''XOR A'' es equivalente a hacer ''LD A, 0'', ya que la operación XOR de un número consigo mismo daría 0 en todos sus bits porque XOR sólo deja a uno los bits diferentes (y A XOR A tiene todos los bits iguales, por lo que todos quedan a 0). Es muy habitual ver ''XOR A'' en programas en vez de ''LD A, 0'' porque ocupa un sólo byte en el programa en vez de dos, y además se ejecuta más rápido.+ Para empezar, ''xor a'' es equivalente a hacer ''ld a, 0'', ya que la operación XOR de un número consigo mismo daría 0 en todos sus bits porque XOR sólo deja a uno los bits diferentes (y A xor a tiene todos los bits iguales, por lo que todos quedan a 0). Es muy habitual ver ''xor a'' en programas en vez de ''ld a, 0'' porque ocupa un sólo byte en el programa en vez de dos, y además se ejecuta más rápido.
  
 <code> <code>
-XOR A   =>   LD A, 0+xor a    =>   ld a, 0
 </code> </code>
  
- Por otra parte, se suele utilizar ''OR A'' para limpiar el Carry Flag y ponerlo a 0.+ Por otra parte, se suele utilizar ''or a'' para limpiar el Carry Flag y ponerlo a 0.
  
  
  • cursos/ensamblador/lenguaje_2.1705480272.txt.gz
  • Última modificación: 17-01-2024 08:31
  • por sromero