Vistas de página en total

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.








domingo, 19 de mayo de 2013

¿COMO FUNCIONA "RUTINA"?

 Vamos a comprobar que sucedió con la librería GRAPHICS.ASM  al compilarla.
  Os muestro la parte del listado generación de programa y de publicación de variables.

 Pues aquí os pongo el listado generado por el compilador donde se desarrolla el código de forma completa.
  Este pues sería el código que deberíamos colocar si no hubiéramos creado nuestras macros.
   En un programa de 45 líneas tenemos 15 generadas por el precompilador. Esto sin contar que ya hemos publicado las funciones, y hemos creado una estructura de trabajo más aprosimada al "C" que al ensamblador.
     Básicamente mi macro "rutina nombre x1,y1,z1" equivale a "proc nombre arg x1,y1,z1" en el TASM.

     0     _code    
1   1 0000 code segment byte public 'code'
     2
     3     rutina _line x1,y1,x2,y2,color
1   4 *000 _linep struc
1   5 *000  01*(????????)      dd ?
2   6 *004  01*(????)  x1  dw ?
2   7 *006  01*(????)  y1  dw ?
2   8 *008  01*(????)  x2  dw ?
2   9 *00A  01*(????)  y2  dw ?
2   10 *00C  01*(????)  color dw ?
1   11 *00E _linep ends
1   12 0000     _line proc near
 1   13 *0000  55     push bp
 1   14 *0001  8B EC     mov bp,sp
    15
    16     ; espacio para la rutina
    17 0003  5D     pop bp
    18 0004  C3     ret
    19 0005     _line endp
    20
    21     rutina _putpixel x,y,color1
1   22 *005 _putpixelp struc
1   23 *000  01*(????????)      dd ?
2   24 *004  01*(????)  x  dw ?
2   25 *006  01*(????)  y  dw ?
2   26 *008  01*(????)  color1  dw ?
1   27 *00A _putpixelp  ends
1   28 0005     _putpixel proc near
1    29 *0005  55     push bp
1    30 *0006  8B EC     mov bp,sp
    31 0008  53     push bx
    32 0009  51     push cx
    33 000A  52     push dx
    34 000B  8B 46 0C     mov ax,[bp].color
    35 000E  B4 0C     mov ah,0ch
    36 0010  BB 0000     mov bx,0
    37 0013  8B 4E 04     mov cx,[bp].x
    38 0016  8B 56 06     mov dx,[bp].y
    39 0019  CD 10     int 10h
    40 001B  5A     pop dx
    41 001C  59     pop cx
    42 001D  5B     pop bx
    43 001E  5D     pop bp
    44 001F  C3     ret
    45 0020     _putpixel endp



Symbol Name  Type Value

??DATE  Text "08/05/13"
??FILENAME  Text "graphics"
??TIME  Text "15:34:19"
??VERSION  Number 0200
@CPU  Text 0101H
@CURSEG  Text CODE
@FILENAME  Text GRAPHICS
@WORDSIZE  Text 2
_LINE  Near CODE:0000
_PUTPIXEL  Near CODE:0005

domingo, 12 de mayo de 2013

DOS


En esta cabecera se encuentran definidas las principales funciones del dos, para manejo de ficheros, directorios y memoria.
    Al inicio están definidas las constantes de manejo de unidades y atributos de ficheros.




DOS.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/>.
; definición de unidades
ifndef _unidades
    _unidades equ 1
;unidades
_A equ  0
_B equ 1
_C equ 2
_D equ 3
endif

; definición de atributos de ficheros y directorios
ifndef _atributos
   _atributos equ 1
;;atributos de fichero
_O_READ  equ 1
_HIDE    equ 2
_SISTEM  equ 4
_VOL     equ 8
_DIR     equ 16
_ARCHIVO equ 32
_TODOS   equ 00111111B
endif

; borrar de fichero
delete macro file
    mov ah,41h
    push dx
    lea dx,file
    int 21h
    pop dx
 endm

; renombrar fichero
 rename macro file,file1
     push es
     push dx
     push di
     lea dx,file
     lea di,file1
     mov ah,56h
     push ds
     pop es
     int 21h
     pop di
     pop dx
     pop es
 endm

; crear directorio
mkdir macro subdir
    mov ah,39h
    push dx
    lea dx,subdir
    int 21h
    pop dx
