Revistas en papel
 Amiga World Nº12 - Julio/Agosto 1990
Anterior
Menú
Logotipo

El Amiga Me Encanta ha conseguido el permiso por escrito de IDG Comunications España
para ofrecer los artículos de la revista Amiga World España.

ENSAMBLADOR DESDE EL BASIC Amiga World

Por Bryan Catley

¿Sus programas Basic necesitan mayor velocidad? COn la incorporación de rutinas en lenguaje máquina en sus listados Basic podrá conseguir un mayor aumento en la velocidad del programa. El Basic es un lenguaje interpretado, y por tanto lento por naturaleza. Los programas que consiguen una mayor velocidad en su ejecución son los escritos en lenguaje Ensamblador, traduciéndose éstos posteriormente (línea por línea) a código máquina. Para la realización de estas operaciones existen programas ensambladores, los cuales se encargan de traducir el listado ensamblador (fuente) en objeto (código máquina). Por tanto si usted necesita realizar gran cantidad de operaciones, podrá considerar la inclusión de una rutina en Ensamblador para mejorar la tarea.

Con el AmigaBasic, una vez se encuentre en memoria la rutina, podrá invocar a ésta de igual forma que realiza una llamada a una librería o a un sub-programa Basic:

CALL miMLrutina(param-1,...,param-n)

Note que puede pasar parámetros a la rutina.

Primero necesitará importar una rutina en ensamblador. Un buen ejemplo, es la incluida en el capítulo 6 de su manual Amiga Basic. Esta no es ni muy grande ni muy pequeña; además utiliza tanto cadenas de caracteres como parámetros numéricos. La rutina acepta una cadena de caracteres, pasando todos aquellos que estén en minúsculas a mayúsculas.

Usted tiene dos opciones para introducir el código del lenguaje máquina. El primer método es el más tradicional, siendo satisfactoria para pequeñas rutinas introducidas en sentencias DATA. El segundo método es el mejor para aquellas rutinas que sean más largas, las cuales son cargadas directamente de disco.


Viejas formas de trabajo

La forma tradicional necesita que el código máquina sea introducido en sentencias DATA, leyéndolas posteriormente con la instrucción del Amiga Basic READ para introducir los datos en memoria. La rutina empleada será parecida a la siguiente:

Código$=""
Lontitud%=20
FOR n=1 TO Longitud%
Read x$
x$="&H"+x$
Código$=Código+CHR$(VAL(X$))
NEXT
DATA 48,E1,C0,80,...
Rutina&=SADD(Código$)
CALL Rutina&

El código es
leído y pokeado
de dos bytes en
dos bytes; con lo
cual se gana
velocidad y se
conserva la
paridad en el
direccionamiento
de memoria.

Dicha rutina consigue buenos resultado, pero ésta sólo podrá ejecutarse una vez.

La razón es muy sencilla. Cuando el AmigaBasic aloja memoria para Código$ (o una variable alfanumérica), ésta no se encontrará en la posición contigua. Si la reservación de memoria falla, y ésta se sitúa sobre una dirección impar, al almacenar el código ejecutándolo posteriormente, se recibirá como respuesta un GURU #3 (Direccionamiento) error de direccionamiento.

Para solucionar este problema, sólo tendrá que utilizar la rutina incluida en la librería AllocMem; la cual reserva memoria en una dirección par. A continuación sólo tendrá que 'pokear' los datos de la rutina en la dirección devuelta en la variable utilizada al hacer la llamada de la rutina. Por ejemplo:

LIBRARY "exec.library"
DECLARE FUNCTION AllocMem& LIBRARY
Area&=AllocMem(56,1)
FOR n%=0 to 27
READ xNUM$
POKEW
Area&+n%,VAL("&H"+xNum$)
NEXT
DATA 48E7,C080,202F,0010,206F,0014
DATA 4281,6000,001C,1230,0000,0C01
DATA 0061,6D00,0010,0C01,007A,6E00
DATA 4CDF,0103,4E75,0000
IMPUT "Introduzca una cadena con mayúsculas y minúsculas",s$
strLong&=LEN(s$)
strDir&=SADD(s$)
CALL Area&)strLong&,strDir&)
PRINT "Valor convertido es:";s$;""
CALL FreeMem (Area&,56)
LIBRARY CLOSE
END

La rutina en Lenguaje Máquina ha sido extraida del manual; igual que en el manual, la anterior rutina funciona de una forma consistente. Note las diferencias: el código es leído y pokeado de dos bytes en dos bytes; con lo cual se gana velocidad y se conserva la paridad en el direccionamiento de memoria. Se realiza la llamada a la rutina mediante la función CALL y la dirección de inicio. Como parámetros a la rutina, se pasan la longitud de la cadena (en formato de doble palabra) y la dirección en memoria de la misma.

Este método no resulta muy efectivo si se trata de rutinas demasido largas. Después de todo, el código ha sido almacenado en el programa mediante las sentencias DATA; teniendo que leer éste posteriormente mediante la instrucción READ y almacenado en memoria. Un problema más serio es que todas las direcciones deben ser relativas al contador de programa (Directamente relativo PC), debido a que el sistema no ve dónde se encuentra la rutina. La solución se encuentra en el uso de un sistema para leer la rutina de disco, así como estructurar todos los alojamientos de la misma y observar el direccionamiento relativo.


Servicios del Sistema

El único propósito de la función LoadSeg, incluida en la dos.library, es la de cargar código máquina desde el disco y preparar ésta para su ejecución. La única restricción es que el código deberá ser cargado en formato de módulo. Para utilizar el método del LoadSeg, necesitará acceder a un ensamblador y a un linkador. Otra restricción de esta función es que no devuelve la dirección de ejecución de la rutina, sino que se limita a facilitar el número de dobles palabras de la que consta el código. De esta forma el programa deberá realizar un pequeño cálculo con el cual determinar la dirección de ejecución de la rutina. Utilice la siguiente rutina como guía:

pgmNombre="ML"+CHR$(0)
pgmPtr&=LoadSeg&(SADD(pgmName$))
Code&=pgmPtr&*4
Code&=Code&+4
CALL Code&

Cuando no vaya a utilizar la rutina, libere ésta mediante la siguiente llamada:

CALL UnloadSeg(pgmPtr&)

Mediante un ensamblador y un linkador, introduzca la rutina que figura en su manual; ensamblando esta y posteriormente linkándola. Para grabar la misma podrá utilizar el nombre que desee, en este caso yo la he llamado Ucase.exe. A continuación introduzca el siguiente listado y ejecútelo, asegurándose interiormente de que la rutina se encuentra grabada en el mismo directorio.

Esta rutina deberá funcionar exactamente como el anterior ejemplo, con la excepción de que las sentencias DATA (las cuales contenían la rutina), han sido sustituidas por la carga de la rutina en modo modular.

DECLARE FUNCTION LoadSeg& LIBRARY
LIBRARY "dos.library"
loadModule$="Ucase.exe"+CHR$(0)
pgmPtr&=LoadSeg&(SADD(loadModule$))
IF pgmPTR&=0 THEN
PRINt "LoadSeg Failled"
GOTO Quit
END IF
Ucase&=pgmPtr&*4+4
IMPUT "Introduzca una cadena con mayúsculas/minúsculas:",s$
strLength&=LEN(s$)
strAddr&=SADD(s$)
CALL Ucase&(strLength&,strAddr&)
PRINT "Valor convertido:";s$;""
UnloadSeg pgmPtr&
Quit:
LIBRARY CLOSE
END

Usando estas técnicas, usted podrá realizar de una forma sencilla la inclusión de sus propias rutinas en código máquina desde el Basic.


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