Revistas en papel
 Commodore World Nº59
Anterior
Menú
Logotipo

INICIACIÓN AL LENGUAJE
ENSAMBLADOR

Por Fernando García

Bienvenido al Lenguaje Ensamblador. Este es, sin duda, el lenguaje
más rápido, aunque también puede ser considerado el más complejo.
En este cursillo se demostrará que estas complejidades pueden ser
resultas satisfactoriamente.


El Lenguaje Ensamblador (Assembler en inglés) es el que permite utilizar directamente las instrucciones y registros del 68000 y así, combinándolos, acceder a todas las partes del ordenador: coprocesadores, drives, teclado, memoria y demás.

Antes de comenzar conviene resaltar los pros y los contras de este lenguaje:

  • Es el más rápido y seguro, el que menos memoria ocupa y el que más se acerca a la estructura del propio ordenador.

  • Como contras, es el que más tiempo lleva en programar, y el más difícil de adaptar a otros ordenadores.

Pero ahora no te asustes, lo explicaré de otra manera. Si vas a realizar un programa compatible en otros ordenadores, en un espacio de tiempo no muy largo, los lenguajes más apropiados pueden ser el Basic, el C e incluso el Modula. Pero sin embargo, si preparas un programa a medida para un ordenador y dispones de tiempo de sobra, te recomiendo el ensamblador. ¿Por qué? Porque vas a tener la total seguridad de que tu programa, si lo has realizado correctamente, no pueda ir más rápido, que va a ocupar poca memoria y al mismo tiempo la probabilidad de que no se quede "colgado" va a ser altísima.


Aplicaciones del Ensamblador

El ensamblador, dada su complejidad, se utiliza normalmente para realizar rutinas de manejo gráfico, es decir: CAD, Animación, Dibujo, etc., en las que la velocidad juega un papel importantísimo. Lo más normal es que el programa se realice en C y las rutinas más importantes se programen en ensamblador. El caso de los juegos es parecido, aunque con la popularidad del C y su relativa compatibilidad con otros ordenadores hace que el ensamblador quede en segundo término. Vuelvo a repetir que esto no hace al ensamblador un intocable, pues veremos que poco a poco iremos saltándonos estas barreras.


Características

Su característica primordial es el manejo de etiquetas. No te puedes imaginar el trabajo que ahorra el poder "etiquetar", por decirlo de alguna forma, una subrutina o constante y acceder a ella haciendo referencia a su nombre. Si no hubiera etiquetas, los programadores se pasarían la mayoría del tiempo calculando posiciones de memoria en donde colocar las rutinas. Pero el ensamblador tiene más cualidades, que iré describiendo más tarde.

El ensamblador consta de dos partes o programas: el Ensamblador y el Linker (también llamado "Linkador"). El ensamblador es el que traduce las instrucciones y directivas (una especie de comandos que facilitan las tareas) dadas por el programa fuente (tu programa) en instrucciones reconocibles por el 68000 (programa objeto). Pero ésto no basta, quedan nucos que atar, como las definiciones, referencias externas, ficheros "include", es decir, una serie de estas directivas que permiten acceder a otros programas fuente.

Ahora es donde actúa el Linker. Une los programas ya ensamblados (normalmente no es necesario utilizar dos programas fuentes, pero en el resto de los capítulos lo haremos) y resuelve todas esas directivas a que hacíamos referencia. Otra de las características del Linker es la de transformar los ficheros objeto producidos por el ensamblador en ficheros ejecutables desde CLI o Workbench.


Herramientas de trabajo

Vamos ahora con el material requerido para poder empezar. El primero y primordial es el ensamblador, de los que existen varios modelos. Si tienes problemas a la hora de conseguirlo, los hay también de dominio público, como el A68k. En cuanto a los comerciales están el Macro Assembler (el que actualmente utilizo), el Lattice C y el Aztec C, entre otros. Excepto el A68k, todos los comerciales ya llevan el Linker incluido.

                   TTL     "Astartup"
                   XDEF    STARTUP
                   XDEF    _Stdin
                   XDEF    _stdout
                   XDEF    paramcnt
                   XDEF    paramlen
                   XDEF    paramadd
                   XDEF    parambuf
                   XDEF    _SysBase
                   XDEF    _DOSBase
                   XDEF    OurTask
                   XDEF    inicialSP
                   XREF    START
