Vistas de página en total

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

miércoles, 20 de noviembre de 2013

TEST PUERTO CENTRONICS

   En esta entrada voy a poner una aplicación muy útil para testear el puerto Centronics. El uso más importante que he hecho de esta aplicación es la prueba prototipos controlados por centronics,
   Mediante este programa podemos configurar bit a bit la los puertos del Centronics y ver sus entradas. De esta manera podemos controlar las señales que enviamos por el para testear pequeños circuitos.
   En este caso los textos asociados a cada señal están nombrados con la función que desempeñan en el puerto centronics. Cada uno puede luego cambiar estos textos por el uso que haga de cada bit en su prototipo.
  Como el puerto Centronis tiene dos puertos de salida y uno de entradas, y los de salidas no son de entradas, normalmente, no podemos leer los puertos 378h y 37Ah , que normalmente son simplemente un latch de salida. Por ello, no siempre el dato inicial será correcto. En el caso de realizar un programa test particularizado para una aplicación, podemos cargar al comienzo del programa en estos puertos un valor inicial, para no tener que ir colocando bit a bit.

  En el siguiente blog colocaré el esquema de una targeta que permitirá obtener 48 E/S a través de dos PIO's.
   Estos podrán ser programados y manejados por el ordenador a través del puerto centronics.
    Por supuesto, una vez realizada la tarjeta hay que probarla, y para ello es necesario este programa. Con él podremos ir enviando las señales de control a la tarjeta y verificando que funciona.  
    Con el esquema de la tarjeta añadiré una versión de este programa con los textos cambiados y adapatados al uso que se vaya ha hacer en esa tarjeta.

    Una vez que la tarjeta funcione podremos realizar librerías de control de esta, para programarla y manejar sus 48 E/S. De esta forma crearemos unos drive's de control para estas tarjeta.
 
     Con estas librerías podremos hacer un programa equivalente a este pero que en pantalla aparezcan en vez de los tres puertos centronics los 6 puertos de la tarjeta y sus puertos de configuración. Esta será, al igual que este programa, una herramienta para crear prototipos controlados mediante esta tarjeta.

     Un ejemplo que pondré, bajo una licencia GPL será un emulador de 8051.

       Como todos mis programas, todo lo que uso está basado en mis propias librerías. No existe ni una sola línea de programación estandar o cogido de librerías estandar. Por ello, quien quiera entender como funcionan las funciones implementadas, debe de recorrer este blog, ya que el código de todo lo que se usa ya ha sido publicado en él.


CENTRON.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/>.
 
;programa monitor del puerto centronics

include main.mac
include stdio.mac
include mouse.mac
include math.mac
include window.mac

.model compact,pascal
.stack 100

.data
raton dw 0   ;bandera para detectar flanco de pulsación

m1 db "Control puerto paralelo V1.1",10,13
   db "              (c)Jose Angel Moneo Fernández",0

datos db "Dato-378H",0
control db "Cont-37AH",0
Estado db "Esta-379H",0
idest1 db "/Ocupado-11--------+¦¦¦¦",0
idest2 db "Reconocido-10-------+¦¦¦",0
idest3 db "Sin papel-12---------+¦¦",0
idest4 db "Seleccion Entrada-13--+¦",0
idest5 db "Error-15---------------+",0
idcont1 db "¦¦¦¦+------ /Strobe-1",0
idcont2 db "¦¦¦+------- /Auto feed-14",0
idcont3 db "¦¦+-------- Inicializacion-16",0
idcont4 db "¦+--------- /Select-17",0
idcont5 db "+---------- En. In.",0

msalir  db "Salir",0

orden db "76543210",0
;Inicializamos la varialbe con 100h para que al presentar el número en 
; binario siempre mantenga los 8 dígitos. Despuñes borraremos el 1 inical
; en pantalla
numero dw 100h,0
ncontrol dw 100h,0
nestado dw 100h,0



.code

