Como dije en el anterior blog voy a pasar a integrar totalmente el TASM 2.0. Por ello, eliminaré de mis macros las directivas, creadas para imitar las del TASM 2.0. cuando programaba sobre ASM.
Si se quiere seguir compilando los programas que coloque a partir de ahora, se deberán actualizar las cabeceras para que sean compatibles con las nuevas directivas de TASM 2.0 y posteriores.
Para empezar, a partir de ahora usaremos las directivas .CODE, .STACK, . DATA y .MODEL.
Adaptarnos a esto es muy simple. Basta con eliminar de la cabecera MAIN.MAC las equivalentes _modelo, _stack, _data y _code, QUE YA NO SON NECESARIAS.
Un poco más difícil es adaptarnos al cambio de definición de los procedimientos.Veamos.
HASTA AHORA
- DEFINICIÓN DE MACRO. En la cabecera una definición de función desde la cual llamaba a la subrutina. Ejemplo strcmp
strcmp macro destino,fuente ;orden de push inverso al orden de parametros en la macro
ifndef _strcmp
extrn _strcmp:near
endif
lea ax,fuente
push ax
lea ax,destino
push ax
call _strcmp
pop ax ;sacamos los datos de pila en la macro
pop ax
endm
La macro pasa los datos a la subrutina y saca de pila los datos después al regreso.
- DEFINICIÓN DE FUNCIÓN. En la rutina usábamos las directivas propias en vez de las de TASM 2.0 y en particular rutina para crear el paso de parámetros.
include main.mac
extrn _strlen:near
_modelo exe
_code
rutina _strcmp destino,fuente
PUSH SI ;salvaguarda manual de los registros
PUSH DI
PUSH ES
PUSH DS
POP ES
MOV SI,[BP].destino ;acceso a los parámetros a traves del puntero de pila
MOV DI,[BP].fuente
CLD
MAS: CMPSB
jne final
CMP BYTE PTR [SI-1],0
JNZ MAS
final:
POP ES
POP DI
POP SI
rutina_end ; no ponemos ret, por estar incorporado en rutina_end
_data
_end
extrn _strlen:near
_modelo exe
_code
rutina _strcmp destino,fuente
PUSH SI ;salvaguarda manual de los registros
PUSH DI
PUSH ES
PUSH DS
POP ES
MOV SI,[BP].destino ;acceso a los parámetros a traves del puntero de pila
MOV DI,[BP].fuente
CLD
MAS: CMPSB
jne final
CMP BYTE PTR [SI-1],0
JNZ MAS
final:
POP ES
POP DI
POP SI
rutina_end ; no ponemos ret, por estar incorporado en rutina_end
_data
_end
Mediante rutina creaba una estructura de parámetros en pila, que luego manejaba mediante [bp].nombre y salvaba el puntero de pila.
Una particularidad más este programa es que soy yo el que almacena y rescata los registros utilizados durante la función, mediante push al principio y pop al final del procedimiento.
Además al finalizar el programa rutina_end se encargaba de reponer el puntero de pila, y retronar. El retorno siempre era con ret, ya que no puedo conocer de antemano el número de parámetros enviados en rutina, y por lo tanto prefería sacar los datos de pila en la macro.
A PARTIR DE AHORA (TASM 2.0)
- DEFINICÓN DE MACRO. En la cabecera se seguirá creando una macro para llamar a la función de forma cómoda en la que aprovecharemos para pasar los parámetros a pila, pero no necesitamos sacarlos manualmente de pila pues el compilador ya realizará un ret xxx, con el número de parámetros que definamos. Por lo tanto el caso anterior quedará:
strcmp macro destino,fuente
ifndef _strcmp
extrn _strcmp:near
endif
lea ax,destino ;orden de envío a pila directo, en vez de inverso
push ax
lea ax,fuente
push ax
call _strcmp
; no sacamos datos de pila a la vuelta
endm
En la actualidad existe en el MASM 11 y el NASM la instrucción INVOKE, para realizar la llamada y almacenar los argumentos en pila. Pero, aunque ya no programo en ensamblado, estoy seguro que si lo hiciera, no la usaría. El problema del invoque, es que los programas quedan muy planos, al estar llenos de "invoke". Para leerlos hace fata ir saltandose los invokes de cada línea. La idea es buena,pero mal implementada. Es mejor como veréis usar una macro para cada instrucción, dado que el programa es más legible. Pero claro se han creado tantas librerías, que ahora resulta un engorro crear una macro para cada una. Pero eso lo arreglaré si decido llegar hasta el TASM11 en este blog. por ahora seguiré usando este formato.
RESUMIENDO
Esto se deberá hacer con todas las cabeceras y luego con todas las funciones que he publicado, de forma que se compilen y se almacenen en una nueva librería, que será la que se use a partir de ahora. A partir de ahora todas la rutinas que exponga serán compatibles con este nuevo método.
Hemos ganado algo de comodidad en la estructuración , al almacenar de forma automática los registros usados mediante uses. Pero sobre todo, con el .model hemos ganado posibilidades de compilación, pudiendo ahora hacer diferentes organizaciones de memoria y diferentes configuraciones de lenguajes. Es por esta razón por la que, aunque algunas directivas puedan simularse, hay que pasar al TASM 2.0.
ifndef _strcmp
extrn _strcmp:near
endif
lea ax,destino ;orden de envío a pila directo, en vez de inverso
push ax
lea ax,fuente
push ax
call _strcmp
; no sacamos datos de pila a la vuelta
endm
En la actualidad existe en el MASM 11 y el NASM la instrucción INVOKE, para realizar la llamada y almacenar los argumentos en pila. Pero, aunque ya no programo en ensamblado, estoy seguro que si lo hiciera, no la usaría. El problema del invoque, es que los programas quedan muy planos, al estar llenos de "invoke". Para leerlos hace fata ir saltandose los invokes de cada línea. La idea es buena,pero mal implementada. Es mejor como veréis usar una macro para cada instrucción, dado que el programa es más legible. Pero claro se han creado tantas librerías, que ahora resulta un engorro crear una macro para cada una. Pero eso lo arreglaré si decido llegar hasta el TASM11 en este blog. por ahora seguiré usando este formato.
- DEFINICIÓN DE FUNCIÓN. A su vez en la subrutina, en vez de usar mi macro rutina, utilizaré la directiva proc nombre user ...arg.... que gestiona a la vez el paso de parámetros y la salvaguarda de registros en pila. la rutina quedará ahora.
public _strcmp
extrn _strlen:near
.model compact,pascal
.code
proc _strcmp uses si di es ds,destino,fuente ; definición de registros a alvar y parámetros de paso por pila
MOV SI,destino
MOV DI,fuente
CLD
MAS: CMPSB
jne final
CMP BYTE PTR [SI-1],0
JNZ MAS
final:
ret ; colocamos el ret
_strcmp endp
end
extrn _strlen:near
.model compact,pascal
.code
proc _strcmp uses si di es ds,destino,fuente ; definición de registros a alvar y parámetros de paso por pila
MOV SI,destino
MOV DI,fuente
CLD
MAS: CMPSB
jne final
CMP BYTE PTR [SI-1],0
JNZ MAS
final:
ret ; colocamos el ret
_strcmp endp
end
Como se ve, he usado las directivas .code, .data, . model.
He definido el modelo como pascal, para poder utilizar mi tipo de definición de nombres (llamar a la rutina como la macro, pero con '_' delante.
Ya no salvo y recupero los registros. eso se lo dejo al TASM, indicándoselo mediante uses.
Uso el nombre del parámetro directamente, en vez de usar [bp].nombre, para acceder a él. Es el TASM el que hace la conversión y coloca el indexador [bp], que es ahora transparente para mi. Aunque si desensamblo lo veré. Igualmente es trasparente la salvaguarda y recuperación del bp.
Otra característica más actual es que aunque yo escriba ret, el compilador realizar ret xx donde xx lo coloca al número de bytes que ocupen los parámetros definidos en uses. Es por eso que ya no debemos sacar los parámetros de pila en la macro.
Un última cosa es que ahora es necesario hacer public de la rutina, ya que ya no se hace automáticamente al declararla.
RESUMIENDO
Esto se deberá hacer con todas las cabeceras y luego con todas las funciones que he publicado, de forma que se compilen y se almacenen en una nueva librería, que será la que se use a partir de ahora. A partir de ahora todas la rutinas que exponga serán compatibles con este nuevo método.
Hemos ganado algo de comodidad en la estructuración , al almacenar de forma automática los registros usados mediante uses. Pero sobre todo, con el .model hemos ganado posibilidades de compilación, pudiendo ahora hacer diferentes organizaciones de memoria y diferentes configuraciones de lenguajes. Es por esta razón por la que, aunque algunas directivas puedan simularse, hay que pasar al TASM 2.0.
No hay comentarios:
Publicar un comentario
Si tienes algún comentario, duda o sugerencia, o si quieres aportar algún código creado a partir de las librerías expuestas aquí, por favor, indícamelo.