Vistas de página en total

sábado, 21 de septiembre de 2013

BASE DE DATOS

Hoy voy a colocar un programa mucho más laborioso, y lo voy a hacer de una sola vez.
     Este programa es un ejemplo de uso de las funciones de fichero, y en concreto del acceso a ficheros mediante la función rseek.
     En su día hice este programa para mostrar como crear y manipular registros en un a base de datos con ASM. Ahora me sirve para mostrar en un solo programa como utilizar todo lo que hasta ahora he colocado.

    El programa almacena las notas de alumnos en un curso. Cada fichero .DAT sería un curso.

  El programa pedirá el nombre de un fichero que usará como base de datos, para almacenar las notas del curso. Si se da un nombre que no existe, se creará el fichero. 



Si no damos un nombre, y pulsamos enter, se abrirá una ventana emergente con el directorio actual, para seleccionar el fichero deseado entre las bases de datos existentes

Una vez elegido el fichero se abrirá una pantalla con cuatro ventanas. 
En la superior-izquierda estará el listado de registros de la base de datos, ordenados por entrada. En esta ventana se verá  una flecha que indicará el registro seleccionado. Los valores de este registro se mostrarán en la ventana superior-derecha. Mediante las teclas up y dw se podrá mover la flecha por el listado de registros para ir seleccionando cada uno.

En la ventana inferior izquierda estará el menú y en la Inferior derecha la ayuda y los mensajes que va dando el programa.

 


Como se ve el interfaces es muy simple. Pero en este caso, el ejemplo, es para ver como crear un registro, y usarlo dentro de una base de datos. Es el típico programa Altas-Bajas-Modificaciones-Consultas, de un ejercicio de Programación de bases de datos.

  El programa almacena las notas de alumnos en un curso.
 Ejemplo ya compilado en Notas.exe

NOTAS.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
include stdio.mac
include io.mac
include string.mac
include math.mac
include window.mac

.model compact,pascal

Horizontal equ 205
Vertical equ 186
eds equ 187
ide equ 188
eis equ 201
eii equ 200
medio equ 206
mb equ 202
ms equ 203
mi equ 204
md equ 185
eom equ "$"

;Definición del registro de la báse de datos
registro struc
        string Nom,25  
        string Eva_1,4
        string Eva_2,4
        string Eva_3,4
        db 13
registro ends

.stack 512

.data
   mens0    dB " M E N U ",0
   mens1    dB " 1.- Altas.",0
   mens2    dB " 2.- Bajas.",0
   mens3    dB " 3.- Modificaciones.",0
   mens4    dB " 4.- Salir.",0
   mens5    dB "A L T A S ",0
   mens7    dB "B A J A S ",0
   mens8    dB "Se borrará la persona indicada.",0
   mens9    dB "M O D I F I C A C I O N E S ",0
   MENS10   dB "No se ordenara.",0
   mens11   dB "A Y U D A",0
   mens12   dB "Elige un numero del 1 al 4.",0
   mens13   dB " Para mover la flecha de la primera",0
   mens14   dB "pantalla.",0
   mens15   dB " Para mover la flecha de la primera",0
   mens16   dB "pantalla.",0
   mens17   dB "L I S T A D O ",0
   mens19   dB "D A T O S ",0
   mens20   db "Tabla vacia ",0
   mens21   db "Imposible eliminar elementos. ",0
   mens22   db "Pulse una tecla para continuar.",0
   mens40   dB "¿Esta usted seguro (s/n)?",0
   flechas  dB "-- ",0
   mensno   db "Eva-1: ",0
   mensdi   DB "Eva-2: ",0
   menste   DB "Eva-3: ",0
   mensdn   DB "Nombre: ",0

  ;Marcos de ventana
   l1       db eis,38 dup (horizontal),ms,39 dup (horizontal),eds,0
   l2       db mi,38 dup (horizontal),medio,39 dup (horizontal),md,0
   l3       db eii,38 dup (horizontal),mb,39 dup (horizontal),ide,0
   solicita db "Digame el nombre de la base de datos o pulse enter",0
   base db "*.dat",0
   extension db ".dat",0
   string   file1,20
   op       DB "0"
   lin      DB 0
   col      DB 0
   xlin     DB 0
   res      DB 0
   flecha   DB 0
   pos      dw 0
   indice   DW 0
   comienzo Dw 0
   hand1    dw 0
   long1    dw 0,0
   long2    dw 0,0