centronics proc far

      main
      setcursor off
      resmouse
      mouse on
      putmouse 64,64
      clrscr

      gotoxy 10,1
      puts m1
      draw_win 9,35,12,46,control
      gotoxy 37,10
      puts orden
      draw_win 15,25,18,36,estado
      gotoxy 27,16
      puts orden
      draw_win 9,18,12,29,datos
      gotoxy 20,10
      puts orden
      gotoxy 8,19
      puts idest1
      gotoxy 8,20
      puts idest2
      gotoxy 8,21
      puts idest3
      gotoxy 8,22
      puts idest4
      gotoxy 8,23
      puts idest5
      gotoxy 40,13
      puts idcont1
      gotoxy 40,14
      puts idcont2
      gotoxy 40,15
      puts idcont3
      gotoxy 40,16
      puts idcont4
      gotoxy 40,17
      puts idcont5
       gotoxy 50,22
      puts msalir    
      mov dx,378h
      in al,dx
      mov byte ptr numero,al
      mov dx,37Ah
      in al,dx
      mov byte ptr ncontrol,al
refresca:      
      ;imprime el valor para enviar como dato
      gotoxy 19,11
      printf numero,@b   ;imprime el valor en binario
      gotoxy 19,11   ; borra el uno no valido
      putchar ' '
      ; imprime el valor para ncontrol
      gotoxy 36,11
      printf ncontrol,@b
      gotoxy 36,11   ; borra el uno no valido
      putchar ' '

test2:
      mov dx,379h
      in al,dx
      cmp al,byte ptr nestado  ; no imprime si no cambia el valor
      je espera
      mov byte ptr nestado,al
      gotoxy 26,17
      printf nestado,@b
      gotoxy 26,17   ; borra el uno no valido
      putchar ' '
      
 espera:

        getmouse                ;comprueba el estado del raton
        cmp ax,1
        jnz actual              ;si no se ha pulsado se espera
        cmp ax,raton            ;si se pulso se verifica si ha sido un
        mov raton,ax            ;flanco de subida
        jnz  seleccion           ;si es asi se selecciona la opcion deseada
actual:
        mov raton,ax
        jmp espera      
seleccion:
        getmousexy 19,11,8,0    ; numero
        cmp al,0ffh
        jnz op_numero
        getmousexy 36,11,8,0    ; ncontrol
        cmp al,0ffh
        jnz op_control
        getmousexy 50,22,5,0    ; ventana para salir
        cmp al,0ffh
        jnz fin
        jmp espera
        
op_control:        
        ; ncontrol

        ;Creamos una palabra con el bit indicado a 1
        ;mediante traslaciones de un bit
       
        mov cl,ah
        xor al,al   ; borra al , donde crearemos la mascara
        stc    ; carry a 1
        rcr al,cl      ; situa el bit elegido
        mov ah,al
        mov al,byte ptr ncontrol
        xor al,ah
        ;cambiar bit ncontrol para enviarlo
        mov byte ptr ncontrol,al
        mov dx,37Ah
        out dx,al
      
        jmp refresca
        
op_numero: ;numero 

        ;Creamos una palabra con el bit indicado a 1
        ;mediante traslaciones de un bit
        mov cl,ah
        xor al,al   ; borra al , donde crearemos la mascara
        stc    ; carry a 1
        rcr al,cl      ; situa el bit elegido
        mov ah,al
        mov al,byte ptr numero
        xor al,ah
        ;cambiar bit ncontrol para enviarlo
        mov byte ptr numero,al
        ;saca el dato por el puerto
        mov dx,378h
        out dx,al
       
        jmp refresca
fin:
      setcursor on
      mouse off
      ret
centronics endp

end centronics


viernes, 12 de julio de 2013

EJEMPLO "HORA"


     Este es un ejercicio en el que imprimiremos la hora. Para ello usamos las funciones ya creadas anteriormente: printf para imprimir los valores,  time para tomar la hora, y clrscr para borrar pantalla.

     Como en este caso se trata de un programa ejecutable y no de una librería, se declara la pila mediante _stack, se usa main al comienzo del programa para inicializar el programa., y usamos exit para salir al DOS devolviendo 0.

    El programa al ejecutarse borra la pantalla y muestra la hora en formato hh:mm:ss.


EJ_HORA.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
include main.mac
include time.mac
_modelo exe

_stack 512
_data
time hora
separador db ":",0
_code
p proc far
       main
       clrscr
       gettime hora
       printf hora.ti_hora,@d
       puts separador
       printf hora.ti_min,@d
       puts separador
       printf hora.ti_seg,@d
       getch al
       exit 0
