Vistas de página en total

viernes, 9 de agosto de 2013

PASAMOS A INTEGRAR TASM 2.0

     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


     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.



  •   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
        


      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.