;definición de bufer para lectura
   dim      leer, registro, 1
   dim      leer2,registro,1
   buffer   db 255 dup (0)



.code
     inicio proc far
        main
        push ds
        pop es
        clrscr
        setcolor verde
        gotoxy 20,10
        puts solicita
        gotoxy 20,12
        setcursor on
        scanf file1
        cmp file1+1,0
        jnz abase
        windir 10,10,base,file1+2
        jmp por_vent
abase:
        strcat file1+2,file1+2,extension
por_vent:
        setcolor blanco
        open file1+2, _R_W, hand1
        jnc bien
        new_file file1+2,_ARCHIVO,hand1

  bien:
        fseek hand1,_INICIO,0
        read hand1,2,indice
        setcursor off
        call mascara

     panta:
        call menu
     panta1:
        call listado
     lee:
        gotoxy 79, 23
        getch op
        cmp op, 0
        je lee
        cmp op, "1"
        jne s1
        clswindow 12,41,21,78
        gotoxy 55,13
        printf mens5
        call insertar
        jmp panta
     s1:
        cmp op, "2"
        jne s2
        clswindow 12,41,21,78
        gotoxy 55,13
        puts mens7
        gotoxy 42,16
        puts mens8
        call confirma
        jnz lee1
        jmp lee
    lee1:
        call elimina
  ;; test y realizacion de la confirmacion

        jmp panta
     s2:
        cmp op, "3"
        jne s3
        clswindow 12,41,21,78
        gotoxy 47,13
        puts mens9
        gotoxy 42, 16
        puts mens10
        call confirma
        jnz lee2
        jmp lee
    lee2:
        call modificar
        jmp panta
     s3:
        cmp op, "P"
        jne s4
        call baja
        jmp panta1
     s4:
        cmp op, "H"
        jne s5
        call sube
        jmp panta1
     s5:
        cmp op, "4"
        je final
        jmp panta1
    final:
        setcolor normal
        clrscr
        close hand1
        ret
inicio endp

baja proc near
        xor ax,ax
        mov al,flecha
        add ax, comienzo
        INC AX
        cmp ax,indice
        jAe b3
        cmp flecha,7
        jae b1
        inc flecha
        jmp b3
    B1:
        inc comienzo
     b3:
        ret
baja endp
;; pide confirmacion y devuelve en la bandera  z=0 si se dijo NO y
;; z=1 si se dijo
;; SI
;; no modifica nigún registro

confirma proc near  uses ax bx dx
   otro:
        gotoxy 42,20
        puts mens40
        gotoxy 42,21
        getch op
        mov ax,0
        cmp op,'s'
        je conf
        cmp op,'S'
        je conf
        cmp op,'n'
        je salir
        cmp op,'N'
        je salir
        jmp otro
  conf:
        mov ax,1
  salir:
        or ax,ax
        pushf
        clswindow 12,41,21,78
        popf
        ret
confirma endp
sube proc near
        cmp flecha, 0
        je su1
        dec flecha
        jmp su3
     su1:
        cmp comienzo,0
        je su3
        dec comienzo
     su3:
        ret
sube endp

mascara proc near
        setcolor blanco
        clrscr
        mov cl, 1
     inicios0:
        gotoxy 0, cl
        putchar vertical
        gotoxy 39, cl
        putchar vertical
        gotoxy 79, cl
        putchar vertical
        add cl, 1
        cmp cl, 22
        jne inicios0
        gotoxy 0,0
        puts l1
        gotoxy 0,11
        puts l2
        gotoxy 0,22
        puts l3
        ret
mascara endp


menu PROC near
          gotoxy 15,13
          puts mens0
          gotoxy 10,15
          puts mens1
          gotoxy 10, 17
          puts mens2
          gotoxy 10, 19
          puts mens3
          gotoxy 10, 21
          puts mens4
          gotoxy 55,13
          puts mens11
          gotoxy 42,15
          puts mens12
          gotoxy 42,17
          puts mens13
          gotoxy 44,18
          puts mens14
          gotoxy 42,20
          puts mens15
          gotoxy 44,21
          puts mens16
          ret
menu endp


listado proc near
        setcursor off
        clswindow 1,1,10,38
        gotoxy 10, 1
        puts mens17
        cmp indice,0
        jne nofuer
        jmp fuer
