Vistas de página en total

Mostrando entradas con la etiqueta MATH. Mostrar todas las entradas
Mostrando entradas con la etiqueta MATH. Mostrar todas las entradas

lunes, 24 de marzo de 2014

ACTUALIZACIÓN LIBRERÍA MATH

   Debido a que ahora vamos a necesitar alguna de las funciones matemáticas publicadas al comienzo del blog, y a que ya nos encontramos programando sobre TASM2.0, voy a refrescar estas librerías, pasando al nuevo fromato de código y comentándolas un poco más.

     Estas librerías son necesarias para realizar el progra,a de ejemplo de circulo que pondré más adelante. Para poder determinar el centro y radio de un circulo a partir de dos pintos elegidos por el ratón en pantalla.
    no pongo todas. Solo las que usaré para realizar un ejemplo como el de dibujos de líneas con el ratón, pero de circulos.
  En este caso, como se trata de refrescar algo que ya he puesto, pondré en unas sola entrada la definición de la cabecera y de cada una de las librerías.

; 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/>.


Cabecera matemática

MATH.MAC
@b = 2
@o = 8
@d = 10
@h = 16

;valor absoluto del dato 16bits
abs macro dato
local positivo
        add dato,0       
        jns  positivo1    
        neg dato
endm

;suma datos 32bits
suma macro ope1,ope2,res
ifndef _suma
       extrn _suma:near
endif
        lea ax,ope1
        push ax
        lea ax,ope2
        push ax
        lea ax,res
        push ax
        call _suma

     endm
    
;resta datos 32bits    
resta macro ope1,ope2,res
ifndef _resta
       extrn _resta:near
endif
        lea ax,ope1
        push ax
        lea ax,ope2
        push ax
        lea ax,res
        push ax
        call _resta

     endm


;multiplica dato 32 bits
mult macro ope1,ope2,res
ifndef _mult
       extrn _mult:near
endif
        lea ax,ope1
        push ax
        lea ax,ope2
        push ax
        lea ax,res
        push ax
        call _mult

     endm
    
    
;divide dato 32 bits    
divi macro ope1,ope2,res
ifndef _divi
       extrn _divi:near
endif
        lea ax,ope1
        push ax
        lea ax,ope2
        push ax
        lea ax,res
        push ax
        call _divi

     endm
    
    
;sqr devuelve en ax el resultado de la raiz de 32 bits
sqr macro oper
ifndef _sqr
        extrn _sqr:near
endif
        lea ax,oper
        push ax
        call _sqr

      endm

;factorial numeros de 32bits
;fac calcula el factorial del int fuente y lo devuelve en destino
fac macro fuente,destino
ifndef _fac
       extrn _fac:near
endif
        lea ax,fuente
        push ax
        lea ax,destino
        push ax
        call _fac

  endm
 
;potencia numeros de 32bits
;fuente es un puntero de una variable de 16 bits
;potencia es una variable de 16 bits
;destino es un puntero a una variable de 32 bits
;pot calcula x a la n siendo x=fuente,n=potenc y devuelve el resultado en destino
pot macro fuente,potenc,destino
ifndef _pot
       extrn _pot:near
endif
        lea ax,fuente
        push ax
        mov ax,potenc
        push ax
        lea ax,destino
        push ax
        call _pot

  endm
 
;exp numeros de 32bits 
exp macro potenc,destino
ifndef _exp
       extrn _exp:near
endif
        lea ax,potenc
        push ax
        mov ax,destino
        push ax
        call _exp

  endm

;compara numeros de 32bits
cmpi macro destino,fuente
local fin

     push ax
     mov ax,fuente+2
     cmp destino+2,ax
     jne fin
     mov ax,fuente
     cmp destino,ax
 fin:
     pop ax
     endm






Librerías Matemáticas

POT.ASM

; eleva un úmero de 16 bits a otro número dando el resultado en un número de 32 bits
;op1 puntero a varialbe de 16 bits
;op2 numero de 16 bits
;res puntero a variable de 16 bits
model compact,pascal

.code
      public _pot