* inicializa rutina ******************************************************
STARTUP            MOVE.L  A7,inicialSP    salva puntero de pila
                   MOVEM.L D0/A0,-(A7)     salva l�nea de comandos
                   MOVE.L  4,A6            obtiene direcci�n SysBase
                   MOVE.L  A6,_SysBase     la salva
                   SUBA.L  A1,A1           hace nulo el puntero del nombre
                   JSR     -$126(A6)       va a FindTask para buscar Task
                   MOVE.L  D0,A4           apunta a TCB de NuestroTask
                   MOVE.L  D0,OurTask      lo salva
                   LEA     DOSName,A1      apunta el nombre DOS'
                   JSR     -$198(A6)       abre librer�a
                   MOVE.L  D0,_DOSBase     salva la direcci�n base
                   TST.L   $AC(A4)         es CLI?
                   BEQ     desdeWorkbench  no, saltar adelante
* CLI rutina *************************************************************
                   CLR.L   D2              si, borrar cont. de par�metro
                   LEA     parambuf,A2     apunta a buffer de par�metro
                   LEA     paramadd,A3     apunta a direcci�n de par�metro
                   LEA     paramlen.A4     apunta a la long. del par�metro
                   MOVEM.L (A7)+,D0/A0     restablece informaci�n
1$                 CLR.L   D3              borrar contador de longitud
2$                 MOVE.B  (A0)+,D1        obtener un byte
                   SUBI.L  #1,D0           contarlo
                   BLE     paramExit       �ltimo, saltar adelante
                   CMPI.B  #$20,D1         es valido?
                   BLE     2$              no, ir otra vez
                   ADDI.L  #1,D2           si, contar un par�metro
                   ADDI.L  #1,D3           contar la longitud
                   MOVE.L  A2,(A3)+        salvar direcci�n
3$                 MOVE.B  D1,(A2)+        salvar el byte
                   MOVE.B  (A0)+,D1        obtener siguiente byte
                   SUBI.L  #1,D0           contarlo?
                   CMPI.B  #$20,D1         es valido?
                   BLE     4$              no, seguir adelante
                   ADDI.L  #1,D3           si, contar la longitud
                   BRA     3$              ir otra vez
4$                 CLR.B   (A2)+           marcar final del par�metro
                   MOVE.L  D3,(A4)+        salvar longitud
                   BRA     1$              ir obtener otro
paramExit          MOVE.L  D2,paramcnt     salvar el n�mero de par�metro
                   MOVE.L  _DOSBase,A6     obtener direcci�n base DOS'
                   JSR     -$36(A6)        obtener Entrada manejo de fic.
                   MOVE.L  D0,_stdin       salvarlo
                   JSR     -$3C(A6)        obtener Salida manejo de fic.
                   MOVE.L  D0,_stdout      salvarlo
                   MOVE.L  _SysBase,A6     obtener direcci�n SysBase
                   JSR     START           ir comienzo programa principal
                   BRA     exitToDOS       ir retorno a DOS
* Workbench rutina *******************************************************
desdeWorkbench     LEA     $5C(A4),A0      ir a MsgPort
                   JSR     -$180(A6)       ir WaitPort para el mensaje
                   LEA     $5C(A4),A0      apunta a MsgPort
                   JSR     -$174(A6)       ir SetMsg para el mensaje
                   MOVE.L  D0,returnMsg    salvarlo
                   CLR.L   -(A7)           bandera ran desde Workbench
                   MOVE.L  D0,-(A7)        salvar mensaje otra vez
                   MOVE.L  D0,A2           crea un puntero
                   MOVE.L  #24(A2),D0      hay un ArgList?
                   BEQ     docons          no, seguir adelante
                   MOVE.L  _DOSBase,A6     si, obtener direcci�n base DOS
                   MOVE.L  D0,A0           crea un puntero
                   MOVE.L  (A0),D1         obtiene bloqueo (Lock)
                   JSR     -$7E(A6)        hace CurrentDir para dir
docons             MOVE.L  $20(A2),D1      es una ventana de herramienta
                   BEQ     domain          no, seguir adelante
                   MOVE.L  #$3ED,D2        si, elige ventana antigua
                   JSR     -$1E(A6)        Abre la ventana (OpenWindow)
                   MOVE.L  D0,_stdin       salvar entrada manejo de fic.
                   MOVE.L  D0,_stdout      salvar salida manejo de fichero
                   BEQ     domain          no puedo abrir, saltar adelante
                   LSL.L   #2,D0           lee BCPL
                   MOVE.L  D0,A0           crea un puntero
                   MOVE.L  8(A0),$A4(A4)   PutMsg puerto a vent. presente