nofuer:
        mov cl, flecha
        mov ax,comienzo
        mov pos,ax
        inc cl
        inc cl
        gotoxy 1, cl
        puts flechas
         mov cl,2
  nuevocampo:
        push cx
;; tomamos la posicion inicial del registro
        inc pos
        rseek hand1, pos,registro
        dec pos
        mov cx,size registro
        read hand1,cx,leer
        mov si, offset leer
        pop cx
        gotoxy 5,cl
        printf [si].Nom
        inc cl
        inc pos
        mov ax,indice
        cmp pos,ax
        jae fuer
        cmp cl,10
        jne nuevocampo
   fuer:
        call presentar
          ret
listado endp


presentar proc near
        clswindow 1,41,10,78
        call masentrada
        gotoxy 50,1
        puts mens19
        cmp indice,0
        jne con_pre
        jmp end_pre
      con_pre:
        xor Cx,Cx
        mov Cl,flecha
        add Cx,comienzo
        inc cx
        rseek hand1,Cx,registro
        dec cx
        mov cx,size registro
        read hand1,cx,leer
        mov si, offset leer
        gotoxy 51, 3
        printf [si].Nom
        gotoxy 51, 5
        printf [si].Eva_1
        gotoxy 51, 7
        printf [si].Eva_2
        gotoxy 51, 9
        printf [si].Eva_3
   end_pre:
        ret
presentar endp

elimina proc near  uses es
        cmp indice,0
        jne elim
        clswindow 12,41,21,78
        gotoxy 42,15
        puts mens20
        gotoxy 42, 17
        puts mens21
        gotoxy 42,19
        puts mens22
        getch al
        jmp copi1
 elim:
        cld
        push ds
        pop es
        xor bx,bx
        mov bl,flecha
        add bx,comienzo
        inc bx
  copia:
        inc bx
        rseek hand1,bx,registro
        dec bx
        mov cx,size registro
        read hand1,cx,leer
        rseek hand1,bx,registro
        dec  bx
        mov cx,size registro
        write hand1,cx,leer
        inc bx
        inc bx
        cmp bx,indice
        jbe copia
        dec indice
        fseek hand1,_INICIO,0
        write hand1,2,indice
        cmp flecha,0
        jbe copi2
        dec flecha
        jmp copi1
 copi2:
        cmp comienzo,0
        jbe copi1
        dec comienzo
 copi1:
        ret
elimina endp

insertar proc near
        call masentrada
        gotoxy 50,1
        puts mens5
        setcursor on
        mov si, offset leer
        gotoxy 51, 3
        scanf [si].Nom
        gotoxy 51, 5
        scanf [si].Eva_1
        gotoxy 51, 7
        scanf [si].Eva_2
        gotoxy 51, 9
        scanf [si].Eva_3
        inc indice
        rseek hand1, indice,registro
        dec indice
        mov cx,size registro
        write hand1,cx,leer
        inc indice
        fseek hand1,_INICIO,0
        write hand1,2,indice
    ins1:
        call ordena
        setcursor off
        clswindow 1,41,10,78
        ret
insertar endp

ordena proc near
        mov dx,indice
        cmp dx,1
        ja otr_ord
        jmp end_ordena
   otr_ord:
        rseek hand1, dx,registro
        dec dx
        mov cx,size registro
        read hand1,cx,leer
        rseek hand1, dx,registro
        dec dx
        mov cx,size registro
        read hand1,cx,leer2
        strcmp  leer2.Nom+2,leer.Nom+2
        jbe end_ordena
        inc dx
        rseek hand1, dx,registro
        dec dx
        mov cx,size registro
        write hand1,cx,leer
        inc dx
        inc dx
        rseek hand1, dx,registro
        dec dx
        mov cx,size registro
        write hand1,cx,leer2
        cmp dx,1
        jbe end_ordena
        jmp otr_ord
    end_ordena:
        ret
ordena endp


modificar proc near
        setcursor on
        xor cx,cx
        mov cl,flecha
        add cx,comienzo
        push cx
        inc dx
        rseek hand1,cx,registro
        dec dx
        mov cx,size registro
        read hand1,cx,leer
        mov bx, offset leer
        lea di,[bx].Nom
        push bx
        gotoxy 51,3
        call modif
        pop bx
        lea di,[bx].Eva_1
        push bx
        gotoxy 51,5
        call modif
        pop bx
        lea di,[bx].Eva_2
        push bx
        gotoxy 51,7
        call modif
        pop bx
        lea di,[bx].Eva_3
        push bx
        gotoxy 51,9
        call modif
        pop bx
        pop cx
        inc dx
        rseek hand1,cx,registro
        dec dx
        mov cx,size registro
        write hand1,cx,leer
        setcursor off
        ret