endm

;renombrar directorio
rmdir macro subdir
    mov ah,3ah
    push dx
    lea dx,subdir
    int 21h
    pop dx
endm

;cambiar de directorio
chdir macro subdir
    mov ah,3bh
    push dx
    lea dx,subdir
    int 21h
    pop dx
endm

; tomar el directorio actual
getcurdir macro  unidad,destino
    mov ah,47h
    push dx
    push si
    mov dl,unidad
    lea si,destino
    int 21h
    pop si
    pop dx
  endm

;colocar atriburos a un fichero
setattr macro file, atributo
    push dx
    push cx
    lea dx,file
    mov cx,atributo
    mov ax,4301h
    int 21h
    pop cx
    pop dx
endm

;leer los atributos de fichero
getattr macro file
    local sal
    push dx
    push cx
    lea dx,file
    mov ax,4300h
    int 21h
    jc sal
    mov ax,cx
 sal:
    pop cx
    pop dx
endm

; moverse a una unidad
setdisk macro unidad
    mov ah, 0eh
    PUSH DX
    mov dl, unidad
    int 21h
    POP DX
    endm

;tomar la unidad activa
getdisk macro unidad
    mov ah, 19h
    int 21h
    mov unidad,al
    endm

;interceptar una interupción
setint macro inter,posicion
ifndef _set_inter
     extrn _set_inter:near
endif
        mov ax,offset posicion
        push ax
        mov ax,seg posicion
        push ax
        mov ax,inter
        push ax
        call _set_inter
        add sp,6
 endm

; Finalizar y dejar residente
keep macro fin,codigo
        mov al,codigo
        mov ah,31h
        mov dx,offset fin
        mov cl,4
        shr dx,cl
        int 21h
 endm

; tomar la interrupción
 getint macro segmento,offset
        push bx
        push cx
        mov ah,35h
        int 21h
        mov ax,es
        mov segmento,ax
        mov offset,bx
        pop es
        pop bx
      endm

;Nos devuelve el tipo de sistema operativo
 ;ah numero menor
 ;al numero mayor
 ;bx,cx numero serie
 dosver macro
        mov ah,30h
        int 21h
      endm

 ;devuelve en buffer el segmento donde consigue la mamoria pedida
farmalloc macro segmento,tamano
        push bx
        push cx
        mov ah,48h
        mov bx,tamano
        mov cl,4
        shr bx,cl
        int 21h
        mov segmento,ax
        pop cx
        pop bx
 endm


;liverar memoria
 farfree macro segmento
        push es
        mov ah,49h
        mov es,buffer
        int 21h
        pop es
 endm



viernes, 10 de mayo de 2013

_LIN_COMAND

   _LIN_COMAND - IMPLEMENTACIÓN DE  ARGC Y ARGV

  Una vez visto lo que queremos hacer y definido la parte exterior del programa, es decir lo que vemos y escribimos habitualmente, vamos a pasar al código almacenado en nuestras librerías.
   Para poder trabajar fácilmente, se crearon las liberías (.LIB). Estas son almacenes de código compilado, que serán recopiladas por el linker según vayan siendo declaradas.
   El programa declarará las librerías, que han de ser usadas, a través del compilador, y el linker las añadirá al código final, enlazando las llamadas a ellas con la posición donde coloca cada rutina. 
   Debido a que la unión la realiza el linker, el código fuente de las librerías ha de ser compilado y posteriormente almacenado en la librería.  Para ello usaremos el compilador, en este caso TASM, y posteriormente el gestor de librerías TLIB para almacenar el " código objeto" en la librería.
   Como todo esto es parte del manejo de los compiladores, no entraré en como se hace.
  Simplemente quiero recordar que la mayor parte del código a utilizar lo deberemos almacenar en las librerías. 
   Existen librerías ya construidas, que pueden ser usadas. Como el sistema que utilizo de paso de parámetros es el estandar de C, se pueden enlazar con nuestros programas cualquier rutina de las librerías de Borland C. En mi caso no existe librería C ya que, no hay código previo. Parto de cero. Todo el código es nuevo.
  Más adelante indicaré como aprovecharnos de funciones ya creadas en otras librerías, para realizar programas con apoyo de instrucciones más complejas.

 Como mostré en la declaración del Main.mac la macro main llama a una función que extrae los argumentos de la linea de comandos y los almacena en una estructura, para luego poder analizarlos individualmente. Esta función es la que hoy presento. La función _lin_comand.

   Como se ve en la definición de la función existe algunas novedades.
   Primero Public. Directiva de compilación que permite declarar el nombre como localizable por el linkador para poder asociar la rutina al resto del código. Public lo que hace es añadir una entrada en una tabla de referencias en la librería con el nombre y la dirección en del código dentro de la librería. De esta manera el linkador podrá tomar la función y añadirla al código en curso. Si no se declara no será localizable.
 Igualmente debemos publicar las variables que debamos alcanzar desde el exterior. En este caso   _argc y _argv, que son precisamente las que se declararon como extern en el argum.mac.
   
  La función _lin_comand recorre la linea de comandos del dos, y va tomando las palabras, almacenando la dirección de cada una en una lista de punteros llamada argv. El número de palabras lo guarda en argc.
  Esta función no será incorporada al main.mac si no se incluye la cabecera ARGUM.MAC



