cursos:ensamblador:asmz88dk

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:asmz88dk [10-01-2024 09:47] – [Ejemplos varios] sromerocursos:ensamblador:asmz88dk [21-01-2024 16:52] (actual) – [Enlaces] sromero
Línea 1: Línea 1:
 ====== Integración de ASM en Z88DK ====== ====== Integración de ASM en Z88DK ======
  
-En este capítulo vamos a ver cómo podemos usar ASM dentro del compilador de C más utilizado en Spectrum: el Z88DK.+En este capítulo vamos a ver cómo podemos usar ASM dentro del compilador de C más utilizado en Spectrum: el **Z88DK** (//Z88 Development Kit//).
  
 La idea de hacer programas mixtos en C con pequeñas partes en ASM es la de escribir en ensamblador las partes más críticas o importantes del mismo para acelerar su ejecución. La idea de hacer programas mixtos en C con pequeñas partes en ASM es la de escribir en ensamblador las partes más críticas o importantes del mismo para acelerar su ejecución.
Línea 15: Línea 15:
 ===== Embeber ASM dentro de código C ===== ===== Embeber ASM dentro de código C =====
  
-Z88DK permite utilizar ASM de diferentes formas. En nuestro caso vamos a ver cómo se "embebeC en ASM con las siguientes directivas:+Z88DK permite utilizar ASM de diferentes formas. En nuestro caso vamos a ver cómo se embebe C en ASM con las directivas ''#asm'' y ''#endasm'':
  
 <code c> <code c>
Línea 39: Línea 39:
 { {
   #asm   #asm
-    XOR A +    xor a 
-    LD HL, 16384          ; HL = Inicio de la videoram +    ld hl, 16384          ; HL = Inicio de la videoram 
-    LD (HL),            ; Escribimos el patron A en (HL) +    ld (hl),            ; Escribimos el patron A en (HL) 
-    LD DE, 16385          ; Apuntamos DE a 16385 +    ld de, 16385          ; Apuntamos DE a 16385 
-    LD BC, 192*32-1       ; Copiaremos 192*32-1 veces (HL) en (DE) +    ld bc, 192*32-1       ; Copiaremos 192*32-1 veces (HL) en (DE) 
-    LDIR                  +    ldir                  
   #endasm   #endasm
 } }
 </code> </code>
  
- No es necesario hacer PUSH y POP de los registros para preservar sus valores porque Z88DK lo hace automáticamente por nosotros.+ No es necesario hacer ''PUSH'' ''POP'' de los registros para preservar sus valores porque Z88DK lo hace automáticamente por nosotros.
  
  Podremos llamar a esta función desde nuestro código en C como a cualquier otra función:  Podremos llamar a esta función desde nuestro código en C como a cualquier otra función:
Línea 66: Línea 66:
  Veamos unos ejemplos:  Veamos unos ejemplos:
  
-<code>+<code c>
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Sea parte de nuestro programa en C: // Sea parte de nuestro programa en C:
Línea 83: Línea 83:
  
 #asm #asm
-    LD HL,2 +    ld hl, 2 
-    ADD HL,SP           ; Ahora SP apunta al ultimo parametro metido+    add hlsp          ; Ahora SP apunta al ultimo parametro metido
                         ; en la pila por el compilador (valor de Y)                         ; en la pila por el compilador (valor de Y)
  
-    LD C, (HL+    ld c, (hl
-    INC HL +    inc hl 
-    LD B, (HL+    ld b, (hl
-    INC HL              ; Ahora BC = y+    inc hl              ; Ahora BC = y
  
-    LD E, (HL+    ld e, (hl
-    INC HL +    inc hl 
-    LD D, (HL+    ld d, (hl
-    INC HL              ; Ahora, DE = x+    inc hl              ; Ahora, DE = x
  
     ;;; (ahora hacemos lo que queramos en asm)     ;;; (ahora hacemos lo que queramos en asm)
Línea 103: Línea 103:
 </code> </code>
  
- Como hemos comentado en un apartado anterior, no tenemos que preocuparnos por hacer PUSH y POP de los registros para preservar su valor dado que Z88DK lo hace automáticamente antes y después de cada #asm y #endasm.+ Como hemos comentado en un apartado anterior, no tenemos que preocuparnos por hacer ''PUSH'' ''POP'' de los registros para preservar su valor dado que Z88DK lo hace automáticamente antes y después de cada ''#asm'' ''#endasm''.
  
- El problema es que conforme crece el número de parámetros apilados, es posible que tengamos que hacer malabarismos para almacenarlos, dado que no podemos usar HL (es nuestro puntero a la pila en las lecturas). Veamos el siguiente ejemplo con 3 parámetros, donde tenemos que usar PUSH para guardar el valor de DE y EX DEHL para acabar asociando el valor final a HL:+ El problema es que conforme crece el número de parámetros apilados, es posible que tengamos que hacer malabarismos para almacenarlos, dado que no podemos usar HL (es nuestro puntero a la pila en las lecturas). Veamos el siguiente ejemplo con 3 parámetros, donde tenemos que usar ''PUSH'' para guardar el valor de DE y ''ex dehl'' para acabar asociando el valor final a HL:
  
-<code>+<code c>
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 int Funcion(int x, int y, int z) int Funcion(int x, int y, int z)
Línea 113: Línea 113:
  
 #asm #asm
-    LD HL,2 +    ld hl, 2 
-    ADD HL,SP           ; Ahora SP apunta al ultimo parametro metido+    add hlsp          ; Ahora SP apunta al ultimo parametro metido
                         ; en la pila por el compilador (z)                         ; en la pila por el compilador (z)
-    LD C, (HL+    ld c, (hl
-    INC HL +    inc hl 
-    LD B, (HL+    ld b, (hl
-    INC HL              ; Ahora BC = z+    inc hl              ; Ahora BC = z
  
-    LD E, (HL+    ld e, (hl
-    INC HL +    inc hl 
-    LD D, (HL+    ld d, (hl
-    INC HL              ; Ahora, DE = y+    inc hl              ; Ahora, DE = y
  
-    PUSH DE             ; Guardamos DE+    push de             ; Guardamos DE
  
-    LD E, (HL+    ld e, (hl
-    INC HL +    inc hl 
-    LD D, (HL+    ld d, (hl
-    INC HL              ; Usamos DE para leer el valor de x+    inc hl              ; Usamos DE para leer el valor de x
  
-    EX DEHL           ; Ahora cambiamos x a HL +    ex dehl           ; Ahora cambiamos x a HL 
-    POP DE              ; Y recuperamos el valor de y en DE+    pop de              ; Y recuperamos el valor de y en DE
  
     ;;; (ahora hacemos lo que queramos en asm)     ;;; (ahora hacemos lo que queramos en asm)
Línea 144: Línea 144:
  La manera de leer bytes (variables de tipo char) pulsados en C es de la misma forma que leemos una palabra de 16 bits, pero ignorando la parte alta. En realidad, como la pila es de 16 bits, el compilador convierte el dato de 8 bits en uno de 16 (rellenando con ceros) y mete en la pila este valor:  La manera de leer bytes (variables de tipo char) pulsados en C es de la misma forma que leemos una palabra de 16 bits, pero ignorando la parte alta. En realidad, como la pila es de 16 bits, el compilador convierte el dato de 8 bits en uno de 16 (rellenando con ceros) y mete en la pila este valor:
  
-<code>+<code c>
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 int Funcion(char x, char y) int Funcion(char x, char y)
Línea 150: Línea 150:
  
 #asm #asm
-    LD HL,2 +    ld hl, 2 
-    ADD HL,SP           ; Ahora SP apunta al ultimo parametro metido+    add hlsp          ; Ahora SP apunta al ultimo parametro metido
                         ; en la pila por el compilador (y)                         ; en la pila por el compilador (y)
  
-    LD A, (HL)          ; Aquí tenemos nuestro dato de 8 bits (y) +    ld a, (hl)          ; Aquí tenemos nuestro dato de 8 bits (y) 
-    LD BA +    ld ba 
-    INC HL +    inc hl 
-    INC HL              ; La parte alta del byte no nos interesa+    inc hl              ; La parte alta del byte no nos interesa
  
-    LD A, (HL)          ; Aquí tenemos nuestro dato de 8 bits (x) +    ld a, (hl)          ; Aquí tenemos nuestro dato de 8 bits (x) 
-    LD CA+    ld ca
     ; Si hubiera más parámetros, necesitaríamos seguir haciendo dos     ; Si hubiera más parámetros, necesitaríamos seguir haciendo dos
-    ; "INC HL" para acceder a ellos. Como es el último, no es necesario.+    ; "inc hl" para acceder a ellos. Como es el último, no es necesario.
          
     ;;; (ahora hacemos lo que queramos en asm)     ;;; (ahora hacemos lo que queramos en asm)
Línea 169: Línea 169:
 </code> </code>
  
-Por ejemplo, veamos nuestra rutina anterior de ClearScreen() permitiendo pasar un parámetro para indicar el carácter a utilizar para el rellenado de la pantalla:+Por ejemplo, veamos nuestra rutina anterior de ''ClearScreen()'' permitiendo pasar un parámetro para indicar el carácter a utilizar para el rellenado de la pantalla:
  
 <code c> <code c>
Línea 175: Línea 175:
 { {
   #asm   #asm
-    LD HL,2 +    ld hl, 2 
-    ADD HL,SP             ; Ahora SP apunta al ultimo parametro metido+    add hlsp            ; Ahora SP apunta al ultimo parametro metido
                           ; en la pila por el compilador (value)                           ; en la pila por el compilador (value)
-    LD A, (HL)            ; Aquí tenemos nuestro dato de 8 bits (value)+    ld a, (hl)            ; Aquí tenemos nuestro dato de 8 bits (value)
          
-    LD HL, 16384          ; HL = Inicio de la videoram +    ld hl, 16384          ; HL = Inicio de la videoram 
-    LD (HL),            ; Escribimos el patron A en (HL) +    ld (hl),            ; Escribimos el patron A en (HL) 
-    LD DE, 16385          ; Apuntamos DE a 16385 +    ld de, 16385          ; Apuntamos DE a 16385 
-    LD BC, 192*32-1       ; Copiaremos 192*32-1 veces (HL) en (DE) +    ld bc, 192*32-1       ; Copiaremos 192*32-1 veces (HL) en (DE) 
-    LDIR                  +    ldir                  
   #endasm   #endasm
 } }
Línea 191: Línea 191:
  En ocasiones, es posible que incluso tengamos que utilizar variables auxiliares de memoria para guardar datos:  En ocasiones, es posible que incluso tengamos que utilizar variables auxiliares de memoria para guardar datos:
  
-<code>+<code c>
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 int Funcion(int x, int y, char z) int Funcion(int x, int y, char z)
Línea 197: Línea 197:
  
 #asm #asm
-    LD HL,2 +    ld hl, 2 
-    ADD HL,SP           ; Ahora SP apunta al ultimo parametro metido+    add hlsp          ; Ahora SP apunta al ultimo parametro metido
                         ; en la pila por el compilador (z)                         ; en la pila por el compilador (z)
  
-    LD C, (HL+    ld c, (hl
-    INC HL +    inc hl 
-    LD B, (HL+    ld b, (hl
-    INC HL              ; Ahora BC = y +    inc hl              ; Ahora BC = y 
-    LD (valor_y), BC    ; nos lo guardamos, BC libre de nuevo+    ld (valor_y), bc    ; nos lo guardamos, bc libre de nuevo
  
-    LD C, (HL+    ld c, (hl
-    INC HL +    inc hl 
-    LD B, (HL+    ld b, (hl
-    INC HL +    inc hl 
-    LD (valor_x), BC    ; Nos lo guardamos, BC libre de nuevo+    ld (valor_x), bc    ; Nos lo guardamos, bc libre de nuevo
  
-    LD A, (HL+    ld a, (hl
-    LD (valor_z),     ; Nos guardamos el byte +    ld (valor_z),     ; Nos guardamos el byte 
-    INC HL +    inc hl 
-    INC HL              ; La parte alta del byte no nos interesa+    inc hl              ; La parte alta del byte no nos interesa
  
     ;;; (ahora hacemos lo que queramos en asm)     ;;; (ahora hacemos lo que queramos en asm)
  
-    RET+    ret
  
 valor_x   DW  0 valor_x   DW  0
Línea 234: Línea 234:
 ===== Devolver parámetros desde funciones escritas en ASM ===== ===== Devolver parámetros desde funciones escritas en ASM =====
  
- Por contra, para devolver valores no se utiliza la pila dado que no podemos tocarla, ya que el RET volvería al valor pulsado y no a la dirección de retorno. Lo que se hace en Z88DK es utilizar un determinado registro. En el caso de Z88DK, se utiliza el registro **HL**. Si la función es de tipo INT o CHAR en cuanto a devolución, el valor que dejemos en HL al finalizar la función será el que se asignará en una llamada de este tipo:+ Por contra, para devolver valores no se utiliza la pila dado que no podemos tocarla, ya que el ''RET'' trataría de volver al valor pulsado y no a la dirección de retorno. Lo que se hace en Z88DK es utilizar un determinado registro. En el caso de Z88DK, se utiliza el registro **HL**. Si la función es de tipo INT o CHAR en cuanto a devolución, el valor que dejemos en HL al finalizar la función será el que se asignará en una llamada de este tipo:
  
 <code c> <code c>
Línea 249: Línea 249:
  Para aprovechar esta introducción de "uso de ASM en Z88DK", veamos el código de algunos ejemplos de funciones en C que usen ASM internamente y que muestren, entre otras cosas, la lectura de parámetros de la pila, el acceso a variables del código C, el uso de etiquetas, o la devolución de valores.  Para aprovechar esta introducción de "uso de ASM en Z88DK", veamos el código de algunos ejemplos de funciones en C que usen ASM internamente y que muestren, entre otras cosas, la lectura de parámetros de la pila, el acceso a variables del código C, el uso de etiquetas, o la devolución de valores.
  
- Como ejemplo de función sin parámetros, y que tampoco devuelve ningún valor, además del **ClearScreen()** que hemos visto al principio de este capítulo, podemos examinar la siguiente función de "Fundido de pantalla a negro", la cual hace uso de etiquetas de Z88DK, que van precedidas de un carácter punto en lugar del sufijo de los dos puntos que usamos normalmente en programas ensambladores:+ Como ejemplo de función sin parámetros, y que tampoco devuelve ningún valor, además del ''ClearScreen()'' que hemos visto al principio de este capítulo, podemos examinar la siguiente función de "Fundido de pantalla a negro", la cual hace uso de etiquetas de Z88DK, que van precedidas de un carácter punto en lugar del sufijo de los dos puntos que usamos normalmente en programas ensambladores:
    
 <code c> <code c>
Línea 262: Línea 262:
  
 #asm #asm
-    LD B, 9                      ; Repetiremos el bucle 9 veces+    ld b, 9                      ; Repetiremos el bucle 9 veces
  
 .fadescreen_loop1 .fadescreen_loop1
-    LD HL, 16384+6144            ; Apuntamos HL a la zona de atributos +    ld hl, 16384+6144            ; Apuntamos HL a la zona de atributos 
-    LD DE, 768                   ; Iteraciones bucle+    ld de, 768                   ; Iteraciones bucle
  
-    HALT +    halt 
-    HALT                         ; Ralentizamos el efecto+    halt                         ; Ralentizamos el efecto
  
 .fadescreen_loop2 .fadescreen_loop2
-    LD A, (HL)                   ; Cogemos el atributo +    ld a, (hl)                   ; Cogemos el atributo 
-    AND 127                      ; Eliminamos el bit de flash +    and 127                      ; Eliminamos el bit de flash 
-    LD CA+    ld ca
  
-    AND 7                        ; Extraemos la tinta (AND 00000111b) +    and 7                        ; Extraemos la tinta (and 00000111b) 
-    JR Z, fadescreen_ink_zero    ; Si la tinta ya es cero, no hacemos nada+    jr z, fadescreen_ink_zero    ; Si la tinta ya es cero, no hacemos nada
  
-    DEC A                        ; Si no es cero, decrementamos su valor+    dec a                        ; Si no es cero, decrementamos su valor
  
 .fadescreen_ink_zero .fadescreen_ink_zero
  
-    EX AFAF                    ; Nos hacemos una copia de la tinta en A +    ex afaf                    ; Nos hacemos una copia de la tinta en A 
-    LD A                     ; Recuperamos el atributo +    ld a                     ; Recuperamos el atributo 
-    SRA A +    sra a 
-    SRA A                        ; Pasamos los bits de paper a 0-2 +    sra a                        ; Pasamos los bits de paper a 0-2 
-    SRA A                        ; con 3 instrucciones de desplazamiento >>+    sra a                        ; con 3 instrucciones de desplazamiento >>
  
-    AND 7                        ; Eliminamos el resto de bits +    and 7                        ; Eliminamos el resto de bits 
-    JR Z, fadescreen_paper_zero  ; Si ya es cero, no lo decrementamos+    jr z, fadescreen_paper_zero  ; Si ya es cero, no lo decrementamos
  
-    DEC A                        ; Lo decrementamos+    dec a                        ; Lo decrementamos
  
 .fadescreen_paper_zero .fadescreen_paper_zero
-    SLA A +    sla a 
-    SLA A                        ; Volvemos a color paper en bits 3-5 +    sla a                        ; Volvemos a color paper en bits 3-5 
-    SLA A                        ; Con 3 instrucciones de desplazamiento <<+    sla a                        ; Con 3 instrucciones de desplazamiento <<
  
-    LD C                     ; Guardamos el papel decrementado en A +    ld c                     ; Guardamos el papel decrementado en A 
-    EX AFAF                    ; Recuperamos A +    ex afaf                    ; Recuperamos A 
-    OR C                         ; A = A OR C   PAPEL OR TINTA+    or c                         ; A = A or c   PAPEL OR TINTA
  
-    LD (HL),                   ; Almacenamos el atributo modificado +    ld (hl),                   ; Almacenamos el atributo modificado 
-    INC HL                       ; Avanzamos puntero de memoria+    inc hl                       ; Avanzamos puntero de memoria
  
-    DEC DE +    dec de 
-    LD AD +    ld ad 
-    OR E +    or e 
-    JP NZ, fadescreen_loop2      ; Hasta que DE == 0+    jp nz, fadescreen_loop2      ; Hasta que DE == 0
  
-    DJNZ fadescreen_loop1        ; Repeticion 9 veces+    djnz fadescreen_loop1        ; Repeticion 9 veces
  
 #endasm #endasm
Línea 317: Línea 317:
 </code> </code>
  
- Un detalle a tener en cuenta, para demostrar esas pequeñas diferencias entre **z80asm** y **pasmo**, es que z80asm utiliza el nmemónico "**EX AF, AF**", mientras que pasmo requiere poner la comilla del shadow-register: "**EX AFAF'**".+ Un detalle a tener en cuenta, para demostrar esas pequeñas diferencias entre **z80asm** y **pasmo**, es que z80asm utiliza el nmemónico ''ex afaf'' mientras que pasmo requiere poner la comilla del shadow-register: ''ex afaf<nowiki>'</nowiki>''.
  
 \\  \\ 
Línea 325: Línea 325:
  En la anterior captura podéis ver el aspecto de uno de los pasos del fundido.  En la anterior captura podéis ver el aspecto de uno de los pasos del fundido.
  
- A continuación vamos a ver una rutina que calcula la dirección de un atributo de pantalla dadas las coordenadas X,Y en baja resolución (0-31, 0-23) de un "bloque" 8x8 de la pantalla. La función recibe dos parámetros de tipo CHAR (x e y). Para recoger los valores de estos parámetros con el objetivo de operar con ellos, ignora la parte alta de cada uno de los 2 parámetros en la pila.+ A continuación vamos a ver una rutina que calcula la dirección de un atributo de pantalla dadas las coordenadas X,Y en baja resolución (0-31, 0-23) de un "bloque" 8x8 de la pantalla. La función recibe dos parámetros de tipo ''char'' (**x** **y**). Para recoger los valores de estos parámetros con el objetivo de operar con ellos, ignora la parte alta de cada uno de los 2 parámetros en la pila.
    
  El cálculo resultante se almacena en HL para que este valor sea devuelto a C, de forma que se asigne como resultado de la llamada.  El cálculo resultante se almacena en HL para que este valor sea devuelto a C, de forma que se asigne como resultado de la llamada.
Línea 342: Línea 342:
 #asm #asm
  
-    LD HL, 2 +    ld hl, 2 
-    ADD HLSP                 ; Leemos x e y de la pila +    add hlsp                 ; Leemos x e y de la pila 
-    LD  D, (HL)  ; d = y +    ld  d, (hl)  ; d = y 
-    INC HL                     ; Primero "y" y luego "x"+    inc hl                     ; Primero "y" y luego "x"
-    INC HL                     ; Como son "char", ignoramos parte alta. +    inc hl                     ; Como son "char", ignoramos parte alta. 
-    LD  E, (HL)  ; e = x+    ld  e, (hl)  ; e = x
  
-    LD H, 0 +    ld h, 0 
-    LD LD +    ld ld 
-    ADD HLHL                 ; HL = HL*2 +    add hlhl                 ; HL = HL*2 
-    ADD HLHL                 ; HL = HL*4 +    add hlhl                 ; HL = HL*4 
-    ADD HLHL                 ; HL = HL*8 +    add hlhl                 ; HL = HL*8 
-    ADD HLHL                 ; HL = HL*16 +    add hlhl                 ; HL = HL*16 
-    ADD HLHL                 ; HL = HL*32 +    add hlhl                 ; HL = HL*32 
-    LD D, 0 +    ld d, 0 
-    ADD HLDE                 ; Ahora HL = (32*y)+x +    add hlde                 ; Ahora HL = (32*y)+x 
-    LD BC, 16384+6144          ; Ahora BC = offset attrib (0,0) +    ld bc, 16384+6144          ; Ahora BC = offset attrib (0,0) 
-    ADD HLBC                 ; Sumamos y devolvemos en HL+    add hlbc                 ; Sumamos y devolvemos en HL
 #endasm #endasm
 } }
Línea 366: Línea 366:
 El siguiente ejemplo muestra cómo acceder a variables globales del programa en C desde nuestro código en ASM, utilizando un "subrayado" ("_") delante del nombre de la variable que queremos acceder El siguiente ejemplo muestra cómo acceder a variables globales del programa en C desde nuestro código en ASM, utilizando un "subrayado" ("_") delante del nombre de la variable que queremos acceder
  
-<code>+<code c>
 // //
 // Set Border // Set Border
Línea 377: Línea 377:
 { {
 #asm #asm
-    LD HL, 2 +    ld hl, 2 
-    ADD HLSP +    add hlsp 
-    LD A, (HL)             ; A = parametro de la pila (value)+    ld a, (hl)             ; A = parametro de la pila (value)
          
-    LD C254 +    ld c$FE 
-    OUT (C), A +    out (c), a 
-    LD (_bordeactual),   ; Guardamos el valor del borde en la variable+    ld (_bordeactual),   ; Guardamos el valor del borde en la variable
 #endasm #endasm
 } }
Línea 457: Línea 457:
     inc hl     inc hl
     pop bc                              // recuperamos BC     pop bc                              // recuperamos BC
-    dec bc                              // Este DEC BC puede hacer BC=0 si los datos+    dec bc                              // Este dec bc puede hacer BC=0 si los datos
                                         // RLE no correctos. Cuidado (mem-smashing).                                         // RLE no correctos. Cuidado (mem-smashing).
     dec bc     dec bc
Línea 474: Línea 474:
 //--- SetRAMBank ------------------------------------------------------ //--- SetRAMBank ------------------------------------------------------
 // //
-// Se mapea el banco (0-7) indicado sobre $C000.+// Se mapea el banco (0-7) indicado sobre $c000.
 // //
 // Ojo: en esta función no se deshabilitan las interrupciones y además,  // Ojo: en esta función no se deshabilitan las interrupciones y además, 
Línea 488: Línea 488:
  
     ld b, a     ld b, a
-    ld a, ($5B5C)+    ld a, ($5b5c)
     and f8h     and f8h
     or b     or b
-    ld bc, $7FFD +    ld bc, $7ffd 
-    ld ($5B5C), a+    ld ($5b5c), a
     out (c), a        ; Realizamos cambio de banco     out (c), a        ; Realizamos cambio de banco
    #endasm    #endasm
Línea 498: Línea 498:
 </code> </code>
  
-Con el anterior código podemos mapear uno de los bancos de memoria de 16KB sobre la página que va desde $C000 a $FFFF, pero debido al uso de memoria, variables y estructuras internas que hace Z88DK, debemos seguir una serie de consideraciones.+Con el anterior código podemos mapear uno de los bancos de memoria de 16KB sobre la página que va desde $c000 a $ffff, pero debido al uso de memoria, variables y estructuras internas que hace Z88DK, debemos seguir una serie de consideraciones
 + 
 +  * Todo el código en ejecución debe estar por debajo de $c000, para lo cual es recomendable definir los gráficos al final del "binario".
  
-  * Todo el código en ejecución debe estar por debajo de $C000, para lo cual es recomendable definir los gráficos al final del "binario". 
   * Es importantísimo colocar la pila en la memoria baja, mediante la siguiente instrucción (o similar, según la dirección en que queremos colocarla) al principio de nuestro programa:   * Es importantísimo colocar la pila en la memoria baja, mediante la siguiente instrucción (o similar, según la dirección en que queremos colocarla) al principio de nuestro programa:
  
 \\  \\ 
-<code>+<code c>
 /* Allocate space for the stack */ /* Allocate space for the stack */
 #pragma output STACKPTR=24500 #pragma output STACKPTR=24500
Línea 510: Línea 511:
 \\  \\ 
  
- La regla general es asegurarse de que no haya nada importante (para la ejecución de nuestro programa) en el bloque $C000 a $FFFF cuando se haga el cambio: ni la pila, ni código al que debamos acceder. Tan sólo datos que puedan ser intercambiandos de un banco a otro sin riesgo para la ejecución del mismo (por ejemplo, los datos de un nivel de juego en el que ya no estamos).+ La regla general es asegurarse de que no haya nada importante (para la ejecución de nuestro programa) en el bloque $c000 a $ffff cuando se haga el cambio: ni la pila, ni código al que debamos acceder. Tan sólo datos que puedan ser intercambiandos de un banco a otro sin riesgo para la ejecución del mismo (por ejemplo, los datos de un nivel de juego en el que ya no estamos).
  
  
Línea 520: Línea 521:
  
 \\  \\ 
-**[ [[.:indice|⬉]] | [[.:avanzadas2|⬅]] ]**+**[ [[.:indice|⬉]] | [[.:avanzadas2|⬅]] | [[.:anexo1|➡]] ]**
  • cursos/ensamblador/asmz88dk.1704880042.txt.gz
  • Última modificación: 10-01-2024 09:47
  • por sromero