_pot proc uses bx di cx,op1,op2,res
      extrn _mult:near

 mov cx,op2
        mov bx,op1
        mov di,res
        mov word ptr [di],1
        mov word ptr [di+2],0
 otro:
        cmp cx,0
        jz fin
        push bx
        push bx
        push di
        call _mult
        dec cx
        jmp otro
   fin:
               ret
_pot endp

end


MULT.ASM
;multiplica dos numeros de 32 bits  y el resultado lo lleva a otro de 16 bits
;op1 puntero a nuemro de 32 bits
;op2 puntero a nuemro de 32 bits
;res puntero a número de 32 bits
; multiplica en formato de 32 bits, pero el resultado debe de ser como máximo de 32 bits
;multiplica número sin signo.
.model compact,pascal

.code    
       public _mult
_mult proc uses bx dx cx si di,op1,op2,res
        mov si,op1
        mov bx,op2
        mov di,res
        mov ax,[bx+2]
        push ax
        mov ax,[si]
        push ax
        mov ax,[si]
        mov cx,[bx]
        mul cx
        mov [di],ax
        push dx
        mov ax,[si+2]
        mul cx
        pop dx
        add ax,dx
        mov [di+2],ax
        pop ax
        pop cx
        mul cx
        add [di+2],ax

        ret
_mult endp

end




SUMA.ASM
; codigo
;suma dos números de 32 bits
;sum1 puntero a variable de 32 bits
;sum2 puntero a varialbe de 32 bits
;res puntero a variable de 32 bits
.model compact,pascal
.code
        public _suma
_suma proc uses bx si di,sum1,sum2,res

        mov si,sum1
        mov bx,sum2
        mov di,res
        mov ax,[si]
        add ax,[bx]
        mov [di],ax
        mov ax,[si+2]
        adc ax,[bx+2]
        mov [di+2],ax

        ret
_suma endp

end



SQR.ASM

INCLUDE MATH.MAC
; raiz cuadrada. devuelve en ax el resultado
;Calcula la raiz de un número de 32 bis
; p1 puntero a variable de 32 bits
;El valor de una raíz cuadrada lo vamos a ir a aproximando de está forma:
; Para una raiz N, y teniendo una aproximación APROX, mi siguiente aproximación va a ser igual a:
;APROX = APROX - (APROX ^2 - N) / (2 * APROX)
;Este proceso lo repetimos hasta que la aproximación no cambie, o cuando los cambios de ésta sean mínimos (depende de que tan precisa quieres la raíz)
;SOLO PODREMOS CALCULAR RAICES DE NUMEROS HASTA 4.294.836.225, YA QUE EL RESULTADO DE LA RAIZ LO DEVOLVEREMOS EN AX

model compact,pascal
.data 
APROX DW 0,0
AAPROX DW 0,0
APROX2 DW 0,0
APROX3 DW 0,0
APROX4 DW 0,0
N DW 0,0

.code
      public _sqr
_sqr proc uses bx CX si,p1

        mov bx,p1   ;SE RECOGE EL PUNTERO A LA VARIBLE
        mov si,offset N     ; SE ASIGNA SI AL PUNTERO A LA VARIALBE N
        mov ax,[bx]       ;COPIAMOS EL DATO PASADO 
        mov [si],ax        ;N=P1
        mov ax,[bx+2]
        mov [si+2],ax
        MOV CX,2          ;MULTIPLICADOR 2
        ;COMIENZA LA ITARACIÓN
        mov AX,1       ;APROX=1
    sig:        
        MOV APROX,AX
        MUL CX       ;2*APROX
        MOV AAPROX,AX
        MOV AAPROX+2,DX
        POT APROX,2,APROX2         ;APROX^2
        RESTA APROX2,N,APROX3
        DIVI  APROX3,AAPROX,APROX4
        MOV AX, APROX
        SUB AX, APROX4
        CMP AX, APROX
        jne sig
  

        ret
_sqr endp

end



DIVI.ASM
;; solo divide por numeros menores de ffffh
title dividir
include main.mac

.model  compact,pascal
.data 
aux dw 0,0
.code
      public _divi
_divi proc uses bx dx cx si di,dividendo,divisor,resultado

        mov si,dividendo
        mov di,resultado
        mov bx,divisor
        mov word ptr [di+2],0
        mov word ptr [di],0
        xor dx,dx
        cmp word ptr [bx+2],0
        jz normal
        mov ax,[si+2]
        cmp ax,[bx+2]
        jb fin
        mov cx,[bx+2]
        div cx
        mov [di],ax