MAIN.ASM (Versión Clásica TASM2.0)
; 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/>.

title libreria del sistema operativo
code segment byte public 'code'
      assume ds:data, cs:code
      public _lin_comand
      public _argc
      public _argv
_lin_comand proc near
        push ds
        push es
        push dx
        push bx
        push cx
        push si
        push di
        xor cx, cx
        cld
        mov si, 81h
        mov ax, data
        mov es, ax
        mov di, offset _lista
        mov bx, 80h
        mov cl,[bx]
        rep movsb
        mov cl, [bx]
        inc cx
        push es
        pop ds
        cmp cx, 0
        ja anali
        mov _argc, 0
        jmp fin

    anali:
        mov bx, offset _argv
        mov di, offset _lista
        mov al,' '
    anali1:
        repe scasb
        cmp cx, 0
        je fin
        dec di
        inc cx
        mov [bx], di
        inc bx
        inc bx
        repne scasb
        inc _argc
        dec di
        mov byte ptr [di], 0
        inc di
        cmp cx, 0
        je fin
        jmp anali1

    fin:
        pop di
        pop si
        pop cx
        pop bx
        pop dx
        pop es
        pop ds
        ret
_lin_comand endp
code ends
data segment byte public 'data'
        _argc db 0
        _argv dw 16 dup(0)
        _lista db 20 dup(0)

data ends
end

Si aplicamos las macros de mejora de directivas mías definidas en main.mac quedará.

MAIN.ASM (Versión Propia con mis macros)
; 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
title libreria del sistema operativo

_modelo exe

_code
      public _lin_comand
      public _argc
      public _argv
_lin_comand proc near
        push ds
        push es
        push dx
        push bx
        push cx
        push si
        push di
        xor cx, cx
        cld
        mov si, 81h
        mov ax, data
        mov es, ax
        mov di, offset _lista
        mov bx, 80h
        mov cl,[bx]
        rep movsb
        mov cl, [bx]
        inc cx
        push es
        pop ds
        cmp cx, 0
        ja anali
        mov _argc, 0
        jmp fin

    anali:
        mov bx, offset _argv
        mov di, offset _lista
        mov al,' '
    anali1:
        repe scasb
        cmp cx, 0
        je fin
        dec di
        inc cx
        mov [bx], di
        inc bx
        inc bx
        repne scasb
        inc _argc
        dec di
        mov byte ptr [di], 0
        inc di
        cmp cx, 0
        je fin
        jmp anali1

    fin:
        pop di
        pop si
        pop cx
        pop bx
        pop dx
        pop es
        pop ds
        ret
_lin_comand endp

_data
        _argc db 0
        _argv dw 16 dup(0)
        _lista db 20 dup(0)
_end


  Como se ve hemos simplificado el programa y lo hemos acercado a TASM5.0. Además, ahora con solo cambiar la línea de"_model exe" a "_model com" podremos compilarla librería para realizar ficheros .com

miércoles, 8 de mayo de 2013