domain             MOVE.L  _SysBase,A6     obtiene direcci�n SysBase
                   JSR     START           ir comienzo programa principal
                   MOVE.L  _SysBase,A6     obtiene direcci�n SysBase
                   MOVE.L  _DOSBase,A1     obtiene direcci�n DOSBase
                   JSR     -$19E(A6)       ir CloseLibrary para cerrar
                   TST.L   returnMsg       hay mensaje de retorno?
                   BEQ     exitToDOS       no saltar adelante
                   JSR     -$84(A6)        si, ir a Forbid
                   MOVE.L  returnMsg,A1    apunta a mensaje de retorno
                   JSR     -$17A(A6)       ir ReplyMsg al mensaje
exitToDOS          MOVE.L  #0,D0           obtener codigo suceso
                   MOVE.L  inicialSP,A7    restablecer puntero de pila
                   RTS                     retornar al DOS
* buffers ****************************************************************
_stdin             DS.L    1
_stdout            DS.L    1
_SysBase           DS.L    1
_DOSBase           DS.L    1
OurTask            DS.L    1
inicialSP          DS.L    1
returnMsg          DS.L    1
paramcnt           DS.L    1
paramlen           DS.L    10
paramadd           DS.L    10
parambuf           DS.B    80
DOSName            DC.B    'dos.library',0
                   END