modificar endp

modif proc near  uses es
        push ds
        pop es
        cld
        mov si,offset buffer
        mov al,[di]
        mov [si],al
        scanf  buffer

        cmp byte ptr [si+1],0
        je fin_modif
        xor cx, cx
        mov cl,[si+1]
        add cx,3
        rep movsb
   fin_modif:
       ret
modif endp

masentrada proc near
        clswindow 1,41,10,78
        gotoxy 43, 3
        puts mensdn
        gotoxy 43, 5
        puts mensno
        gotoxy 43, 7
        puts mensdi
        gotoxy 43, 9
        puts menste
        ret
masentrada endp
end inicio





   

jueves, 19 de septiembre de 2013

COMANDO DEL SISTEMA "ATRIB"

   Este es otro ejemplo de construcción de un comando para DOS. En este caso es un Atrib. Muestra o modifica los atributos de uno o más ficheros.
   Este es un ejemplo de uso de los comandos de búsqueda de ficheros y del uso de la DTA. Aquí usamos la gestión de defectos de EROR.MAC



ATRIB.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 dos.mac
include error.mac
include argum.mac
include io.mac
include stdio.mac
include string.mac
include main.mac


.model compact,pascal
.stack 100
.data
        todo db "*.*",0
        espac db ".........",0
        retor db 10,13,0
        mens1 db "(c) J.A. MONEO Fdez",10,13
              db 'formato: ATRIB [unidad:][path]<nombre de fichero> <parametros>',10,13
              DB 'O..oculto,V..visible,L..solo lectura,E..lectura/escritura,',10,13
              db 'S..sistema,N..normal',10,13,0
        PATH DB 40 DUP (0)
        completo db 40 dup (0)
        dta _dta ?

.code
 oculto proc far
       main
      ; este borrado de pantalla no sería necesario en dos
      ;pero al usar al ventana de windows, por alguna razón no se refresca la pantalla 
      ; si no lo usamos antes.
       clrscr           
       xor cx,cx
       setdta dta
       argc cl
       cmp cl, 2       ;dos parámetros , se indica atributo
       jne  sig
       jmp oculto0
  sig:     
       cmp cl,1        ;un parámetro, se pide listar atributos
       je busca1
  Faltan:       
       puts mens1    ; faltan parámetros
       exit 1
busca1:
       argv 1,si
       findfirst todo,_TODOS
       jc error

   lis2:
       call p_atr
       findnext
       jnc lis2
       puts retor
       exit 0
  oculto0:
       argv 1,si
       getpath path,[si]
       findfirst dta,_TODOS
       jnc bueno
 error:
       errext
       puts retor
       exit 1
bueno:
       ;analisis del parámetro
       argv 2,bx            
       strupr [bx]
oculto2:
       mov dl,dta._attr
       cmp byte ptr [bx],'L'
       jne oculto3
       or dl,_O_READ
       JMP fin_oculto

 OCULTO3:
       CMP byte ptr [BX],'E'
       JNE OCULTO4
       MOV Al,_O_READ
       XOR Al,0FFH
       AND Dl,Al
       JMP fin_oculto

oculto4:
       cmp byte ptr [bx],'O'
       jne oculto5
       mov al,_hide
       or dl,al
       JMP fin_oculto
oculto5:
       cmp byte ptr [bx], 'V'
       jne oculto6
       mov al,_hide
       xor al,0ffh
       and dl,al
       JMP fin_oculto

oculto6:
       cmp byte ptr [bx],'S'
       jne oculto7
       mov al,_SISTEM
       or dl,al
       JMP fin_oculto
oculto7:
       cmp byte ptr [bx], 'N'
       jne FIN_OCULTO
       mov al,_SISTEM
       xor al,0ffh
       and dl,al


fin_oculto:
       inc bx
       cmp byte ptr [bx], 0
       je fin_oculto1
       jmp oculto2
