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:ensambladores [16-01-2024 07:33] – [Programas ensambladores] sromero | cursos:ensamblador:ensambladores [24-01-2024 08:01] (actual) – sromero | ||
---|---|---|---|
Línea 15: | Línea 15: | ||
Aunque estos 3 ensambladores comprenden los **nmemónicos** del Z80 (las instrucciones que hemos estado viendo en los anteriores capítulos), | Aunque estos 3 ensambladores comprenden los **nmemónicos** del Z80 (las instrucciones que hemos estado viendo en los anteriores capítulos), | ||
- | * pasmo y sjasmplus usan el nmenónico '' | + | * pasmo y sjasmplus usan el nmenónico '' |
- | * sjasmplus soporta "Fake instructions" | + | * sjasmplus soporta "Fake instructions" |
Pero la mayor incompatibilidad viene en las **directivas** del lenguaje ensamblador, | Pero la mayor incompatibilidad viene en las **directivas** del lenguaje ensamblador, | ||
Línea 33: | Línea 33: | ||
Los siguientes 3 apartados mostrarán lo siguiente: | Los siguientes 3 apartados mostrarán lo siguiente: | ||
- | * **Directivas comunes**: aquellas directivas de ensamblador básicas, presentes en prácticamente todos los programa ensambladores, | + | \\ |
+ | * **Directivas comunes | ||
* **Directivas propias de pasmo**: directivas y peculiaridades de pasmo. Hablaremos de cómo se ensamblan programas en pamo y de algunas directivas que se utilizan en pasmo de diferente forma que en otros ensambladores, | * **Directivas propias de pasmo**: directivas y peculiaridades de pasmo. Hablaremos de cómo se ensamblan programas en pamo y de algunas directivas que se utilizan en pasmo de diferente forma que en otros ensambladores, | ||
Línea 47: | Línea 48: | ||
\\ | \\ | ||
- | ===== Directivas comunes ===== | + | ===== Directivas comunes |
- | Las siguientes directivas son comunes a los diferentes ensambladores, | + | Las siguientes directivas son comunes a los diferentes ensambladores, |
Ya hemos utilizado algunas de ellas en programas de ejemplo, y otras las utilizaremos en posteriores capítulos. | Ya hemos utilizado algunas de ellas en programas de ejemplo, y otras las utilizaremos en posteriores capítulos. | ||
Línea 65: | Línea 66: | ||
ORG 35000 | ORG 35000 | ||
- | | + | |
| | ||
menu: | menu: | ||
- | | + | |
- | | + | |
main: | main: | ||
- | | + | |
- | | + | |
- | | + | |
| | ||
INCLUDE " | INCLUDE " | ||
Línea 117: | Línea 118: | ||
\\ | \\ | ||
- | ===== pasmo ===== | + | ===== Directivas específicas de pasmo ===== |
\\ | \\ | ||
Línea 142: | Línea 143: | ||
ORG 33500 | ORG 33500 | ||
- | 82DC CD 0DAF | + | 82DC CD 0DAF |
- | 82DF 06 FF | + | 82DF 06 FF |
bucle: | bucle: | ||
- | 82E1 | + | 82E1 |
- | 82E2 | + | 82E2 |
- | 82E3 06 00 | + | 82E3 06 00 |
- | 82E5 CD 82F1 | + | 82E5 CD 82F1 |
- | 82E8 | + | 82E8 |
- | 82E9 CD 8304 | + | 82E9 CD 8304 |
- | 82EC 10 F3 | + | 82EC 10 F3 |
- | 82EE | + | 82EE |
82EF | 82EF | ||
Línea 186: | Línea 187: | ||
_loop: | _loop: | ||
... | ... | ||
- | | + | |
- | | + | |
Rutina2: | Rutina2: | ||
Línea 193: | Línea 194: | ||
_loop: | _loop: | ||
... | ... | ||
- | | + | |
- | | + | |
</ | </ | ||
\\ | \\ | ||
Línea 220: | Línea 221: | ||
\\ | \\ | ||
<code z80> | <code z80> | ||
- | | + | |
drawsp8x8_loopLD: | drawsp8x8_loopLD: | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
\\ | \\ | ||
Línea 235: | Línea 236: | ||
\\ | \\ | ||
<code z80> | <code z80> | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
(...) ; Y así 8 veces | (...) ; Y así 8 veces | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
\\ | \\ | ||
Línea 266: | Línea 267: | ||
<code z80> | <code z80> | ||
REPT 8 | REPT 8 | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDM | ENDM | ||
</ | </ | ||
Línea 279: | Línea 280: | ||
<code z80> | <code z80> | ||
REPT 7 | REPT 7 | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDM | ENDM | ||
- | | + | |
- | | + | |
- | | + | |
</ | </ | ||
\\ | \\ | ||
Línea 295: | Línea 296: | ||
\\ | \\ | ||
- | ===== sjasmplus ===== | + | ===== Directivas específicas de sjasmplus ===== |
==== Generar BINs, TAPs y SNAs con sjasmplus ==== | ==== Generar BINs, TAPs y SNAs con sjasmplus ==== | ||
Línea 321: | Línea 322: | ||
ORG 35000 | ORG 35000 | ||
- | BORDCR EQU $5C48 ; Spectrum' | + | BORDCR EQU $5c48 ; Spectrum' |
; | ; | ||
Línea 431: | Línea 432: | ||
.loop: | .loop: | ||
... | ... | ||
- | | + | |
- | | + | |
Rutina2: | Rutina2: | ||
Línea 438: | Línea 439: | ||
.loop: | .loop: | ||
... | ... | ||
- | | + | |
.loop2: | .loop2: | ||
- | | + | |
- | | + | |
</ | </ | ||
Línea 452: | Línea 453: | ||
<code z80> | <code z80> | ||
REPT 8 | REPT 8 | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDR | ENDR | ||
</ | </ | ||
Línea 477: | Línea 478: | ||
inicio: | inicio: | ||
- | | + | |
bucle: | bucle: | ||
- | | + | |
;... | ;... | ||
- | | + | |
DISPLAY "-- Final del ensamblado --" | DISPLAY "-- Final del ensamblado --" | ||
Línea 542: | Línea 543: | ||
IF (MODO_DEBUG == 1) | IF (MODO_DEBUG == 1) | ||
- | | + | |
- | | + | |
- | | + | |
ENDIF | ENDIF | ||
Línea 600: | Línea 601: | ||
\\ | \\ | ||
- | Ahora, sjasmplus sólo ensamblará e incluirá en el BIN/TAP final el código máquina de la rutina, si esta es llamada ('' | + | Ahora, sjasmplus sólo ensamblará e incluirá en el BIN/TAP final el código máquina de la rutina, si esta es llamada ('' |
Veamos el caso de nuestra librería '' | Veamos el caso de nuestra librería '' | ||
Línea 614: | Línea 615: | ||
PrintSpace: | PrintSpace: | ||
IFUSED | IFUSED | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDIF | ENDIF | ||
PrintCR: | PrintCR: | ||
IFUSED | IFUSED | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDIF | ENDIF | ||
</ | </ | ||
Línea 658: | Línea 659: | ||
IF USAR_PRINTSPACE = 1 | IF USAR_PRINTSPACE = 1 | ||
PrintSpace: | PrintSpace: | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDIF | ENDIF | ||
IF USAR_PRINTCR = 1 | IF USAR_PRINTCR = 1 | ||
PrintCR: | PrintCR: | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
ENDIF | ENDIF | ||
Línea 705: | Línea 706: | ||
La desventaja de '' | La desventaja de '' | ||
+ | |||
+ | \\ | ||
+ | De nuevo, **pasmo no tiene esta funcionalidad**, | ||
+ | |||
+ | <code z80> | ||
+ | ; Macro de alineacion para PASMO | ||
+ | align macro value | ||
+ | if $ mod value | ||
+ | ds value - ($ mod value) | ||
+ | endif | ||
+ | endm | ||
+ | |||
+ | align 256 | ||
+ | </ | ||
\\ | \\ | ||
- | ===== z80asm ===== | + | ===== Una visión breve de z80asm ===== |
El ensamblador z80asm es un mundo en sí mismo ya que permite generar código para gran cantidad de sistemas Z80 (desde el Z80 del Spectrum, a la variante del Z80 que utiliza la GameBoy clásica). | El ensamblador z80asm es un mundo en sí mismo ya que permite generar código para gran cantidad de sistemas Z80 (desde el Z80 del Spectrum, a la variante del Z80 que utiliza la GameBoy clásica). | ||
Línea 730: | Línea 745: | ||
$ cat bucle.sym | $ cat bucle.sym | ||
bucle = $0002 ; addr, local, , , , bucle.asm:4 | bucle = $0002 ; addr, local, , , , bucle.asm:4 | ||
- | variable | + | variable |
$ cat bucle.map | $ cat bucle.map | ||
- | bucle = $82DE ; addr, local, , bucle, , bucle.asm: | + | bucle = $82de ; addr, local, , bucle, , bucle.asm: |
- | variable | + | variable |
- | __head | + | __head |
- | __tail | + | __tail |
- | __size | + | __size |
$ cat bucle.lis | $ cat bucle.lis | ||
Línea 743: | Línea 758: | ||
| | ||
2 | 2 | ||
- | | + | |
| | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
9 | 9 | ||
- | 10 0007 10f9 | + | 10 0007 10f9 |
11 | 11 | ||
- | 12 0009 c9 | + | 12 0009 c9 |
13 | 13 | ||
14 000a ffff variable: | 14 000a ffff variable: | ||
Línea 760: | Línea 775: | ||
| | ||
+ | El uso habitual de z80asm es el de generar " | ||
\\ | \\ | ||
+ | <code z80> | ||
+ | ; Fichero libreria.asm | ||
+ | SECTION code_user | ||
+ | |||
+ | ; exportamos el nombre de nuestra rutina para que sea usable desde C: | ||
+ | |||
+ | PUBLIC _nuestra_rutina_asm | ||
+ | |||
+ | ; Variables o funciones externas globales de C (definidas en el | ||
+ | ; programa en C) a las que queremos acceder desde este código ASM: | ||
+ | |||
+ | EXTERN _una_variable_global_de_C | ||
+ | EXTERN _funcion_externa_de_C | ||
+ | |||
+ | _nuestra_rutina_asm: | ||
+ | |||
+ | ; Llamar a función C | ||
+ | call _funcion_externa_de_C | ||
+ | |||
+ | ; Acceder a variable C | ||
+ | ld a, _una_variable_global_de_C | ||
+ | |||
+ | loop: | ||
+ | (...) | ||
+ | |||
+ | djnz loop ; do it for all five members of array a[] | ||
+ | ret | ||
+ | </ | ||
+ | \\ | ||
+ | |||
+ | Este programa en ensamblador define una rutina la cual hace pública con '' | ||
+ | |||
+ | A continuación podemos crear un programa en C que haga uso de esta librería: | ||
+ | |||
+ | \\ | ||
+ | <code c> | ||
+ | // Fichero ejemplo.c | ||
+ | #include < | ||
+ | |||
+ | unsigned char una_variable_global_de_C = 128; | ||
+ | |||
+ | void funcion_externa_de_C(void) | ||
+ | { | ||
+ | // Hacer algo | ||
+ | | ||
+ | } | ||
+ | |||
+ | // Declaramos en C como extern nuestra rutina ASM (externa) | ||
+ | extern void nuestra_rutina_asm(void); | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | | ||
+ | |||
+ | | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | |||
+ | Nótese el prefijo '' | ||
+ | |||
+ | Ahora podemos compilar el programa de la siguiente forma: | ||
+ | |||
+ | '' | ||
+ | |||
+ | Así, podemos crear diferentes módulos y librerías para tareas que requieran la máxima velocidad (impresión de gráficos, sonido, texto, etc) y utilizarlos dentro de programas en C. Pero eso nos obliga a realizar los ficheros ASM en formato z80asm, porque como se puede apreciar en la línea que hemos usado para compilar el programa, no se incluyen como librerías externas sino que se compilan junto al propio código C. | ||
+ | |||
===== En resumen ===== | ===== En resumen ===== | ||
- | Los diferentes programas ensambladores tienen una gran cantidad de directivas en común, pero también una serie de directivas propias de cada uno de ellos (o bien que unos las implementan y otros no, o bien que lo hacen con un nombre | + | Los diferentes programas ensambladores tienen una gran cantidad de directivas en común, pero también una serie de directivas propias de cada uno de ellos (o bien que unos las implementan y otros no, o bien que lo hacen con un formato o modo de uso diferente). |
Dejando de lado z80asm, que sólo recomendamos usar si necesitamos escribir código C+ASM para Z88DK, las dos opciones que nos quedan son **pasmo** y **sjasmplus**. | Dejando de lado z80asm, que sólo recomendamos usar si necesitamos escribir código C+ASM para Z88DK, las dos opciones que nos quedan son **pasmo** y **sjasmplus**. | ||
Línea 770: | Línea 853: | ||
Si escribimos código ASM puro, sin utilizar las ventajas que proporcionan los ensambladores, | Si escribimos código ASM puro, sin utilizar las ventajas que proporcionan los ensambladores, | ||
- | Pero en cuanto utilizamos cualquier funcionalidad especial del ensamblador, | + | Pero en cuanto utilizamos cualquier funcionalidad especial del ensamblador, |
Estas funcionalidades (etiquetas locales, macros, DEFINES, etc) son básicas para facilitarnos la vida cuando se programa en un lenguaje como ensamblador, | Estas funcionalidades (etiquetas locales, macros, DEFINES, etc) son básicas para facilitarnos la vida cuando se programa en un lenguaje como ensamblador, | ||
- | Lo hemos dicho ya varias veces: nuestro consejo para seguir el curso, escribir un programa sencilla, | + | Lo hemos dicho ya varias veces: nuestro consejo para seguir el curso, escribir un pequeño fragmento de código para comprobar |
Línea 789: | Línea 872: | ||
\\ | \\ | ||
- | **[ [[.: | + | **[ [[.: |