p endp
_data
time hora
separador db ":",0
_end p

viernes, 28 de junio de 2013

PROGRAMA USO LIBRERÍA STDIO

    Este ya es el primer ejemplo complejo que  visualiza lo que he conseguido hasta ahora.
   Aunque simple, sería muy complicado editar y seguir un programa tan complejo directamente en ensamblador.
    Este programa es solo un ejemplo inicial de la operatividad de las funciones de STDIO.

    Este programa toma del teclado un texto y lo imprime. Luego toma un número, interpretándolo como decimal, y lo imprime posteriormente en decimal, binario, octal, hexadecimal, binario y en base 5.
    Como se puede ver el programa ya tiene los mensajes por pantalla y los posicionamientos tanto de mensajes como de entradas y salidas de textos  y variables.
    
    Con este ejemplo se puede ver igualmente, como se definirán las variables, apoyándonos en las definiciones hechas en MAIN.MAC.
    String, define una cadena y integer un entero. Para la salida de textos simples usamos simplemente una lista de bytes, con final en 0 que serán usados con puts.
    
    Dado que es un ejecutable la data la colocamos al comienzo, pues si no nos puede dar un error. En el caso de que fuese com la data la colocamos al final. Igualmente en _end damos el nombre de la rutina que debe ejecutarse.

      ¡Esto ya es My Assembler!   

     Recuerdo que seguimos compilando por debajo de MASM, pero a partir de ahora haremos maravillas....

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

_modelo exe
_stack 512

_data
string cadena,30
integer valor 25
msgtexto db "Introduce un texto",0
msgvalor db "Introduce un numero decimal",0

_code
 p proc far
      main
      clrscr
      gotoxy 10,9
      puts msgtexto
      gotoxy 10,10
      scanf cadena
      gotoxy 20,10
      printf cadena
      gotoxy 10,11
      puts msgvalor
      gotoxy 10,12
      scanf valor
      gotoxy 20,12
      printf valor
      getch al
      gotoxy 20,13
      printf valor,@b
      getch al
      gotoxy 20,14
      printf valor,@o
      getch al
      gotoxy 20,15
      printf valor,@h
      getch al
      gotoxy 20,16
      printf valor,@d
      getch al
      gotoxy 20,17
      printf valor,5
      ret
  endp

_end ejemplo1



lunes, 24 de junio de 2013

IMPRIMIR VARIABLES

 Vamos a montar la función de impresión de variables PRINTV, que es parte de la librería STDIO, y es llamada por la función   printf.
  Aprovechando esto, vamos a mejorar la cabecera MAIN.MAC, añadiendo una nueva macro.
   En la cabecera vamos a añadir:
            rutina_end macro
                   pop bp
                   ret
                   endp
             endm


  Esta nueva macro nos perimitirá, cerrar las rutinas de forma más sencilla sin necesidad de realizar la recuperación final de la pila ni el cierre del procedimiento. por lo tanto substituye a:

                   pop bp
                    ret
            _scanf endp


    Ahora simplemente deberemos colocar la palabra rutina_end.
    
    No resulta complejo esto, pues el código de la llamada a la función lo tenemos siempre en las macros y por lo tanto lo podemos adaptar fácilmente.
   En este caso hay que tener cuidado cuando usamos una macro como auxilio de una función. En este caso si necesitamos pasar los datos de la pila como parámetros a la macro, hay que tener en cuenta que los datos pasados por pila a la función que estamos creando ya son las direcciones de las variables de trabajo, por lo que no debemos usar una macro para llamar a la siguiente función si esta usa lea para obtener la dirección de la variable.
    Si hubiéramos usado la macro itoa, en vez de colocar mov habría colocado lea de [bp].var, y nos habría dado la dirección de la pila, no la dirección de la variable. Como en [bp].var ya tenemos la dirección de la variable, guardada por la macro printf, lo que debemos hacer es simplemente poner mov.
  Por todo esto, y dado que esto es algo puntual, pues se trata de la creación de nuevas librerías, cuando nos apoyemos en funciones, para crear nuevas funciones, debemos considerar que si usan en la macro la opción lea, debemos copiar el código de la macro, substituyendo los lea por mov, en vez de usarla como función.
  Tenemos que tener en cuenta que si no usamos la macro debemos declarar como externa la función a usar.
 Si podemos usar, en cambio, la macro puts.