fin_oculto1:
       strcat completo,path,dta._nombre
       setattr completo,dx
       jnc seguir
       cmp ax,5
       je seguir
       jmp error
 seguir:
       findnext
       jc salir
       jmp oculto2
  salir:
       ret

   oculto endp
p_atr proc near
;imprime los atributos del fichero
       puts retor
       puts dta._nombre
       puts espac
       test dta._attr,_o_read
       jz ot1
       putchar 'L'
   ot1:
       test dta._attr,_hide
       jz ot2
       putchar 'O'
   ot2:
       test dta._attr,_sistem
       jz ot3
       putchar 'S'
   ot3:
       test dta._attr,_vol
       jz ot4
       putchar 'I'
   ot4:
       test dta._attr,_Dir
       jz ot5
       putchar 'D'
   ot5:
       test dta._attr,_archivo
       jz ot6
       putchar 'A'
   ot6:
       ret
p_atr endp
end oculto

martes, 17 de septiembre de 2013

RUTINAS ERROR


   Para completar la librería hoy pongo las rutinas asociadas a la cabecera de error.mac.
   Con estas funciones, se podrá presentar en pantalla, el código texto asociado al error que el sistema nos indique al hacer una operación.

   A partir de ahora ya tenemos una librería básica bastante potente para poder hacer casi de todo.
   Por supuesto se podrá ampliar, pero no vale la pena, ya que todo esto es de MS-DOS y ahora estamos en Windows. Por lo tanto, si se desea más potencia es mejor pasar a TASM 11 y usar Windows. Sin embargo creo que con todas las entradas de este blog he mostrado una forma de estructurar y  gestionar los programas, que para mí, es muy potente y sencilla de manejar, por su aproximación a los lenguajes de alto nivel, y por su claridad en la lectura del programa principal.
   Por supuesto cuando programo en los nuevos ensambladores, retoco todas las funciones y me creo mis propias macros de llamada que necesito, con la misma filosofía; de manera que me quede la estructura de programa clara.
   Como ya he dicho, la función Invoke,  creada y usada en las llamadas a funciones Windows en los compiladores NASM y WINASM, es muy cómoda de crear, pero muy engorrosa de usar. Para usarla tengo que conocer todos los nombres y paso de parámetros de cada función, y luego el programa  resulta engorroso de leer, pues  simplemente está lleno de invoke.
   Por lo tanto, aunque sea más laborioso al principio, siguiendo mi filosofía “ Trabaja un poco al principio, para no volver a trabajar”, prefiero crearme mis macros de llamada para las funciones que realmente uso, reuniendo,  si es necesario, varios invoke en un solo comando.
 
    Por todo esto a partir de ahora ya no añadiré librerías ni macros. Ya están todas las que se necesitan. Añadiré solo programas como ejemplo de lo que podemos hacer con ensamblador.  Simplemente para eliminar miedos de algunos a este lenguaje, y demostrar que con organización es igual de fácil que cualquier otro.







ERROR.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 stdio.mac
;rutina de gestión de errores
;(c) José Angel Moneo Fdez

.model compact,pascal
.data
     ;; mensajes de error de print_error
_error_extendido dw 0,_ee1,_ee2,_ee3,_ee4,_ee5,_ee6,_ee7,_ee8,_ee9
                 dw _ee10,_ee11,_ee12,_ee13
                 dw _ee14,_ee15,_ee16,_ee17
                 dw _ee18,_ee19,_ee20,_ee21,_ee22,_ee23,_ee24
                 dw _ee25,_ee26,_ee27,_ee28,_ee29,_ee30,_ee31
                 dw _ee32,_ee33,_ee34,_ee35,_ee36,_ee37,_ee38
                 dw _ee39,_ee40,_ee41,_ee42,_ee43,_ee44,_ee45
                 dw _ee46,_ee47,_ee48,_ee49,_ee50,_ee51,_ee52
                 dw _ee53,_ee54,_ee55,_ee56,_ee57,_ee58,_ee59
                 dw _ee60