COMPAREMOS CON TASM


   Ahora ya hemos visto las macros creadas para manejar el entrono de definición de segmentos de forma más cómoda. Hay que tener en cuenta que esto está programado para enseñar el funcionamiento del compilador y la comunicación con subrutinas.Su fin es demostrar como sacar partido a las macros y como todo es definible para así crear un lenguaje cómodo a partir de un compilador muy básico.
   Más tarde usaremos las directivas del TASM, las cuales ya se ha implementado para realizar estas mismas funciones y que funcionan de forma todavía mas completa que mis macros. Por ejemplo, para combinar código con otro lenguajes.
      Pero como no siempre dispondremos de estos compiladores o al menos yo no dispuse en el 1988 de ellos para el Z80, tube que solucionar la estructuración con las macros que si tenían estos compiladores.

   Aquí está el ejemplo "Hola mundo" que podéis encontrar hecho con TASM 5.0.
   Como veis la estructura es prácticamente idéntica. En este caso usa MODEL para definir un programa ".com",cuya forma equivalente mía es _modelo.
   Una diferencia en mi caso es que debo definir la Data al final, para que las macros coloquen correctamente los segmentos en caso de .com. Pero eso es una nimiedad.

    Como veis a nivel de precompilador y de declaración de pila, zona de datos, y zona de código, queda igual. Podemos hasta considerar el .startup como si fuera mi main. Pero como como veréis más adelante el mío es mucho más que la declaración de inicio de programa, en mi caso implementa también la recogida de datos del dos.
    Así mismo la asignación del DS, ya está hecha dentro de mi main.
   Al final veréis el regreso al sistema mediante instruciones asm y la int 21h, en cambio yo dispongo de mi  macro exit.
   Es por todo esto que, aunque existen las directivas en TASM 2.0, yo estoy subiendo porgramas sin usarlas usando las mías, aunque solo sea por demostrar que se puede hacer lo mismo si se saben usar bien las MACROS, y porque de esa manera se puede entender mejor lo que hace el compilador, cuando usamos sus directivas.


Ejemplo "Hola mundo con TASM 5.0"

; Turbo Assembler    Copyright (c) 1988, 1991 By Borland International, Inc.

; HELLO.ASM - Display the message "Hello World"

; From the Turbo Assembler Users Guide - Getting started



   .MODEL small
   .STACK 100h
   .DATA
HelloMessage DB 'Hello, world',13,10,'$'
   .CODE
   .startup
   mov  ax,@data
   mov  ds,ax                  ;set DS to point to the data segment
   mov  ah,9                   ;DOS print string function
   mov  dx,OFFSET HelloMessage ;point to "Hello, world"
   int  21h                    ;display "Hello, world"
   mov  ah,4ch                 ;DOS terminate program function
   int  21h                    ;terminate the program
   END



Ejemplo "Hola mundo con ASM Y MIS DIRECTIVAS"
; Assembler    Copyright (c) 1995 By José Angel Moneo Frdez.

; HELLO.ASM - Display the message "Hello World"
    include main.mac
   _MODELO com
   _STACK 100h
   _DATA
HelloMessage DB 'Hello, world',13,10,'$'
   _CODE
   main
   mov  ah,9                   ;DOS print string function
   mov  dx,OFFSET HelloMessage ;point to "Hello, world"
   int  21h                    ;display "Hello, world"
   exit 0
   _END

martes, 7 de mayo de 2013

PRIMER PROGRAMA EJECUTABLE

  Como se ve, con una pocas instruciones, hemos creado un código, muy sencillo de leer y muy estructurado, en ensamblador. Tenemos que tener en cuenta que este cCon el vistas hasta ahora, parece imposible componer algo ejecutable de forma fácil. Pero, para adelantar lo que queremos conseguir, vamos a poner el código de un programa ".exe"

  En este caso el programa, no realizaría ninguna función. Simplemente ejecutaría y saldría al sistema de nuevo.

  En este código se puede ver el uso de cada una de las macro definidas en la cabecera main.
  El código se divide en tres partes:
       include - Directiva para incluir  la cabecera main, para que la lea las macros que definen nuestras nuevas directivas de compilación
       _data  Directiva propia. Definición del segmento de datos, para luego delcarar las varialbes
      _modelo - Directiva propia. Indica el modelo de programa que deseamos exe o com
       _stack - Directiva propia. Define la pila en 300 bytes
       _code  - Directiva propia. Define la zona de programa. Dentro declaramos el procedimiento. En este caso _vacio
       _end- Directiva propia. Fin de codigo. En este caso hay que indicar el nombre de larutina principal, ya que se trata del programa ejecutable.
      main - Función de inicialización cuyo código veremos posteriormente.
      exit - Macro de salida al sistema incluida en main.mac, en la que se indica el código de salida


   En este caso no incluimos la cabecera argum.mac, y por lo tanto no será incluido el código de la librería _lin_comand y no leeremos la linea de comando. 
   En este caso el programa no hace nada en particular. Eso lo dejaremos para cuando aumentemos las librerías. Ahora solo interesa ver la estructura base del código.
    Como vemos he puesto la data al final, para que pueda funcionar mi directiva _data con la de _modelo, y me permita cambiar el programa de exe a com. Si no ponemos la directiva _modelo el programa será exe