PRINTV.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
_modelo exe
   extrn _itoa:near  


_code

rutina _printv base,var,color
        push bx
        push cx
        push dx
        push si
        push di

      ; itoa buffer,[bp].var,[bp].base
        mov ax,[bp].base
        push ax
        mov ax,[bp].var
        push ax
        lea ax,buffer
        push ax
        call _itoa
        add sp,6

        puts buffer,[bp].color

        pop di
        pop si
        pop dx
        pop cx
        pop bx
rutina_end
_data
buffer db 33 dup (0)
_end

martes, 18 de junio de 2013

DECLARACIÓN FUNCIONES DE IO TECLADO-PANTALLA


   Para poder realizar algún programa ya complejo vamos a colocar la que, creo es la cabecera y librería más básica. La STDIO. Como en C esta librería contendrá  los comandos y funciones para el manejo de la pantalla. En esta librería está incluidas la funciones de posicionamiento de cursor, impresión de textos y variables, y entradas de teclado.
   Además al comienzo incluyo las definiciones de constantes para el manejo del cursor, los colores y las variables numéricas.
 
    Las cabeceras son la forma de consultar la forma de llamar a cada función, por lo que siempre han de estar a mano. Las librerías sin embrago, serán compiladas y almacenadas en un .LIB, a partir del cual, ya no hace falta que tengamos a mano el código fuente.
 
     Como se ve en esta cabecera, algunas funciones como clswindow o clrscr, llaman a funciones auxiliares, ya que son más complejas de lo que se ve ahora.
      Un caso particular es la función printf. Esta es un ejemplo de programación condicional de macro. De esa forma conseguimos crear de  forma sencilla una función que en realidad son dos. Estamos creando realmente polimorfismo en ensambaldor.
    Que significa polimorfismo. Es una propiedad de los lenguajes Orientados a Objetos, por el cual se puede definir una función con varias formas, de manera que el compilador utilizará la adecuada en cada momento.

  Printf
     Pues bien, en este caso mediante las sentencias ifndef , ifidn e ifb  vamos a conseguir lo mismo. Según los parámetros que indiquemos al usar la función printf esta se comportará como la función puts(impresion de cadenas)  o la función printv (impresion de variables). 
    Igualmente si dirección es un byte, pero no se define base, se entiende que se usa base 10 como base de numeración. Si en cambio se indica una base entonces se interpretará en esa base.

    Ejemplos:
             Variables
                    m1 db 'primera linea ',10,13,'segunda linea',0 ; cadena de texto
                    A0 Dw 100h,0   ; variable numérica de palabra


             codigo
                      printf m1                        ; imprime texto
                      printf A0,@b                 ; imprime valor en binario
                      printf A0                        ; imprime valor en decimal

                      printf A0,5                     ; imprime valor en  base 5

    Exactamente sucederá con scanf que es la entrada de variables por teclado. podremos especificar si queremos leer una variable y en que sistema de numeración deberemos interpretarla.
   
     En las siguientes entradas iré exponiendo las rutinas asociadas a STDIO. Es decir las rutinas  _puts, _scanf, _getxy, etc que son llamadas desde las macros de esta cabecera. Después  estaremos en disposición de crear nuestro primer programa sobre pantalla que usen estas instrucciones, que nos serán absolutamente imprescindibles para crear pantallas de interface Hombre-Maquina.

   Otra ejemplo de este polimorfismo lo tenemos en _puts y printf. Estas macro está pensadas para ser usada con la variable de color por defecto o para ser usadas con un color pasado de forma puntual.
    Para ello usamos el siguiente código:
      ifb <color>
          mov ax,_color
       else
          mov ax,color
       endif


STDIO.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 encendido y apagado del cursor
ON = 1
OFF = 0

;definición de bases para impresión de valores numéricos
ifndef _numeracion
   _numeracion equ 1
@b = 2
@o = 8
@d = 10
@h = 16
endif

; definición de colores y modos de testo
ifndef _colores
     _colores equ 1
parpadeo equ 80h
intenso equ 0fh
normal equ 7
subrayado equ 1
inverso equ 70h