_ee1 db "Número de función no válido",0
_ee2 db "Fichero no encontrado",0
_ee3 db "Via de acceso no encontrada",0
_ee4 db "No hay mas handles disponibles",0
_ee5 db "Acceso denegado",0
_ee6 db "Handle no Válido",0
_ee7 db "Bloque de control de memoria destruidos",0
_ee8 db "No hay memoria suficiente",0
_ee9 db "Direccion de bloque de memoria no válido",0
_ee10 db "Bloque de entorno no valido",0
_ee11 db "Formato no valido",0
_ee12 db "Codigo de acceso a fichero no valido",0
_ee13 db "Datos no validos",0
_ee14 db " ",0
_ee15 db "Especificacion de unidad no valida",0
_ee16 db "Intento de borrar el directorio activo",0
_ee17 db "No es el mismo dispositivo",0
_ee18 db "No hay más ficheros",0
_ee19 db "El disco está protegido contra escritura",0
_ee20 db "Identificador de unidad de disco desconocida",0
_ee21 db "Unidad de disco no preparada",0
_ee22 db "Comando de disco desconocido",0
_ee23 db "Error de datos de disco",0
_ee24 db "Longitud de escritura solicitada para disco incorrecta",0
_ee25 db "Error de búsqueda de disco",0
_ee26 db "No es un disco DOS",0
_ee27 db "Sector de disco no encontrado",0
_ee28 db "Impresora sin papel",0
_ee29 db "Error de escritura",0
_ee30 db "Error de lectura",0
_ee31 db "Fallo general",0
_ee32 db "Violacion de fichero compartido",0
_ee33 db "Violacion de bloqueo de fichero",0
_ee34 db "Cambio de disco no valido",0
_ee35 db "No hay FCB disponible",0
_ee36 db "Desbordamiento de buffer compartido",0
_ee37 db " ",0
_ee38 db " ",0
_ee39 db " ",0
_ee40 db " ",0
_ee41 db " ",0
_ee42 db " ",0
_ee43 db " ",0
_ee44 db " ",0
_ee45 db " ",0
_ee46 db " ",0
_ee47 db " ",0
_ee48 db " ",0
_ee49 db " ",0
_ee50 db "Solicitud de red no soportada",0
_ee51 db "Ordenador remoto no escuchado",0
_ee52 db "Nombre duplicado en red",0
_ee53 db "Nombre de red no encontado",0
_ee54 db "Red ocupada",0
_ee55 db "El dispositivo de red no existirá mas tiempo",0
_ee56 db "Excedido el límite de comandos del BIOS de red",0
_ee57 db "Error de hadware del adaptador de red",0
_ee58 db "Respuesta incorrecta de la red",0
_ee59 db "Error de red inexperado",0
_ee60 db "Adaptador remoto incompatible",0
;;
;;
.code

    public _print_error
    public _p_error
;Localiza el error del sistema e imprime su texto asociado  
_print_error proc near  uses  ax bx cx dx si di es ds
        mov ah,59h
        mov bx,0
        int 21h
        call _p_error
        ret
_print_error endp

;imprime uno de los textos de error indicando el número de error
_p_error proc near  uses si di bx,numero
        mov bx,offset _error_extendido
        mov si,numero
        cmp si,60
        ja sal_p_error
        shl si,1
        mov di,[bx+si]   ;pasamos el puntero deseado a di, para pasarlo a la macro puts
        puts  [di]
  sal_p_error:
        ret
_p_error endp

domingo, 15 de septiembre de 2013

CABECERA ERROR


    Hoy vamos a terminar de completar las funciones básicas para poder crear programas.  Y lo haremos con unas funciones de presentación de errores.
   Como siempre primero las cabeceras.
    A partir de ahora ya tenemos una librería básica bastante potente para poder hacer casi de todo.




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

errext macro
ifndef _print_error
       extrn _print_error:near
endif
       call _print_error
endm

perror macro numero
ifndef _p_error
        extrn _p_error:near
endif
        mov ax,numero
        push ax
        call _p_error
        pop ax
 endm

viernes, 13 de septiembre de 2013