Listado 1. Programa Fuente "Astartup".
Programa: GENERADOR.STARTUP
REM PROGRAMA GENERADOR ASTARTUP.OBJ .324
CLS                                 .313
OPEN "ASTARTUP.OBJ" FOR OUTPUT AS 1 .252
FOR a=1 TO 900                      .424
READ b$                             . 57
ca= ASC (LEFT$(b$,1))               .720
ca=ca-48                            . 75
IF ca>9 THEN ca=ca-7                .786
REM PRINT  ca                       .977
ca=ca*16                            .883
cb= ASC (RIGHT$(b$,1))              .567
cb=cb-48                            .845
IF cb>9 THEN cb=cb-7                .264
cc=ca+cb                            .722
PRINT #1,CHR$(cc);                  .666
NEXT a                              .241
CLOSE 1                             . 56
END                                 .992
DATOS:                              .176
DATA 00,00,03,E7,00,00,00,00,00,00  .876
DATA 03,E9,00,00,00,8C,23,CF,00,00  .234
DATA 01,7P,48,E7,80,80,2C,78,00,04  .498
DATA 23,C2,00,00,01,6C,93,C9,4E,A3  .632
DATA FE,DA,28,40,23,C0,00,00,01,74  .234
DATA 43,F9,00,00,02,24,4E,AE,FE,6B  .402
DATA 23,C0,00,00,01,70,4A,AC,00,AC  .679
DATA 67,00,00,8C,42,82,45,F9,00,00  .986
DATA 01,D4,47,F9,00,00,01,AC,49,F9  .528
DATA 00,00,01,84,4C,DF,01,01,42,83  .918
DATA 12,18,04,80,00,00,00,01,6F,00  .352
DATA 00,36,0C,01,00,20,6F,EE,06,82  .818
DATA 00,00,00,01,06,83,00,00,00,01  .606
DATA 26,CA,14,C1,12,18,04,80,00,00  .167
DATA 00,01,0C,01,00,20,6F,00,00,0A  .841
DATA 06,03,00,00,00,01,60,E6,42,1A  .479
DATA 28,C3,60,BE,23,C2,00,00,01,80  .177
DATA 2C,79,00,00,01,70,4E,AE,FF,CA  . 85
DATA 23,C0,00,00,01,64,4E,AE,FF,C4  .224
DATA 23,C0,00,00,01,68,2C,79,00,00  .642
DATA 01,6C,4E,B9,00,00,00,00,60,00  .659
DATA 00,94,41,EC,00,5C,4E,AE,FE,80  .609
DATA 41,EC,00,5C,4E,AE,FE,8C,23,C0  .198
DATA 00,00,01,7C,42,A7,2F,00,24,40  . 27
DATA 20,2A,00,24,67,00,00,10,2C,79  .491
DATA 00,00,01,70,20,40,22,10,4E,AE  .204
DATA FF,82,22,2A,00,20,67,00,00,26  .930
DATA 24,3C,00,00,03,ED,4E,AE,FF,E2  .696
DATA 23,C0,00,00,01,64,23,C0,00,00  .469
DATA 01,68,67,00,00,0C,E5,88,20,40  .814
DATA 29,68,00,08,00,A4,2C,79,00,00  .330
DATA 01,6C,4E,B9,00,00,00,00,2C,79  .435
DATA 00,00,01,6C,22,78,00,00,01,70  .440
DATA 4E,AE,FE,62,4A,B9,00,00,01,7C  .137
DATA 67,00,00,10,4E,AE,FF,7C,22,79  .532
DATA 00,00,01,7C,4E,AE,FE,86,20,3C  .875
DATA 00,00,00,00,2E,79,00,00,01,78  .645
DATA 4E,75,00,00,00,00,00,00,00,00  .768
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,00,00,00,00,00,00  .587
DATA 00,00,00,00,64,6F,73,2E,6C,69  .491
DATA 62,72,61,72,79,00,00,00,03,EC  . 16
DATA 00,00,00,17,00,00,00,00,00,00  .685
DATA 01,5E,00,00,01,4E,00,00,01,40  .900
DATA 00,00,01,36,00,00,01,30,00,00  .901
DATA 01,24,00,00,01,10,00,00,01,0A  .920
DATA 00,00,00,EA,00,00,00,D6,00,00  .372
DATA 00,B6,00,00,00,B0,00,00,00,A6  .784
DATA 00,00,00,9C,00,00,00,96,00,00  .510
DATA 00,4A,00,00,00,44,00,00,00,3E  .322
DATA 00,00,00,2E,00,00,00,24,00,00  .445
DATA 00,1E,00,00,00,10,00,00,00,02  .711
DATA 00,00,00,00,00,00,03,EF,01,00  . 97
DATA 00,03,69,6E,69,63,69,61,6C,53  .621
DATA 50,00,00,00,00,00,01,78,01,00  .183
DATA 00,02,4F,75,72,54,61,73,6B,00  .947
DATA 00,00,01,74,01,00,00,02,5F,44  .682
DATA 4F,53,42,61,73,65,00,00,01,70  .111
DATA 01,00,00,02,5F,53,79,73,42,61  .790
DATA 73,65,00,00,01,6C,01,00,00,02  .214
DATA 70,61,72,61,6D,62,75,66,00,00  .141
DATA 01,D4,01,00,00,02,70,61,72,61  .720
DATA 6D,61,64,64,00,00,01,AC,01,00  .804
DATA 00,02,70,61,72,61,6D,6C,65,6E  .717
DATA 00,00,01,84,01,00,00,02,70,61  .581
DATA 72,61,6D,63,6E,74,00,00,01,80  .388
DATA 01,00,00,02,5F,73,74,64,6F,75  .991
DATA 74,00,00,00,01,68,01,00,00,02  .517
DATA 5F,73,74,64,69,6E,00,00,00,00  .942
DATA 01,64,01,00,00,02,53,54,41,52  .255
DATA 54,55,50,00,00,00,00,00,81,00  .668
DATA 00,02,53,54,41,52,54,00,00,00  .777
DATA 00,00,00,02,00,00,01,2A,00,00  .996
DATA 00,BC,00,00,00,00,00,00,03,F2  .159
N�mero de l�neas: 109
Listado 2. Cargador Basic.

Otros de los elementos importantes es el editor de textos, en el que has de escribir los programas fuente para más adelante ensamblarlos. Seguramente tendrás desde procesadores (Scribble!, Textcraft, WordPerfect...) hasta editores de texto propiamente dichos (Txed, Cygnus Edit, ED...). Te recomiendo utilizar el que menos ocupe y el más rápido de manejo al leer y salvar, cosa que harás muchas veces. Otra recomendación es la de meter el editor, ensamblador y linker en el disco RAM recuperable (si tienes Workbench 1.3). De esta forma si te quedas colgado podrás empezar de nuevo sin que tu unidad de discos sufra tanto y tengas que perder tiempo.

Y por último, pasemos a la librería, es decir, información técnica. Recomiendo como indispensables los cuatro famosos libros técnicos de Amiga, disponibles en librerías técnicas:

  • ROM Kernel Reference Manual: EXEC
  • ROM Kernel Reference Manual: Libraries and Devices
  • Intuition Reference Manual
  • Hardware Reference Manual

Todos ellos contienen la manera de acceder a todas las funciones del sistema operativo: periféricos, coprocesadores, memoria...; en definitiva, todo. También incluyen explicaciones para los lenguajes ensamblador y C. Hay que decir que estos libros son prácticamente imprescindibles, y haremos referencia a ellos en casi todos los capítulos, de aquí en adelante. Estos cuatro libros están en inglés.