negro equ 0
azul equ 1
verde equ 2
cian equ 3
rojo equ 4
magenta equ 5
marron equ 6
gris_claro equ 7
gris_obscuro equ 8
Azul_Claro equ 9
verde_claro equ 10
cian_claro equ 11
rojo_claro equ 12
magenta_claro equ 13
amarillo equ 14
blanco equ 15
endif

_color = normal


;Toma posición de cursor devuelve x en al e y en ah
getxy macro
ifndef _getxy
        extrn _getxy:near
endif
        call _getxy
endm

; Toma caracter de teclado
getch macro variable
    mov ah, 8
    int 21h
 ifdif <variable>,<al>
    mov variable, al
  endif
endm

;Toma caracter de teclado con eco
getche macro variable
    mov ah, 1
    int 21h
 ifdif <variable>,<al>
    mov variable, al
  endif
endm

;ZF = 1 si Vacio
;Lee si teclado pulsado
kbhit macro
        mov ah,1
        int 16h
endm

; borra pantalla
clrscr macro
ifndef _cls
        extrn _cls:near
endif
       call _cls
endm



;Posiciona el cursor en una coordenada
;La macro toma los dos parámetros y los combina en una sola palabra 
gotoxy macro px, py
ifndef _gotoxy
        extrn _gotoxy:near
endif
        mov al,px
        mov ah,py
        call _gotoxy

endm

;Selecciona un color
setcolor macro color
    _color = color
endm

;Imprime una cadena de texto string o variables
printf macro direccion,base,dest1,base1,color
ifndef _puts
        extrn _puts:near
endif

       ifb <color>
          mov ax,_color
       else
          mov ax,color
       endif

        push ax
ifidn <base>,<ptr>
        lea ax,dest1
else
        lea ax,direccion
endif
     
ifidn <base>,<ptr>
  ifidn <direccion>,<byte>

         add ax,2
         push ax

         call _puts
  else
       push ax
      ifb <base1>
         mov ax,10
      else
         mov ax,base1
      endif
      ifndef _printv
           extrn _printv:near
      endif
         push ax
         call _printv
         pop ax
   endif

 else
  if (type (direccion)) eq 1

         add ax,2
          push ax

         call _puts
  else
      push ax
      ifb <base>
         mov ax,10
      else
         mov ax,base
      endif
      ifndef _printv
           extrn _printv:near
      endif

         push ax
         call _printv
         pop ax
   endif
endif
         add sp,4
endm

; entrada de variables o testo string scanf macro direccion,base,dest1,base1
ifdif <base>,<ptr>
    if type (direccion) ne 1
       ifb <base>
          mov ax,10
       else
          mov ax,base
       endif
          push ax
     endif
        lea ax,direccion
        push ax
      if type (direccion) eq 1
        ifndef _gets
            extrn _gets:near
         endif
         call _gets
         pop ax
       else
         ifndef _scanf
             extrn _scanf:near
         endif
         call _scanf
         pop ax
         pop ax
       endif
else
    ifdif <direccion>,<byte>
       ifb <base1>
          mov ax,10
       else
          mov ax,base1
       endif
          push ax
     endif
        lea ax,dest1
        push ax
      ifidn <direccion>,<byte>
        ifndef _gets
            extrn _gets:near
         endif
         call _gets
         pop ax
       else
         ifndef _scanf
             extrn _scanf:near
         endif
         call _scanf
         add sp,4
       endif
endif
endm

;imprime texto simple puts macro  buffer
ifndef _puts
        extrn _puts:near
endif

       ifb <color>
          mov ax,_color
       else
          mov ax,color
       endif

        push ax
        lea ax,buffer
        push ax
        CALL _puts
        add sp,4
endm


; pide texto con formato string
gets macro  buffer
ifndef _puts
        extrn _gets:near
endif
        lea ax,buffer
        push ax
        CALL _gets
        pop ax
      
endm

putchar macro caracter
    push dx
ifdif <caracter>,<dl>
    mov dl, caracter
else 
    mov dl,al
endif
    mov ah,2
    int 21h
    pop dx
     
 endm

setcursor macro opcion
ifndef _set_cursor
        extrn _set_cursor:near
endif
        mov ax,opcion
        push ax
        call _set_cursor
        pop ax
endm