Vistas de página en total

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

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


martes, 20 de agosto de 2013

USO DE WHILE...ENDWHILE

    Este sería un ejemplo del uso de la macro while....endwhile. Como se ve es idéntico a como sería en basic.
   En este caso imprime 5 veces un mensaje indicando el contador de cada mensaje.




EJEMPLO FOR.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/>.

include main.mac
include stdio.mac
include Hi_nivel.mac

.model compact,pascal
.stack 100

.data
valor db 0,0,0,0
msgtexto db "Mensaje ",0

.code
p proc 
          main
         clrscr
     while valor,b,5
          gotoxy 10,valor
          mov ax,word ptr valor
          mov word ptr numero,ax
          puts msgtexto
          printf numero
         inc valor
     endwhile
        exit 0
p endp
end p


lunes, 19 de agosto de 2013

USO DE FOR...NEXT

    Este sería un ejemplo del uso de la macro for....next. Como se ve es idéntico a como sería en basic. No resulta por lo tanto difícil de usar.
   En este caso imprime 5 veces un mensaje indicando el contador de cada mensaje.




EJEMPLO FOR.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/>.
 
include main.mac
include stdio.mac
include Hi_nivel.mac

.model compact,pascal
.stack 100

.data

valor db 0,0,0,0
msgtexto db "Mensaje ",0

.code

p proc 
      main
     clrscr
  for valor,0,5
      gotoxy 10,valor
      mov ax,word ptr valor
      mov word ptr numero,ax
      puts msgtexto
      printf numero
  next valor
     exit 0
p endp
end p

sábado, 17 de agosto de 2013

DIRECTIVAS PROGRAMACIÓN ESTRUCTURADA

   Hoy voy a enseñar como podemos crear directivas bucles de alto nivel para simplificar algunos programas.
   En concreto voy a exponer una cabecera donde definiremos directivas para realizar las instrucciones WHILE y FOR.
    Podía hacer la instrucción do..while, pero esta es demasiado simple da realizar directamente en ensamblador, ya que la comparación con salto atrás es directamente esta estructura. por ello no vale pena.
    La idea de estas estructuras de alto nivel es seguir aclarando el programa, de manera que se pueda distinguir de un vistazo la estructura del programa.
    En ensamblador, como todos sabemos, seguir un programa es muy laborioso, incluso para el programador que lo hizo, si ha pasado tiempo desde que lo creó.
     Todas las funciones, macros, y directivas que voy exponiendo, no hacen nada que no se pueda hacer directamente, pero aclaran la estructura, de forma que resulta muy sencilla de seguir, incluso después de 20 años, como estoy haciendo yo ahora.



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

;;definiciones de controles de estructuras complejas para
;;programación estructurada

;***** for var=ini to fin*****
for macro var,ini,fin
        mov var,ini
        $salvar
        cmp var,fin
        jb $ + 5
        $salvar
        nop
        nop
        nop
   endm


;***** next var*******
next macro var
        $recup
$hueco = $simbolo
        $recup
$bucle = $simbolo
        inc var
        jmp $bucle
$fin = this near
        org $hueco
        jmp $fin
        org $fin
  endm


;****while op1 (a es >,e es =,b es <,ae es >=,be es <=) op2***********
while macro op1,oper,op2
        $salvar
        cmp op1,op2
        j&oper $ + 5
        $salvar
        nop
        nop
        nop
   endm


;************endwhile
endwhile macro
        $recup
$hueco = $simbolo
        $recup
$bucle = $simbolo
        jmp $bucle
$fin = this near
        org $hueco
        jmp $fin
        org $fin
  endm


$salvar macro
        ifndef $i
           $i = 0
        endif
        $i = $i + 1
        $salvar1 %$i
endm

$salvar1 macro $i
$sim_&$i = this near
endm

$recup macro
      $recup1 %$i
$i = $i - 1
endm

$recup1 macro $i
        ifndef $sim_&$i
         .lall
         .sall
       endif
$simbolo = $sim_&$i
endm