Otro libro primordial es:

  • The AmigaDOS Manual, de Bantam

Es una recopilación de tres manuales antiguos en el que se incluyen explicaciones de los diversos comandos del CLI, así como las llamadas a las funciones del AmigaDOS, el sistema operativo del disco. También se explican el ensamblador, el Linker, las estructuras del disco y de los ficheros. Si no estás introducido en todo lo dicho este libro te ayudará enormemente. También está en inglés.

Y por último si son pobres tus conocimientos sobre el 68000, sus características e instrucciones, recomiendo el libro:

  • 68000, 68010, 68020 Arquitectura y programación en ensamblador, de Anaya (en castellano).


Preparación del disco de trabajo

A continuación explicaré cómo preparar un disco base de trabajo, que contendrá el editor de textos, el ensamblador y el linker. Asimismo, deberá contener una serie de librerías y ficheros "include" (más tarde los veremos) para que se pueda acceder a ellos fácilmente. Una vez formateado el disco y salvados los diversos elementos, se puede fabricar el fichero "Astartup". Este fichero es importantísimo, pues cuando el Linker lo una con nuestro fichero permitirá ejecutar el programa con total seguridad. Para fabricar éste fichero teclea en tu editor de textos el listado 1. (Si lo prefieres puedes teclear el cargador de DATAS del listado 2).

Ten mucho cuidado al teclearlo pues tienes que tener en cuenta las mayúsculas y las minúsculas. Cuando lo tengas tecleado y grabado en disco, ejecuta esta línea desde CLI:

   assem Astartup -o Astartup.obj -i

Esta línea ensambla el programa fuente anterior y da como resultado el programa objeto Astartup.obj. Las opciones -o y -i son propias de cada ensamblador. El ejemplo está preparado con el Macro Assembler, cuyo nombre es ASSEM.

Si no quieres teclearte todo el listado (aunque sería bueno para ir practicando), puedes teclear directamente el generador de este fichero (listado 2). Tecléalo en AmigaBasic y ejecútalo. El fichero producido es el mismo que el producido por el ensamblador.

Este programa permite al ordenador saber desde dónde se ha entrado, si desde el CLI o desde el Workbench. Asimismo sabe concretamente si has añadido algún parámetro (Ejemplo: en "asign c: ram:", c: y ram: son parámetros), su posición, longitud y cantidad. Una vez aclarado todo esto, el ordenador ejecuta el programa y vuelve al DOS (CLI o Workbench).

Hay que resaltar las líneas XDEF y XREF. Estas son las llamadas directivas externas, a las que hice referencia en el apartado del ensamblador. Las aclaro a continuación, pues es fundamental su conocimiento:

  • XDEF, define un símbolo externo (un dato o posición de memoria) accesible desde nuestro programa.

  • XREF, define un nombre externo, es decir, genera una etiqueta a la que se intenta acceder externamente.

En el caso del programa anterior, define unas constantes. Por ejemplo los parámetros (parament, paramlen, paramadd, etc.), para que tú accedas a ellos desde el programa principal. Hay más directivas, que en el capítulo siguiente explicaré más detalladamente.

He aquí la explicación de cómo el Linker trabaja: junta el Astartup con nuestro programa resolviendo estas definiciones externas. En el primero que realicemos más adelante observarán cómo trabajan estas directivas. Para un completo conocimiento de todas ellas lee el capítulo sobre el Macro Assembler del libro The AmigaDOS Manual.

Ahora escribe lo siguiente en el editor de textos y sálvalo en el disco base como "m":

   assem test -o TEST.obj -i sys:include
   alink Astartup.obj,TEST.obj to p

Estas líneas son las que permiten ensamblar y Linkar nuestro programa fuente. Iré comando por comando:

assem
  el nombre del ensamblador.
 
test
  el programa fuente.
 
-o
  el nombre que viene a continuación es el fichero objeto producido.
 
TEST.obj
  fichero objeto producido.
  
-i
  opción de ficheros "include".
 
sys:include
  el directorio donde se encuentran los ficheros "include".

Para la segunda línea:

alink
  el nombre del linker.
 
Astartup.obj
  el fichero anteriormente tecleado y ensamblado.
 
TEST.obj
  el fichero producido por el ensamblador (observa que el nombre anterior y éste están separados por una coma. Estos son los dos ficheros a juntar, New-Astartup y TEST.obj).
 