SWITCH...CASE

    Como había anunciado, voy a ampliar la cabecera Hi_LEVEL. Vamos a crear un conjunto de macros para poder realizar el SWITCH...CASE de forma más cómoda.
   A partir de ahora, igual que sucede con el FOR y el WHILE,  podremos utilizar estas macros que funcionan como generador de código para escribir el programa de forma más clara.

  Como todos sabemos, uno de los problemas del ensamblador es su linealidad. As ser tan lineal, resulta plano. Es decir, en un programa, no distinguimos de forma clara la estructura. Dado que las funciones son las mismas en todos los caso, perdemos la visión de conjunto.  Esta macro, junto con todos las que están en HI_LEVEL, tienen la misión de aclarar un poco el programa de manera que sea fácil distinguir las estructuras de programa, bucles y cases.

   Como ya se habrá visto, esta es una gran preocupación para mí. por eso me molesto tanto en crear macros para cada función. Quiero que el programa quede lo más claro, sin necesidad de comentarios, de manera que pueda ser leído e interpretado fácilmente aunque pase mucho tiempo.

   Parece que esta filosofía ha funcionado, pues lo que estoy poniendo hace 20 años que lo hice, y me está siendo muy sencillo recuperarlo e incluso ampliarlo con programas nuevos según voy escribiendo este Blog.

   Empecemos pues.

 Las macros a incorporar a HI_LEVEL son estas.

;inicio del switch. Se indica la varible a mirar.
;esta varialbe debe de ser un byte
switch macro var
       mov al,var
      ifndef $h
          $h = 0
       endif
       $h = $h + 1
endm


; se compara con val, usando la operación indicada y si es cierta se llama
; a la subrutina indicada
case macro val,op,rutina
local sigue
      cmp al,val
       j&op sigue
      call &rutina
     $recup1 %$h
      jmp $simbolo
sigue:
endm


;marca la parte que será ejecutada siempre que no se cumpla ningún case
; el código se colocará siempre dentro del switch
default macro
endm


; Marca fin de witch
endswitch macro
     $salvar1 %$h
endm 


EJEMPLO
 Aquí voy a poner un ejemplo para ver el uso de la estructura. Si se compila y linka con Turbodebuger se podrá ver lo que se genera. Pero este programa no tiene una funcionalidad. Simplemente permitirá ver la estructura creada.

; 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
include stdio.mac
include Hi_level.mac

.model compact,pascal
.stack 100

.data

op db 0

.code

p proc
      main
     clrscr
     getch op
  switch  op                           ; comienza el switch indicando la variable a comparar
       case 'h',e,casoh             ; caso de ser = a h llama a la subrutina casoh
       case 'l',be,casol           ; caso de ser <= a l llama a la subrutina casol       

  default
          mov ah,50              ; secuencia en caso de no cumplirse nada
   endswitch                      ; fin del swirch

 
     getch op


;Segundo switch  
       switch  op
       case 'm',e,casoh
       case 'n',be,casol 
       default

          mov ah,40
    endswitch 
     exit 0
p endp
casoh proc near
     ;falta el código pues es un ejemplo

    ret
endp
casol proc near
    ;falta el código pues es un ejemplo
    ret
endp
end p


miércoles, 11 de septiembre de 2013

COMANDO "TYPE"

    

  Con todo lo que he ido publicando en este blog hasta ahora, ya estamos en disposición de hacer el primer comando del sistema. En este caso voy a exponer el comando Type. Para evitar que choque con el comando interno del sistema vamos a llamarlo MyType.
      Este programa imprimirá un fichero sobre pantalla o sobre impresora. Y podremos hacerlo de forma continua o de forma paginada.
      Llevará como todos los comandos una ayuda implícita que podrá ser llamada a través de la línea de comandos con '/H', '/h', o '/?'. Cuando se introduzca alguno de estos comandos en la línea aparecerá la siguiente información.

      Este comando muestra el fichero especificado"
      Por Jose Angel Moneo"
      Formato: ver [unidad:][trayecto]fichero(s)        [/M] [/P][/H][/?]

                   /M ....Por páginas
                  /P .....Sobre impresora
                  /H o /?.......Ayuda

   En este caso el programa es muy sencillo. Solo tiene la rutina principal en la que analizamos y ejecutamos el comando y una subrutina para imprimir el fichero. Por lo tanto lo incluyo de forma íntegra en esta entrada.
   Es sencillo, no porque sea fácil hacer esto en ensamblador, sino porque ya dispongo de una librería de funciones y una estructura de programa suficientemente potente, para programar como si lo estuviera haciendo en alto nivel.
    La rutina principal lee la línea de comandos y analiza los parámetros pasados, para realizar posteriormente la acción correspondiente.
    Si no indicamos fichero en la línea de comandos, este Type, solicitará el fichero por ventana emergente mediante el windir.
    En el caso de que se pulse EXC y no se seleccione fichero en el windir, la función saldrá sin hacer nada.
    En una impresión paginada (/M) el fichero se irá imprimiendo, deteniendo el proceso al final de la pantalla y escribiendo "------MAS-----", para indicar que el fichero no ha terminado.
    Al final de proceso, siempre pedirá un CR antes de salir al sistema.

    En este caso, como se ve también he utilizado la macro FOR...NEXT, para realizar los bucles. Existe un SWITCH, en el programa que ha sido implementado de forma directa en ensamblador, ya que es muy simple. En la siguiente entrada creare una macro SWITCH...CASE, para poder ver como simplificar  el programa, aunque en este caso es innecesario, ya que está muy claro.