comprueba:
        mul word ptr [bx]
        mov aux,ax
        mov aux+2,dx
        mov ax,[di]
        mul word ptr [bx+2]
        add aux+2,ax
        mov ax,aux+2
        cmp ax,[si+2]
        ja no_cabe
        jne fin
        mov ax,aux
        cmp ax,[si]
        jbe fin
no_cabe:
        dec word ptr [di]
        mov ax,[di]
        jmp comprueba


  normal:
        mov cx,[bx]
        mov ax,[si+2]
        div cx
        mov [di+2],ax
        mov ax,[si]
        div cx
        mov [di],ax
   fin:

        ret
_divi endp





RESTA.ASM
; codigo
    public _resta
model compact,pascal

.code
_resta proc uses bx si di,min,subs,res

        mov si,min
        mov bx,subs
        mov di,res
        mov ax,[si]
        sub ax,[bx]
        mov [di],ax
        mov ax,[si+2]
        sbb ax,[bx+2]
        mov [di+2],ax

        ret
_resta endp


end


sábado, 8 de junio de 2013

EXPONENTE

   Hoy vamos a dar una vuelta de tuerca a la estructura de programación.
   Visto ya como se utilizaba la función rutina de la cabecera MAIN.MAC, para crear fácilmente las cabeceras de las rutinas y simplificar el código fuente de ensamblador, vamos ahora a ver como hacer lo mismo con el resto de las cabeceras, de forma que vamos a usar varias funciones ya creadas para crear una más compleja.
  El resultado volverá a ser como intentamos desde el principio, un programa en ensamblador con apariencia de alto nivel. Cuanto más cabeceras y rutinas hayamos  implementado, más simple queda el programa, utilizando el ensamblador puro simplemente para las inicializaciones de pilas y las características propias de la rutina implementada en el código en curso.

    En este caso para realizar el exponente necesitaremos apoyarnos en el factorial, en la potencia, en la suma y en la división. Como la definición de sus macros está en la cabecera MATH.MAC, la cabecera la incluirémos en el programa mediante include al igual que hacemos con MAIN.MAC para poder usar la macro rutina.

   El resultado, como se ve, es una código que declara las cabeceras, de las cuales tomaremos la forma uso de cada función, y en la que no importa que este incluida la declaración de la macro de la propia función exp, para simplificar el código.
    Como vemos lo primero es tomar las variables pasadas a la función como parámetros y guardarlos en las variables locales. De esta forma podemos utilizar esta como parámetros de paso para las funciones auxiliares, usando las macros para ello.

EXP.ASM
; 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/>.

include main.mac      ; inclusion de la cabecera main para uso de rutina
include math.mac     ; inclusion de la cabecera math, para usar pot, fac, divi y suma

; no poner _modelo exe  equivale a definir tipo exe

_code
rutina _exp exponente,resultado      ;declaración de la función con sus variables de paso
        push bx      ;salvaguarda de registros usados
        push di
        mov ax,[bp].exponente
        mov x,ax
        mov x+2,0
        mov di,[bp].resultado
        mov n,0
        mov word ptr [di],0
        mov word ptr [di+2],0
   mas:
        pot x,n,aux       ;llamada a la función potencia
        fac n,aux1        ; llamada a la función factorial
        divi aux,aux1,aux2    ;División
        suma [di],aux2,[di]   ;Suma
        inc n
        cmp n,13
        jnz mas
        pop di   ; recuperación de registros usados
        pop bx
        pop bp
        ret
_exp endp

_data             ;variables locales usadas por esta función
n dw 0,0       ;variables locales usadas por esta función
x dw 0,0
aux dd 0
aux1 dd 0
aux2 dd 0
_end



jueves, 6 de junio de 2013

DIVIDIR


Función dividir de la librería matemática Math.



DIVI.ASM
; 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/>.

;; solo divide por numeros menores de ffffh
include main.mac
_modelo exe