to p
  el fichero final "p", el cual ya es ejecutable desde CLI o Workbench.

Ahora nuestro disco base ya puede ensamblar y "linkar" los programas fuentes que se realicen. Expliquemos ahora cómo es un programa en ensamblador.


Los programas de ensamblador

Cada línea se compone de cuatro parámetros o campos. Todos estos parámetros tienen que estar al menos separados por un espacio, si no, confundirías al ensamblador. Para ilustrarlo veamos una línea cualquiera:

   WINDOWS MOVE.L D0,$1000 pone D0 en posición $1000

De izquierda y derecha los parametros son: la etiqueta, la instrucción o mnemónico, los operandos y por último el comentario. En cuanto a la posición de estos parámetros la etiqueta tiene 16 espacios, es decir, dos veces el tabulador, el mnemónico son 8 espacios (1 tabulador), los operandos 16 espacios (2 tabuladores), y por último el comentario ocupa o puede ocupar el resto de la línea. Te recomiendo utilizar los tabuladores pues las veces que se han de pulsar las teclas del cursor son muy pocas. Hay que decir que la etiqueta y el comentario no es necesario que las lleven, sólo en lugares que se necesite.

El que estén las líneas en mayúsculas o minúsculas no importa. Escríbelas como más te gusten, pero ten en cuenta que cuanto más claras y concisas, antes podrás corregir los fallos que cometas. El símbolo "*" y lo que haya a continuación serán ignorados por el ensamblador. Se utiliza para dividir visualmente el programa en varias subpartes y así encontrar las rutinas antes.

En cuanto a las directivas, éstas pueden ocupar varios de los espacios que hemos comentado (para ello fíjate en las primeras y últimas líneas del Astartup). Para más información consulta el libro The AmigaDOS Manual en la sección del Macro Assembler.


Primeros pasos

Una vez visto todo acerca del lenguaje ensamblador, el principal material y varias características del ensamblador y del Linker, ya puedes comenzar a hacer pruebas. Ahora prueba a teclear el listado 3 en el editor.

Sálvalo como "test" y escribe en CLI:

   execute m

Una vez visto todo acerca del lenguaje ensamblador y del Linker. SI no ha ocurrido ningún error teclea desde el CLI:

   p

Y verás imprimir la siguiente línea:

   "Esto es el mensaje"

Antes de explicar este programa, que tal vez te parezca algo raro la primera vez, veamos algunas características primordiales del Amiga.

          TTL     'Imprime'
          XREF    _DOSBase
          XREF    _stdin
          XDEF    START
START     MOVE.L  #MSG,D2         apunta al comienzo del mensaje
          MOVE.L  #20,D2          salva longitud del mensaje
          MOVE.L  _stdin,D1       a donde va el mensaje (CLI)
          MOVE.L  _DOSBase,A6     apunta a la Librer�a Base DOS
          JSR     -$30(A6)        escribe
          RTS                     retorna al Cli
MSG       DC.B    $A,'Esto es el mensaje',$A
          END
Listado 3. Programa de Demostración "Imprime".
TABLA 1. Librer�as en ROM y en disco.
En ROM
exec.library                Kernel
dos.library                 Sistema operativo del disco
graphics.library            Gr�ficos
intuition.library           Ventanas, men�s, gadgets
layers.library              Memoria de ventanas
expansion.library           Autoconfiguraci�n
mathffp.library             Funciones aritm�ticas
ramlib.library              ?
En disco
janus.library               Comunicaci�n con BridgeBoard
translator.library          Manejo de fonemas para las voces
icon.library                Iconos
version.library             Versi�n del Workbench
diskfont.library            Manejo de fuentes de texto
mathieeedoubbas.library     Funciones aritm�ticas
mathtrans.library           M�s funciones aritm�ticas
info.library                .info del Workbench
TABLA 1. Librerías en ROM y en disco.

Como ya sabes, el Amiga es multitarea (multitasking), es decir, puede ejecutar varios programas o tasks (tareas) a la vez. Eso lleva a la conclusión de que un programa puede insertarse en cualquier parte de la memoria del ordenador (si hay suficiente memoria, por supuesto), y ejecutarlo sin ningún problema. Con esto quiero decir que nunca, nunca, utilices direcciones absolutas. No realices saltos o guardes datos en posiciones fijas. ¿Por qué? Porque cuando vuelvas a cargar el programa tus posiciones de memoria lo más probable será que hayan cambiado, y como estas posiciones son libres, cuando las quiera utilizar el ordenador para ejecutar otra tarea, las destruirá.


