Vistas de página en total

martes, 21 de mayo de 2013

APROVECHANDO MAIN.MAC (Función FACTORIAL)

  Vamos ahora a pormenorizar un poco lo que hemos visto anteriormente.
  En el ejemplo de las rutinas de gráficos hemos visto como con un código inicial muy pequeño hemos generado un código más grande.
   ¿Pero que hemos hecho realmente?
  lo que hemos hecho es usar la pila como zona de paso de datos, es decir de interface entre la rutina y el programa que la llama. Pero para que no tengamos que estar contando los indices de pila y memorizando que el primero que metimos era el bp, el siguiente la dirección de retorno, el tercero el x, etc hemos usado una estructura.

Para ello vamos a ver otra rutina. En este caso parte de la librería MATH. La rutina de factorial.
Primero la vamos a ve generada con la estructura y luego con la macro rutina.

FAC.ASM (sin apoyarnos en main.mac)
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ;estructura  paso de parámetros a través de pila. 
_parametros struc
        _bp dw ?
        _ret dw ?
        p1  dw ?     ;;primer sumando
        p2  dw ?     ;;segundo sumando
        p3  dw ?     ;;resultado
        p4  dw ?
        p5  dw ?
        p6  dw ?
        p7  dw ?
        p8  dw ?
 ends

; codigo
code segment byte public 'code'
      assume cs:code,ds:data
      public _fac
      extrn _mult:near
_fac proc near
        push bp
        mov bp,sp
        push bx
        push di
        mov bx,[bp].p1 , indexación a través de la estructura para recoger el parametro p1
        mov di,[bp].p2
        mov word ptr [di],1
        mov word ptr [di+2],0
        mov word ptr aux,0
        mov word ptr aux+2,0
 otro:
        mov ax,[bx]
        cmp aux,ax
        jnz no
        mov ax,[bx+2]
        cmp aux+2,ax
        jz fin
     no:
        add aux,1
        adc aux+2,0
        push di
        push di
        mov ax,offset aux
        push ax
        call _mult
        add sp,6
        jmp otro
   fin:
        pop di
        pop bx
        pop bp
        ret
_fac endp
code ends
data segment byte public 'data'
aux dw 0,0
data ends
end


  Como se puede apreciar el código está bastante claro al haber usado la estructura, ya que nos ha permitido direccionar fácilmente los datos de intercambio en pila.
  Pero ahora vamos a hacer el código usando main.mac y la macro rutina.


FAC.ASM (apoyarnos en main.mac)
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

; codigo
include main.mac    ; incluimos las macros y nuestras propias directivas de compilación
extrn _mult 
_modelo exe         ;directiva propia para elegir forma de colocar la data en la función
_code                   ;directiva propia. definición del segmento de codigo
rutina _fac p1,p2   ;directiva propia  definición de función con parámetros
        push bx
        push di
        mov bx,[bp].p1 ; indexación a través de la estructura para recoger el parametro p1
        mov di,[bp].p2
        mov word ptr [di],1
        mov word ptr [di+2],0
        mov word ptr aux,0
        mov word ptr aux+2,0
 otro:
        mov ax,[bx]
        cmp aux,ax
        jnz no
        mov ax,[bx+2]
        cmp aux+2,ax
        jz fin
     no:
        add aux,1
        adc aux+2,0
        push di
        push di
        mov ax,offset aux
        push ax
        call _mult
        add sp,6
        jmp otro
   fin:
        pop di
        pop bx
        pop bp
        ret
_fac endp
_data          ;directiva propia  definición de zona de datos
aux dw 0,0
_end           ; directiva propia. Fin de programa. En este caso no damos nombre pues es librería.


  Como vemos ha quedado más simple.  Igualmente se podría realizar una macro para salvar todos los registros a pila al inicio, pero entonces el código crearía volcados y recuperaciones de registros a pila inútiles. Como lo que queremos con el ensamblador es no crear ni un solo byte innecesario, es mejor sacrificar esa comodidad si implica código basura.








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.