_code
rutina _divi dividendo,divisor,resultado
        push bx
        push dx
        push cx
        push si
        push di
        mov si,[bp].dividendo
        mov di,[bp].resultado
        mov bx,[bp].divisor
        mov word ptr [di+2],0
        mov word ptr [di],0
        xor dx,dx
        cmp word ptr [bx+2],0
        jz normal
        mov ax,[si+2]
        cmp ax,[bx+2]
        jb fin
        mov cx,[bx+2]
        div cx
        mov [di],ax
comprueba:
        mul word ptr [bx]
        mov aux,ax
        mov aux+2,dx
        mov ax,[di]
        mul word ptr [bx+2]
        add aux+2,ax
        mov ax,aux+2
        cmp ax,[si+2]
        ja no_cabe
        jne fin
        mov ax,aux
        cmp ax,[si]
        jbe fin
no_cabe:
        dec word ptr [di]
        mov ax,[di]
        jmp comprueba

  normal:
        mov cx,[bx]
        mov ax,[si+2]
        div cx
        mov [di+2],ax
        mov ax,[si]
        div cx
        mov [di],ax
   fin:
        pop di
        pop si
        pop cx
        pop dx
        pop bx
        pop bp
        ret
_divi endp
_data
aux dw 0,0
_end






martes, 4 de junio de 2013

RAIZ CUADRADA

Rutina que nos permite sacar la raíz cuadrada.

 No hay mucho que explicar pues la estructura se basa en lo mismo.
  Sabemos que existen coprocesadores con coma flotante en un PC. Pero cuando se enseña ensamblador, hay que tener en cuenta que no todos los procesadores lo tienen. Aprender ensamblador, significa aprende también microprocesadores. En la actualidad, muchos microcontroladores se programan en "C" o "basic", pero quizás por testarudez, a mi me gustan los microprocesadores directos.
   Este es un ejemplo de calculo de la raíz cuadrada por el método recurente, (Algoritmo Babilónico). En este caso solo obtenemos la parte entera, pero en muchos casos de pequeños programas de control nos servirá.
  Si queremos obtener decimales, bastará con multiplicar el número previamente por 100 o 10000 y luego aplicar el algoritmo. Después simplemente descomponemos la parte entera que nos haya resultado. Por ejemplo (Raiz de 3) = (Raiz de 300) /10.
   por ello si queremos un decimal, multiplicamos 3*100=300, aplicamos el algoritmo y nos da 17, y dividiendo por 10, la parte entera es la palrte entera y el resto son los decimales =1.7.

  Es un buen ejemplo de como obtener de forma matemática una función complicada, como la raíz cuadrada, mediante funciones simples.
  El método es el de Newton-Raphson, el cuál se basa en una serie de Taylor, para obtener el valor de una función dada. Si quieres saber más acerca de este método, mira en Wikipedia.
      El valor de una raíz cuadrada lo vamos a ir a aproximando de está forma:
 Para una raiz N, y teniendo una aproximación APROX, mi siguiente aproximación va a ser igual a:

APROX = APROX - (APROX * APROX - N) / (2 * APROX)

Este proceso lo repetimos hasta que la aproximación no cambie, o cuando los cambios de ésta sean mínimos (depende de que tan precisa quieres la raíz). Ej:

N=3
APROX = 1 (El valor inicial no importa)

APROX = 1 - ( 1 * 1 - 3) / (2 * 1) = 2
APROX = 2 - ( 2 * 2 - 3) / (2 * 2 ) = 1.75
APROX = 1.75 - (1.75 * 1.75 - 3) / (2 * 1.75) = 1.73215
YA APROXIMAMOS LA RAÍZ DE 3!!


SQR.ASM
; 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
; raiz cuadrada. devuelve en ax el resultado

include main.mac
include math.mac
_modelo exe
_code
rutina _sqr p1

        push bx
        push si
        mov bx,[bp].p1
        mov si,offset n
        mov ax,[bx]       ;COPIAMOS EL DATO PASADO 
        mov [si],ax        ;N=P1
        mov ax,[bx+2]
        mov [si+2],ax
        MOV CX,2          ;MULTIPLICADOR 2
        ;COMIENZA LA ITARACIËN
        mov AX,1       ;APROX=1
    sig:        
        MOV APROX,AX
        MUL CX       ;2*APROX
        MOV AAPROX,AX
        MOV AAPROX+2,DX
        POT APROX,2,APROX2         ;APROX^2
        RESTA APROX2,N,APROX3
        DIVI  APROX3,AAPROX,APROX4
        MOV AX, APROX
        SUB AX, APROX4
        CMP AX, APROX
        jne sig
  
        pop si
        pop bx
        pop bp
        ret