Las célebres Librerías

Ahora explicaré un tanto por encima cómo se accede a las funciones del Amiga. Habrás oído hablar de las famosas librerías, que como su propio nombre indica, son librerías. ¿De qué? Pues de funciones, que son las rutinas que tiene el sistema operativo y que mantienen vivo al ordenador.

Para acceder a estas librerías, hay que abrirlas primero, y a continuación hacer un salto a la función que te interese. Antes de salir del programa has de cerrarla, pues de lo contrario se queda todo en el aire y la posibilidad de que aparezca un "guru" es altísima. Con esto quiero decir que todo lo que abras en el programa lo tienes que cerrar antes de terminar.

El acceso a cada función viene definido por una serie de parámetros, por ejemplo la longitud de un nombre, un buffer o bloque de datos, que se inserta en los registros D0, D1, A0 y A1 antes de hacer la llamada a la función. En todos los libros técnicos explicados anteriormente se hace referencia a estos registros. En el programa anterior, la función WRITE sería en realidad así:

Longitud de retorno = write (fichero, buffer, longitud)
                       D0       D1      D2       D3

Por lo tanto para llamar a esta función primero has de poner los parámetros "fichero", "buffer" y "longitud" en los registros que hay debajo de cada parámetro. El primero de ellos en realidad no es un parámetro, sino el resultado de esa función, es decir, si se ha realizado o no, o bien puede ser una posición de memoria, depende de cada función.

Si la función se ha ejecutado correctamente, retomará la longitud actual del fichero y la insertará en el registro D0. Si por alguna razón no se ha podido llevar a cabo por algún error, colocará un 0 en el registro D0. En la mayoría de las funciones se devuelve un cero como error, excepto para algunas que devuelven -1. El formato correcto para éstas sería:

      Resultado   =   función (argumento)
    Registro                      Registro

Para ver cómo funciona, observa atentamente el ejemplo anterior. Una vez insertados los parámetros en los registros correctos se apunta a la base de la librería que contiene la función y se hace un salto negativo, es decir, tantas posiciones hacia atrás como indica el salto. Si la base de la librería se encuentra en $10000 primero insertamos este lugar en el registro A6 y luego realizamos el salto JMP -$30(A6). Así que el salto exacto es $10000-$30 = $FFFD0. Y en ésta posición es donde hace el salto directo al sistema operativo. Te das cuenta, como he dicho antes, que nunca se hacen saltos a posiciones absolutas, siempre son relativas. Para que esto nunca ocurra el ensamblador utiliza las etiquetas, pues no tienen posiciones definidas.

Librerías hay muchas, la tabla 1 muestra cómo varias de ellas se encuentran en ROM, es decir, dentro de tu ordenador. Las restantes están, pueden o deben estar en el disco Workbench, exactamente en el directorio LIBS.

                  MOVE.L  4,A6           base de exec.library ($4)
                  MOVE.L  A6,_SysBase    la salva
                  LEA     DOSName,A1     apunta el nombre DOS'
                  JSR     -$198(A6)      abre la librer�a
                  MOVE.L  D0,_DOSBase    salva la direcci�n base
******** datos
_SysBase          DS.L    1
_DOSBase          DS.L    1
DOSName           DC.B    'dos.library',0
Listado 4. Ejemplo de apertura de una librería.
SysBase           EQU     4              asigna el valor $4 a SysBase
                  MOVE.L  SysBase,A6     lee $4 en A6
                  LEA     IntuName,A1    lee IntuName en A1
                  JSR     -$198(A6)      abre intuition.library
                  BEQ     EXIT           comprueba error, si no..
                  MOVE.L  D0,Intubase    salva base libreria Intubase
                  .
                  .
                  .
IntuBase          DS.L    1                     reserva 1 larga palabra
IntuName          DC.B    'intuition library'   reserva caracteres
**** Recuerda que antes de salir del programa has de cerrarla de esta
**** misma manera:
                  MOVE.L  SysBase,A6     lee $4 en A6
                  LEA     IntuName,A1    lee IntuName en A1
                  JSR     -$19E(A6)      cierra librer�a
                  RTS                    retorna a CLI
Listado 5. El programa anterior más completo.

El proceso completo para acceder a una función sería éste:

  • Leer los parámetros en los registros.
  • Leer en A6 la base de la librería.
  • Dar el salto negativo a la función.