El código se puede compilar en el ensamblador en cualquier compilador anterior a MASM, pero como se ve la estructura es equivalente a TASM  2.0 y por supuesto puede compilarse en TASM2.0.
   

PRUEBA 1.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
title prueba1 
_modelo exe  ; define formato exe. DS y CS separados.   (equivale a .model compact en TASM)
_stack 300                           ; (equivale a .stack  en TASM)

_code                                   ; (equivale a .code en TASM)
_vacio proc far  
        main
        exit 0
_vacio endp
_data                                    ; (equivale a .data en TASM)
  help db "Ejemplo",10,13
_end vacio

lunes, 6 de mayo de 2013

ARGUM

ARGUM.MAC - TOMA DE ARGUMENTOS DE LA LÍNEA DE COMANDOS


Al igual que en "C", necesitamos tomar los argumentos que nos pasen del sistema, al ejecutar un programa, desde la linea de comandos, para tratarlos en nuestro programa. Esta función llamada como en "C", toma el argumento indicado, para poder tratarles posteriormente.

  En realidad son dos funciones ARGV y ARGC.
  
  Argc nos dará el número de argumentos y Argv nos permitirá tomar un puntero uno específico.
  Los datos de argumentos están cargados en la memoria, como una lista de cadenas. El proceso de descomponer la linea de comandos y almacenar cada argumento en una cadena independiente la realiza una rutina llamada Main, que será expuesta posteriormente y que será llamada al comienzo de cada programa, para la correcta inicialización de este.

  Este caso es más complejo que el anterior. Esta función utiliza el precompilador para crear una macro con parámetro adicional. El numero, que nos permitirá recoger el argumento que necesitemos de la lista de argumentos, y la dirección, que nos dirá en que dirección de memoria está este argumento.

   la función ifdif nos va a permitir usar la macro de dos modos. Podremos indicar en su llamada el argumento deseado y la dirección en la que queremos que nos almacene el puntero del argumento, o podemos no indicar argumentos y tomar bl y ax como indice y puntero por respectivamente. Esto nos permitirá utilizar la función en bucles ahorrando código, si utilizamos bl como contador.

  Como se ve la función es macro directa, su código es muy corto y no tiene sentido almacenarla en librería.
  En cambio se declara una función y dos variables que no están usadas. Las declaraciones extrn están puestas para indicar al compilador las variables  declaradas en _lin_comand.
   Están aquí y no en Main.mac, que es donde se usan, para que podamos eliminarlas de la compilación, simplemente no incluyendo esta cabecera si no necesitamos usar argumentos.
    


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

     
extrn _argv:word     
extrn _argc:byte


argc macro dato
        mov dato,_argc
endm


argv macro numero,direccion
        push bx
        mov bh,0
   ifdif <numero>,<bl>    ;DECLARACION CONDICIONAL PARA USO CON Y SIN PARÁMETROS
        mov bl,numero
    endif
        dec bx
        shl bx,1
        add bx,offset _argv
        mov ax,[bx]
        pop bx
    ifdif <numero>,<ax>  ;DECLARACION CONDICIONAL PARA USO CON Y SIN PARÁMETROS
        mov direccion,ax
    endif
endm

domingo, 5 de mayo de 2013