_sqr endp
_data 
APROX DW 0,0
AAPROX DW 0,0
APROX2 DW 0,0
APROX3 DW 0,0
APROX4 DW 0,0
N DW 0,0
_end

domingo, 2 de junio de 2013

SUMA

De forma idéntica a la resta tenemos la suma.

SUMA.ASM
; 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
_modelo exe
_code
rutina _suma sum1,sum2,res
         push bx
        push si
        push di
        mov si,[bp].sum1
        mov bx,[bp].sum2
        mov di,[bp].res
        mov ax,[si]
        add ax,[bx]
        mov [di],ax
        mov ax,[si+2]
        adc ax,[bx+2]
        mov [di+2],ax
        pop di
        pop si
        pop bx
        pop bp
        ret
_suma endp
_data
_end

jueves, 30 de mayo de 2013

RESTA

Siguiendo con las funciones matemáticas y con la misma filosofía. Aquí está la resta de dos variables.


RESTA.ASM
; 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/>.
;resta al minuendo el substraendo dejandolo en  resultado

; codigo

include main.mac
_modelo exe
_code
rutina _resta min,subs,res
        push bx                      ;salva los registros usados
        push si
        push di
        mov si,[bp].min        ; recoge las direcciones de las variables
        mov bx,[bp].subs
        mov di,[bp].res
        mov ax,[si]                ; opera los datos, primera palabra
        sub ax,[bx]
        mov [di],ax
        mov ax,[si+2]            ; opera los datos, segunda palabra 
        sbb ax,[bx+2]
        mov [di+2],ax           ; almacena el resultado en la dirección de la variable indicada
        pop di                         ; recupera los registros para que la función sea transparente
        pop si
        pop bx
        pop bp
        ret
_resta endp
_data
_end

martes, 28 de mayo de 2013

POTENCIA

  Rutina _pot, perteneciente a la librería MATH. Esta rutina realiza la función potencia apoyándose en la función _mult que hicimos antes.
  En este caso, como se ve, para realizar la multiplicación no llamamos a la macro mult,  ya que  las macros están hecha para ser usadas con variables, y generaría en este caso una instrucción lea extra por cada operando. por lo tanto si introducimos los parámetros en pila directamente hemos ahorrado tres instrucciones lea en este caso.
   Es por eso por lo que en el caso de crear funciones en las librerías a partir de otras funciones prefiero implementar la llamada directamente sin usar las macros.
   Más adelante realizaré las opciones con el coprocesador, y crearemos una cabecera para su uso.


POT.ASM
; 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
 ; eleva un úmero de 16 bits a otro número dando el resultado en un número de 32 bits
;op2 puntero a varialbe de 16 bits
;op1 numero de 16 bits
;res puntero a variable de 16 bits



include main.mac
_modelo exe
_code
rutina _pot op1,op2,res
      extrn _mult:near

        push bx
        push di
        push cx
        mov cx,[bp].op1
        mov bx,[bp].op2
        mov di,[bp].res
        mov word ptr [di],1
        mov word ptr [di+2],0
 otro:
        cmp cx,0
        jz fin
        push di  ; llamada a la función mult, almacenando sus datos directamente en pila 
        push bx  ; sin uso de la macro mult
        push bx
        call _mult
        add sp,6
        dec cx
        jmp otro
   fin:
        pop cx
        pop di
        pop bx
        pop bp
        ret
_pot endp
_data
_end







domingo, 26 de mayo de 2013

MULTIPLICAR


Función mult, que es parte de la librería Math y por lo tanto está declarada en la cabecera MATH.MAC
Esta función multiplica dos números, op1 y op2, y devuelve el resultado en res.
  Recuedo que definimos _data, aunque no lo usemos, para que la directiva propia _data no nos de error en el assume ds:_data. En el caso de usar modelo 'com' no hay problema porque la directiva _data no creará nada.

   La data la colocamos al final, para que sirva tanto para com como para exe. La directiva _data se encargará de crear el segmento de datos o dejar las definiciones de variables dentro del segmento de código.