MYTYPE.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 io.mac
include argum.mac
include stdio.mac
include string.mac
include main.mac
include window.mac
include hi_level.mac

 .model compact,pascal

.stack 300

.data
dta _dta ?
mens1 db 10,13,"Par metro incorrecto",10,13,0
help db "Este comando muestra el fichero especificado"
     db 10,13,"Por Jose Angel Moneo"
     db 10,13,"Formato: ver [unidad:][trayecto]fichero(s)"
     db "   [/M] [/P][/H[/h] ",10,10,13, "    /M ....Por p ginas",10,13
     db "    /P .....Sobre impresora",10,13,0,"    /H o /? .....Ayuda",10,13,0

mens2 db "falta nombre de fichero",0
mens3 db "El fichero ",0
mens4 db " no existe.",0
mens6 db " No se puede abrir ",0
mens7 db "------------------ Presentando fichero ",0
mens8 db "------------------",10,13,0
mens9 db "-----------MAS----------",10,13,0
hay db 0
sw db 0
sw1 db 0
i db 0
salida dw 0
todo db "*.*",0
total db 40 dup (0)
camino db 40 dup (0)
buffer db 80 dup (0)
handle dw 0
ends

.code

Type proc far
        main
        setdta dta
        argc dl
        inc dl    ;inc 1 ya que cl empieza en 1   
  FOR cl,1,dl
        argv cl,si
        cmp byte ptr [si],'/'
        je switch1
        mov hay,1
        jmp fin_for1

switch1:
        mov ah,[si+1]
        cmp ah,'H'
        je irah
        cmp ah,'h'
        je irah
        cmp ah,'?'
        je irah
        cmp ah,'M'
        je iram
        cmp ah,'m'
        je iram
        cmp ah,'P'
        je irap
        cmp ah,'p'
        je irap

   default:
        puts mens1
        puts help
        exit 1
   irah:
        puts help
        exit 0
  iram:
        mov sw,1
        jmp fin_for1
  irap:
        mov sw1,1
  fin_for1:
     NEXT cl

        cmp hay,0
        jne cpsw
        setcursor off
        windir 5,20,todo,dta._nombre
        cmp dta._nombre,0
        je nada
        call presenta
        exit 0
  nada:
        exit 1

cpsw:
        cmp sw1,1
        jne pantalla
        mov salida,_stdprn
        mov sw,0
        jmp alfor2

Pantalla:
        mov salida,_stdout
alfor2:

   FOR CL,1,DL
       argv cl,si
       cmp byte ptr [si],'/'
       je fin_for2
       getpath camino,[si]
       findfirst [si],_archivo
       jnc presentar
       puts mens3
      
puts  [si]
      
puts mens4
       jmp fin_for2
Presentar:
        call presenta
in_while:
        findnext
        jc fin_for2
        call presenta
        jmp in_while
fin_for2:
   NEXT CL
        exit 0
type endp


presenta proc near
        push cx
        strcpy total,camino
        strcat total,total,dta._nombre
        open total,_r,handle
        jnc abierto
       
puts mens3
       
puts total
       
puts mens6
        pop cx
        ret

abierto:
        clrscr
       
puts mens7
       
puts total
       
puts mens8
        mov cx,3
in_buc:
        read handle,80,buffer
        mov bx,ax
        cmp bx,0
        je salir_buc
        mov si,0
 resto:
        cmp si,bx
        je fin_buc
        write salida,1,[buffer+si]
        cmp byte ptr [buffer+si],10
        pushf
        inc si
        popf
        jne resto
        inc cx
        cmp cx,23
        jne resto
        cmp sw,1
        jne resto
       
puts mens9
        getch al
        mov cx,1
fin_buc:
        jmp in_buc
salir_buc:
        close handle
        getch al
        pop cx
        ret
presenta endp
end type