MAIN

 MAIN.MAC - CABECERA PRINCIPAL


   Primero y ante todo decir que el código que voy a implementar no usa muchas directivas ya creadas en MASM y TASM.  Debido a que yo daba clases de Ensamblador y a que comencé con ASM, preferí inicialmente crear directivas propias a usar las que tenía el compilado TASM 2.0. (rutina en vez de proc, modelo en vez de model, _data en vez de .data... etc). De esta forma podía demostrar que realmente las directivas eran definibles. 
    Por eso, aunque muchos digan que lo que estoy haciendo  ya está construido en el compilador, quiero que vean que muchas de las directivas del TASM 2.0 son prescindibles, y que un buen programador puede usar un pequeño compilador y realizar cualquier tarea.
    Esto es importante para los que hemos tenido que compilar con otros compiladores mucho más simples, por ejemplo para otros microprocesadores, y en los que hemos querido aplicar las mismas reglas de programación que con el 8086.
    
     Por eso ruego paciencia. Primero aplicaré mis directivas, y veremos como resulta un código casi idéntico al del ensamblador TASM 2.0.  Así veremos, sin necesidad de desensamblar, lo que realmente hacen esas directivas, que simplifican el código, pero que ocultan cosas, al programador, que se deben conocer y entender.
    Sin embargo, si pensamos usar standares y acoplarnos a códigos de alto nivel, nos conviene usar las directivas incorporadas en el compilador TASM, para compatibilizar de forma sencilla el código con otros lenguajes de alto nivel.
   Por eso a partir de la entrada 50 del blog haré una comparativa de las dos formas y comenzaré a aplicar directamente el código TASM 2.0.

FUNCIONES ACOPLADAS EN MAIN.MAC
    

  Todo lo que iré poniendo ahora será para generar ficheros .exe. Más adelante, Cuando hayamos implementado programas ya con las directivas del TAM completas, lo generaremos en .com.

 Como siempre habrá una cabecera ".mac", bueno ".inc" si se desea, con las macros y definiciones de las funciones. Cuando simplifique los programas a versión completa las llamaré ".inc" para distinguirlas.

  En esta cabecera, como cabecera de inicialización de programa incluyo algunas sentencias de precompilación, que servirán para asignar memoria, segmentos, pila y por supuesto la estructura de lista de argumentos.
       
     Rutina (equivale a proc+ arg en TASM)
     Permite crear estructura para el paso de parámetros través de pila, de esta manera será muy sencillo declarar una función y pasarla hasta 10 variables . Declara  al tiempo la función como publica, al modo que lo hace "C", pero sin apenas darnos cuenta. Se verá mejor cuando coloque la función Graphics.

  _modelo (equivale a model en TASM)
     Sirve para definir el tipo de programa .com o .exe. si no se usa es .exe. Esto se usará paa definr los segmetos
      EN esta macro creamos una constante que podemos identificar en la macro _data, para asignar la zona de datos a DS o CS, según el programa sea . com o .exe. Esto no evitará tener que utilizar dos librerías (una para como y otra para exe) , si no queremos tener que compilar todas las librerías cada vez que hagamos un programa.
   Pero sí nos permitirá tener un programa único para cada librería y una de muy  forma simple compilarlo para uno y otro modo.

  _code (equivale a .code en TASM) 
      Nos define el comienzo de la zona de código.

  _data (equivale a .data en TASM) 
    Nos define el comienzo de la zona de datos. Puede estar antes o después del code, aunque en las funciones es recomendable que esté detrás.

   _end  (equivalente a end en TASM)
        Cierra el programa en caso un programa se debe indicar el nombre de la rutina principal
  _stack (equivale a .stack en TASM)
         Nos inicializa la pila al tamaño indicado en NUMERO

   Todas estas macros crean un entorno de trabajo equivalente al estandar de TASM y MASM, pero sin usar su directivas. Como solo usa if y macro con ellas puede crearse el entrono equivalente a TASM pero en el compilador inicial ASM. Todas estas macros pueden ser eliminadas y substituidas por las directivas equivalentes del TASM 2.0. Cosa que haremos más adelante.

   Con estas  macros podemos ver como se pueden crear no solo llamadas a funciones sino nuevas directivas de compilación. A partir de la entrada 50 del blog veremos como crear con las macros directivas de PROGRAMACIÓN ESTRUCTURADA tales como FOR o WHILE.

 Otras macros más interesantes aún pues no las tiene el TASM son:

   dim - Permite crear una variable compleja tomando una estructura como plantilla.
   asigdata - Nos permitirá reasignar una zona de memoria al segmento de datos.

   of_reg- devuelve la dirección del registro indicado de una tabla que se encuentre en memoria, creada bajo una estructura.

    exit- Fin de programa con salida al sistema.

   encriptar y desencriptar- Funciones especiales que permitirán encriptar parte de los datos del programa, de manera que no sean legibles mediante un Dump del código, pero si sean legibles una vez inicializado el programa.

   string, char, integer Definición de los tres tipos de variables más importantes. Serán usadas en la inicialización de los datos, por lo que están incluidas en el main como definición de variables.

   main - comienzo del programa. Es la encargada de llamar a la linea de comandos si se definieron parámetros y la encargada de asignar la zona de datos si se definió con la macro _data. Así mismo prepara el PSP para que la salvar la dirección de vuelta al sistema.

     Dentro del main existe una directiva por la cual si no se ha añadido la cabecera argum.mac, y por lo tanto no se ha definido la variable externa _line_comand, no se llamará a la función de la librería correspondiente. De esta forma, si no necesitamos argumentos no consumiremos código innecesario.
  Main parece una forma de iniciar el programa pero es mucho más, en realidad  inicializa el programa., reserva la memoria, recoge los argumentos de la línea de comando, y prepara la ejecución. Por ello tomé este nombre para crear una rutina especial, a la que llamaré siempre al inicio del programa ejecutable. Se encargará de inicializar la memoria, la pila del sistema y recoger los argumentos de la linea de comandos, para que posteriormente mediante argv argc  tratarlos.
   En el caso del main  no incluimos la función directamente en la cabecera, pues en este caso el tamaño de la función supera al código de llamada.

  Esta rutina no tendrá argumentos, y será llamada simplemente main
 
   Con esta cabecera estamos creando un entorno de trabajo equivalente al TASM completo, pero sin usar sus directivas más complejas.


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/>.
   ;Declaracion de una rutina (función) con paso de variables
    Esta macro crea una estructura de compilación para ser usada  posteriormente en la recogida de los datos pasados a la función.

;define modelo .com o .exe para definir forma de colocar assume en _data
_modelo macro tipo
   tipo equ 1
endm


rutina macro nombre,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10
   nombre&p struc
         dd ?
   irp arg,<arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10>
          ifnb <arg>
             arg  dw ?
          endif
        endm
    nombre&p  ends
        public nombre
nombre proc near

        push bp
        mov bp,sp
        endm


_end macro nombre
 ends  
   end nombre
endm

;genera la cabecera de datos
_data macro
ifndef com
    ends  ;asegura el cierre del segmento anterior
    data segment byte public 'data'
endif
endm

_code macro
    code segment byte public 'code'
    assume cs:code
ifdef com
  assume ds:code
else
    assume ds:data ; esto nos obliga a definir siempre un data aunque sea vacío
 endif
endm

;genera una pila con el tama¤o indicado
_stack macro NUMERO
     pila segment byte stack 'stack'
          db NUMERO dup (0)
     pila ends
     assume ss:pila
 endm


;coloca en pila de direccion del PSP para salir al dos y llama
;a la gesti¢n de la linea de comandos si se ha usado parametros
main macro
    push ds
    xor ax, ax
    push ax
ifdef _lin_comand
    call _lin_comand
endif
ifdef data
    asigdata data
endif
endm

;asigna un nuevo segmento de datos de trabajo
asigdata macro etiq
    assume ds:etiq
    mov ax, etiq
    mov ds, ax
endm

;dimensiona una tabla de numero de elementos con una estructura regis
dim macro tablas,regis,numero
        tablas regis numero dup (<>)
endm


; devuelve la direccion de un registro en una tabla en memoria
of_reg macro dest,lista,numero
      mov dest,offset lista[numero*type(lista)]
endm

;Sale al sistema devolviendo un codigo
exit macro codigo
     mov ah,4ch
ifdif <codigo>,<al>
     mov al,codigo
endif
     int 21h
endm

;encripta una zona de datos con un codigo dado
encriptar macro inicio,bytes,codigo
ifndef _encriptar
     extrn _encriptar:near
endif
         xor ax,ax
         push ax
         mov ax,codigo
         push ax
         mov ax,bytes
         push ax
         lea ax,inicio
         push ax
         call _encriptar
         add sp,8
 endm

;desencripta una zona de datos con un codigo dado
desencriptar macro inicio,bytes,codigo
ifndef _encriptar
        extrn _encriptar:near
