Vistas de página en total

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

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


viernes, 30 de agosto de 2013

MANEJO FICHEROS

     Hoy voy a crear las instrucciones para manejo de ficheros.
     Como siempre, primero la cabecera con las macros y las constantes asociadas a su manejo.
  Esta cabecera es muy importante, pues sus funciones son utilizadas, junto con las de SYDIO y WINDOW para todos los programas complejos.
     La funciones  open, close y newfile no se implementan en librerías, pues cuando se usan en un programa no se suelen repetir mucho, por lo que no vale la pena el gasto de código extra para paso de parámetros, frente al tamaño de la macro. Por ello lo mantengo como macro.


IO.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/>.
; constantes para manejo de unidades
ifndef _unidades
    _unidades equ 1
;unidades
_A equ  0
_B equ 1
_C equ 2
_D equ 3
endif

; constantes para manejo de archivos
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

;posiciones de fseek
_INICIO EQU 0
_FIN    EQU 2
_ULTIMA EQU 3

;; modos de acceso
_R EQU 0
_W EQU 1
_R_W EQU 2

;;Estructuras
_DTA struc
   _RES_DTA DB 21 DUP (?)
   _ATTR    DB ?
   _HORA    DW ?
   _FECHA   DW ?
   _LONG    DD ?
   _NOMBRE  DB 13 DUP (?)
   ENDS

;dispositivos standar
_stdin equ 0
_stdout equ 1
_stderr equ 2
_stdaux equ 3
_stdprn equ 4








;; file direccion cadena ascii fichero
;;handle numero de fichero o codigo de retorno
;;atributo es el tipo de fichero
;;si cf =1 error
;;si cf=0 ax es numero de fichero

newfile macro file,atributo,handle
     mov ah,3ch
     push cx
     push dx
     mov cx,atributo
     lea dx,file
     int 21h
     pop dx
     pop cx
     mov handle,ax
 endm


;abre un fichero. 
; devuelve cf=0 si ok y el handle en la variable handle
;devuelve cf=1 si error y el error en la variable handle
open macro file,atributo,handle

     mov ah,3dh
     mov al,atributo
     push dx
     lea dx,file
     int 21h
     pop  dx
     mov handle,ax
 endm

close macro handle
     mov ah,3eh
     push bx
     mov bx,handle
     int 21h
     pop bx
 endm


;;fichero encontrado esta escrito en la zona DTA
;;      offset descripcion
;;       0      reservado para dos
;;      21      atributo de fichero encontado
;;      22      hora
;;      24      fecha
;;      26      tamaño
;;      30      nombre del fichero y extension
;; devuelve CF=1 si hay error
findfirst macro file,atributo
ifndef _find_first
        extrn _find_first:near
endif
        lea ax,file
        push ax
        mov ax,atributo
        push ax
        call _find_first
  endm


findnext macro
ifndef _find_next
        extrn _find_next:near
endif
        call _find_next
  endm

;; posicion en un fichero el puntero
;; cx marca la parte alta de la direccion
;; para hacerlo mas sencillo nos limitaremos a 65535 bytes por lo que
;; cx=0
;; el metodo es
;;      0    principio fichero
;;      1    desde la posicion actual
;;      2    desde final de fichero
;; devuelve en dx:ax la direccion en que se ha quedado referida al principo del fichero

fseek macro handle,metodo,posicion
ifndef _fseek
        extrn _fseek:near
endif
        mov ax,handle
        push ax        
        mov ax,metodo
        push ax
        mov ax,posicion
        push ax
        call _fseek

 endm

;;obtine direcion de transferencia de disco
;;devuelve en ax un codigo de retorno
;;devuelve en es:bx direccion de DTA
offsetdta macro
      mov ah,2fh
      int 21h
  endm



;READ y WRITE devuelven en ax el número de bytes leidos
;realmente.

read macro handle,n_bytes,buffer
ifndef _read
        extrn _read:near
endif
        mov ax,handle
        push ax
        mov ax,n_bytes
        push AX
        mov ax,offset buffer
        push ax
        call _read

 endm

rseek macro handle,numero,registro

ifndef _rseek
        extrn _rseek:near
endif
        mov ax,handle
        push ax
        mov ax,numero
        push ax
        mov ax,size registro
        push ax
        call _rseek

 endm

setdta macro posicion
      mov ah,1ah
      PUSH DX
      lea dx,posicion
      int 21h
      POP DX
  endm


write macro handle,n_bytes,buffer
ifndef _write
        extrn _write:near
endif
        mov ax,handle
        push ax
        mov ax,n_bytes
        push AX
        lea ax,buffer
        push ax
        call _write

 endm

getpath macro camino,path
ifndef _getpath
      extrn _getpath:near
endif
      lea ax,camino
      push ax
      lea ax,path
      push ax
      call _getpath

endm