MULT.ASM
; 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
_modelo exe _code
rutina _mult op1,op2,res

        push bx
        push dx
        push cx
        push si
        push di
        mov si,[bp].op1
        mov bx,[bp].op2
        mov di,[bp].res
        mov ax,[bx+2]
        push ax
        mov ax,[si]
        push ax
        mov ax,[si]
        mov cx,[bx]
        mul cx
        mov [di],ax
        push dx
        mov ax,[si+2]
        mul cx
        pop dx
        add ax,dx
        mov [di+2],ax
        pop ax
        pop cx
        mul cx
        add [di+2],ax
        pop di
        pop si
        pop cx
        pop dx
        pop bx
        pop bp
        ret
_mult endp
_data
_end






jueves, 23 de mayo de 2013

DECLARACIÓN FUNCIONES MATEMÁTICAS

    Ya que en la anterior entrada hemos colocado una función matemática, la función fac, continuaremos con la librería matemática.
   En este cas, como en todos, si el código no supera un determinado tamaño no se pasa a librería y se implementa como macro.
 ¿Cual es el tamaño para el cambio?. Si el tamaño que resulta de guardar los datos en pila, la inicialización de pila, y recuperación de la pila,  es mayor que tamaño en si del código de la función.

   Así pues, todas estas funciones son implementadas mediante macros que llaman a funciones, menos la comparación.

     En todas la macros existe la instrucción ifndef, para que no implemente el compilador la función en el código mas que una vez y no declare la función como externa si no es usada. De esta forma el linkador no cargará la rutina de la librería, pues no ha sido declarada.


MATH.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/>.
; cabecera funciones matemáticas

@b = 2  ;binario
@o = 8   ;octal
@d = 10  ;decimal
@h = 16 ;hexadecimal


; res=ope1 + ope2
suma macro ope1,ope2,res
ifndef _suma
       extrn _suma:near     
endif
        lea ax,res
        push ax
        lea ax,ope2
        push ax
        lea ax,ope1
        push ax
        call _suma
        add sp,6
     endm

; res=ope1 -ope2
resta macro ope1,ope2,res
ifndef _resta
       extrn _resta:near
endif
        lea ax,res
        push ax
        lea ax,ope2
        push ax
        lea ax,ope1
        push ax
        call _resta
        add sp,6
     endm

; res=ope1 * ope2
mult macro ope1,ope2,res
ifndef _mult
       extrn _mult:near
endif
        lea ax,res
        push ax
        lea ax,ope2
        push ax
        lea ax,ope1
        push ax
        call _mult
        add sp,6
     endm

; res=ope1 / ope2
divi macro ope1,ope2,res
ifndef _divi
       extrn _divi:near
endif
        lea ax,res
        push ax
        lea ax,ope2
        push ax
        lea ax,ope1
        push ax
        call _divi
        add sp,6
     endm

;sqr devuelve en ax el resultado de la raiz
sqr macro oper
ifndef _sqr
        extrn _sqr:near
endif
        lea ax,oper
        push ax
        call _sqr
        add sp,2
      endm

;fac calcula el factorial del int fuente y lo devuelve en destino
;destino=factorial(fuente)
fac macro fuente,destino
ifndef _fac
       extrn _fac:near
endif
        lea ax,destino
        push ax
        lea ax,fuente
        push ax
        call _fac
        add sp,4
  endm

;pot calcula x a la n siendo x=fuente,n=potenc y devuelve el resultado en destino
pot macro fuente,potenc,destino
ifndef _pot
       extrn _pot:near
endif
        lea ax,destino
        push ax
        mov ax,potenc
        push ax
        lea ax,fuente
        push ax
        call _pot
        add sp,6
  endm

; destino=
exp macro potenc,destino
ifndef _exp
       extrn _exp:near
endif
        lea ax,destino
        push ax
        mov ax,potenc
        push ax
        call _exp
        add sp,4
  endm

cmpi macro destino,fuente
local fin

     push ax
     mov ax,fuente+2
     cmp destino+2,ax
     jne fin
     mov ax,fuente
     cmp destino,ax
 fin:
     pop ax
     endm

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.