endif
         mov ax,28h
         push ax
         mov ax,codigo
         push ax
         mov ax,bytes
         push ax
         lea ax,inicio
         push ax
         call _encriptar
         add sp,8
 endm

;define una cadena de entrada de texto para el scanf
string macro nombre,long
     nombre db long+1,0,long+2 dup (0)
endm

char macro var,ini
  ifb <ini>
      var db ?
  else
      var db ini
  endif
endm

integer macro var,ini
  ifb <ini>
      var dd ?
  else
      var dd ini
  endif
endm

viernes, 3 de mayo de 2013

CONTROL DEL RATÓN

  Esta es la librería para control del ratón. Como en "C" la he llamado MOUSE.
  En  este caso, al ser un código muy corto, he introducido el código como macro. Hacerlo como librería no aporta reducción de código, pues la implementación de código necesario para  pasar los datos a la función de la librería, a través de pila, ocupa tanto como el código mismo.
   Por lo tanto es mejor usar directamente el código en cada función, que llamar a una rutina asociada de la librería.

   En todas la llamadas se utiliza la pila para mantener transparentes los registros, de forma que llamar a la función no nos cause problemas con los datos que ya tenemos en los registros. Esto nos permite, como en "C", usar de forma cómoda las funciones sin preocuparnos por el estado de los datos almacenadas en los registros antes de la llamada.
  
  Por ello, en la mayoría de estas macros aparecen una serie de Push a la pila, que luego serán extraídos en orden inverso de esta. Estos registros salvados en la pila son precisamente los utilizados por nuestra rutina.

 Las macros nos permitirán crear de una forma cómoda y potente llamadas a nuestras funciones

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

ON = 1    ; definición de estado activado
OFF = 0   ; definición de estado apagado


; definición de constantes
;acciones posibles del ratón
m_move equ 1
m_p_left equ 2  ; Pulsar botón izquierdo
m_r_left equ 4  ; Pulsar soltar izquierdo
m_p_right equ 8   ; Pulsar botón derecho
m_r_right equ 16   ; Pulsar soltar derecho
m_p_medio equ 32   ; Pulsar botón medio
m_r_medio equ 64    ; Pulsar soltar medio


; Muestra u oculta el cursor del ratón
; la opcion es ON y OFF
mouse macro opcion
        mov ax,2-opcion
        int 33h
      endm

;reinicializa el ratón
resmouse macro
        mov ax,0
        int 33h
      endm

;coloca el ratón en una posición dada
putmouse macro x,y
      push cx  
      push dx
      mov ax,4
      mov cx,x
      mov dx,y
      int 33h
      pop dx
      pop cx
     endm

;lee los botones del ratón en ax 1 izquierdo,2 derecho,4 medio
getmouse macro
        push bx
        push dx
        mov ax,3
        int 33h
        mov ax,bx
        pop dx
        pop bx
     endm

;toma la posicion x del ratón y la devuelve en ax
getmousex macro
        push bx
        push cx
        push dx
        mov ax,3
        int 33h
        mov ax,cx
        pop dx
        pop cx
        pop bx
     endm

;toma la posicion y del ratón y la devuelve en ax
getmousey macro
        push bx
        push cx
        push dx
        mov ax,3
        int 33h
        mov ax,dx
        pop dx
        pop cx
        pop bx
     endm

;comprueba la corecta instalaci¢n del ratón
mouseok macro
        mov ax,0
        int 33h
        dec ax
        endm


;Activa un procedimiento asociado al ratón
mouseint macro accion,procedure
        mov ax,0ch
        push cx
push dx
        mov cx,accion
        push es
        push cs
        pop es
        mov dx,offset procedure
        int 33h
        pop es
        pod dx
        pop cx
        endm



;TOMA EL MOVIMIENTO DEL RATÓN DESDE LA ULTIMA LLAMADA
;SOBRE EL EJE X
movx_mouse macro
        push cx
        mov ax,11
        int 33h
        mov ax,cx
        pop cx
        endm
     

;TOMA EL MOVIMIENTO DEL RATÓN DESDE LA ULTIMA LLAMADA
;SOBRE EL EJE Y
movy_mouse macro
        push dx
        mov ax,11
        int 33h
        mov ax,dx
        pop dx
        endm