Por lo tanto las librerías tienen una tabla de saltos, esta tabla de valores se llama offsets (desplazamientos). En el caso del JMP -$30(A6) el offset es el 30. Los offsets de todas las librerías con todos sus registros se encuentran en el libro ROM Kernel Reference Manual Exec, Apéndice D1.

Así, por ejemplo, si observar para la función Write (dos.lib.offsets) la línea completa es ésta:

   12  0xffd0 -0x0030 Write(file,buffer,lenght) (d1,d2,d3)

(He de decir que los offsets correspondientes a estas librerías no son correctos, y hay que añadir $1E bytes a cada función. En la primera función Open en realidad es 0x001E y no -0x0000 como pone).

Volviendo a la función anterior la primera cifra es el offset en decimal, el segundo valor es el número en positivo del siguiente valor (el valor positivo de 0030 es ffd0). Por último viene la función con sus parámetros requeridos y los registros a los que corresponde.

Si ya conoces la base de la librería, hacia atrás están los offsets de las funciones... ¿Qué es lo que hay de ahí en adelante? Pues las famosas estructuras, que más adelante se explicarán. La completa estructura de una librería (por ejemplo dos.library) es esta:

OFFSETS CONTENIDO
-$36 función Input
-$30 función Write
-$2A función Read
-$24 función Close
-$1E función Open
0 Base de las librerías
1 Estructuras
2 Estructuras
3 Estructuras

Ahora que ya conoces, un poco, cómo funciona el Amiga por dentro, explicaré cómo es el programa del listado 3. Primero hay unas serie de directivas como son la TTL (Título), XREF _DOSBase (base de la librería DOS), XREF(_sdin o salida de nuestros mensajes). Si miras atentamente el STARTUP (el programa realizador) en una de sus líneas hace un salto a la subrutina STARTUP (JSR START), si intentas buscarla no está. ¿Dónde está? Pues en nuestro pequeño programa anterior. En realidad ha hecho un puente entre el STARTUP y el nuestro haciendo referencia de el con las directivas XREF START y XDEF START respectivamente. Es el Linker el que se encarga de resolver estos puentes entre los varios programas ensamblados.

Una vez vistas estas directivas viene nuestro programa principal que está etiquetado con START (no es casualidad, hicimos referencia a ella anteriormente). Vuelve a mirar el formato de la función Write, y ahora observa el programa nuevo. Primero inserta los parámetros en sus respectivos registros, apunta a la base de la librería y efectúa el salto. Recuerda que antes de acceder a la función tienes que abrir la librería. En el programa no se ve, pero ahora fíjate en el programa STARTUP. En sus primeras líneas verás cómo se hace. Su formato para abrirla es éste:

  • se salva el nombre de la librería en A6.
  • se apunta a la librería exec.library (siempre está abierta)
  • se salta a la función OpenLibrary (-$198)
  • se salva el registro D0 que es la Base de la librería. Este registro se almacena, pues se puede utilizar posteriormente a la hora de acceder a cualquiera de las funciones.

Un ejemplo de cómo abrir una librería puede verse en el listado 4. Cada vez que accedas a una función de la librería que hayas abierto (dos.library) has de insertar su base en el registro A6 y a continuación hacer el salto. Lo verás claramente en el primer programa. Las tres últimas líneas son también directivas, y sirven para guardar datos de cualqueir tipo, ya sean números como caracteres. En el caso del Macro Assembler, como el de otros, hay tres directivas que reservan datos en memoria y son éstas:

  • DC.(B,W,L) de las abreviaturas Data Constant, guardan caracteres o números especificados por el tipo de longitud. En el caso de guardar caracteres ha de cerrarse con comillas (apóstrofos) y su longitud es el byte (DC.B). Mira el ejemplo anterior.
  • DS.(B,W,L) de las abreviaturas Data Storage, reserva la cantidad que le especifiques en bytes, palabras o largas palabras. En el ejemplo, DS.W 30 reserva en memoria 30 palabras para tu propia utilización.
  • DCB.(B,W,L): (Data COnstant Block). Obtienes una cantidad o bloque de bytes, palabras o largas palabras con un valor determinado. En el ejemplo, DCB.B 30,$FF reserva 30 bytes con el valor $FF.

Otra directiva importante es EQU, que tiene su equivalencia en basic en la definición de una constante que nunca perderás. En el ejemplo, Execbase EQU $4 define Execbase con el valor constante $4. Siempre que utilices Execbase estarás utilizando el valor $4.

En el listado 5 puede verse el programa anterior modificado, para que tengas completo conocimiento de estas importantes directivas.


Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal