Vistas de página en total

Mostrando entradas con la etiqueta puts. Mostrar todas las entradas
Mostrando entradas con la etiqueta puts. 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


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


miércoles, 7 de agosto de 2013

TIC_TAC_TOE (5/5)

     Aquí está por fin el juego TIC_TAC_TOE completo, aunque simplificable mediante la posterior rutina getmousexy.
 
      Esta es al última entrada hecha con mis directivas _data,_code, _rutina. A partir de la siguiente entrada de blog, comenzaré a usar las directivas de TASM. Una vez declarada la función getmousexy, volveré a colocar este juego, pero ya totalmente en TASM 2.0

     En este caso veis como introducimos al comienzo una macro. Esta macro nos permite definir una nueva instrucción (tablero), mediante la cual pasamos los parámetros a la rutina _tablero.


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


title tic_tac_toe

include main.mac
include stdio.mac
include string.mac
include time.mac
include mouse.mac

.286  ; para poder usar shr al,3

; macro para crear la instrución de dibujo de tablero
tablero macro jugador,simbolo
        push bx
        mov bl,jugador
        mov bh,simbolo
        call _tablero
        pop bx
endm

_modelo exe

_stack 250

_data
;Mapa de juego
;significado tabla
;     oponente,respuesta,siguiente lista(2 byte)
;significado siguiente lista si
;   offset ->continual el juego en otro nivel
;   0-> ha finalizado el juego
;   1->  si la situación de la máquina es 30h
;   2->  si la situación de la máquina es 90H
;significado respuesta
;   si <>0 es posición de respuesta
;   si =0 no hay respuesta. Son tablas



nivel1  db 80h,20h
            dw offset n2_20h
        db 40h,20h
            dw offset n2_20h
        db 20h,80h
            dw offset n2_80h
        db 10h,80h
            dw offset n2_80h
        db 8,10h
            dw offset n2_10h
        db 4,80h
            dw offset n2_80h
        db 2,40h
            dw offset n2_40h
        db 1,40h
            dw offset n2_40h

;revisado      
n2_10h db 9,40h
           dw offset n3_40h
       db 88h,1,0,0
       db 48h,1,0,0
       db 28h,1,0,0
       db 0ch,1,0,0
       db 0ah,1,0,0
       dd 0


n2_20h db 84h,10h
          dw offset n3_10h_1
       db 44h,10h
          dw offset n3_10h_2
       db 0c0h,4,0,0
       db 90h,4,0,0
       db 88h,4,0,0
       db 82h,4,0,0
       db 81h,4,0,0
       db 50h,4,0,0
       db 48h,4,0,0
       db 42h,4,0,0
       db 41h,4,0,0
       dd 0

;revisado
n2_40h db 82h,10h
            dw offset n3_10h_3
       db 81h,4
            dw offset n3_4h
       db 22h,80h,0,0
       db 21h,80h,0,0
       db 12h,80h,0,0
       db 11h,80h,0,0
       db 0ah,80h,0,0
       db 9,80h,0,0
       db 6,80h,0,0
       db 5,80h,0,0
       db 3,80h,0,0
       dd 0


n2_80h db 60h,10h
            dw offset n3_10h_3
       db 44h,10h
            dw offset n3_10h_3
       db 50h,4
            dw offset n3_4h
       db 30h,40h,0,0
       db 28h,40h,0,0
       db 24h,40h,0,0
       db 22h,40h,0,0
       db 21h,40h,0,0
       db 0ch,40h,0,0
       db 18h,40h,0,0
       db 14h,40h,0,0
       db 12h,40h,0,0
       db 11h,40h,0,0
       db 6,40h,0,0
       db 5,40h,0,0
       dd 0

n3_4h db 70h,8
         dw offset n4_8h
      db 58h,20h,0,0
      db 52h,20h,0,0
      db 51h,20h,0,0
      db 0a1h,10h,0,0
      db 91h,20h,0,0
      db 89h,20h,0,0
      db 83h,20h,0,0
   

n3_10h_1 db 0c4h,8,0        
       db 85h,8,0,0
       db 8ch,1,0,0
       db 86h,8,0,0
       dd 0

n3_10h_2 db 0c4h,8,0,0
       db 4ch,1,0,0
       db 86h,8,0,0
       db 85,8,0,0
       dd 0

n3_10h_3 db 0c4h,2,0,0
       db 0c2h,1,0,0
       db 0c8h,2,0,0
       db 0c1h,2,0,0
       db 4ch,2,0,0
       db 86h,1,0,0
       db 85h,2,0,0
       db 8ah,4,0,0
       db 83h,4,0,0
       db 0a2h,4,0,0
       db 61h,2,0,0
       db 62h,1,0,0
       db 64h,2,0,0
       db 68h,2,0,0
       db 46h,1,0,0
       db 45h,2,0,0
       dd 0



n3_40h db 89h,4,0,0
       db 29h,80h,0,0
       db 0dh,80h,0,0
       db 0bh,80h,0,0
       dd 0
   
n4_8h  db 72h,1,1,0
       db 71h,2,1,0
       dd 0
   
   
nivel_act dw 0 ; almacen de puntero de nivel actual    
maquina db 0 ; situación de la maquina
oponente db 0 ; situación del oponente
ocupados db 0 ; estado ocupados
 
estado db 0; estado partida
posx db 0   ; posicion pulsación del raton
posy db 0
raton dw 0


titulo db "TRES EN LINEA",0
ayuda db "PULSA CON EL RATON EN LA POSICION DESEADA",0
m_gana db "Lo siento has perdido.",0
m_tablas db "Esta partida son tablas",0
m_error db " Ha surgido un error",0

tablero1 db 201,205,203,205,203,205,187,0 ; "╔═╦═╦═╗"
Tablero2 db 186,32,186,32,186,32,186,0      ; "║ ║ ║ ║"
Tablero3 db 204,205,206,205,206,205,185,0   ; "╠═╬═╬═╣"
Tablero4 db 200,205,202,205,202,205,188,0   ; "╚═╩═╩═╝

NW_intento db "Quieres intentarlo de nuevo? S/N",0

_code
tic_tac_toe proc far
        main   ; inicia
        setcursor off
        resmouse
        mouse off
        putmouse 8,8
nw:
;inicia tablero
        clrscr
        gotoxy 9,1
        puts titulo
        gotoxy 9,2
        puts ayuda
        gotoxy 9,3
        puts tablero1
        gotoxy 9,4
        puts tablero2
        gotoxy 9,5
        puts tablero3
        gotoxy 9,6
        puts tablero2
        gotoxy 9,7
        puts tablero3    
        gotoxy 9,8
        puts tablero2    
        gotoxy 9,9
        puts tablero4
        gotoxy 10,4
        putchar 'X'
        mov maquina,0
        mov oponente,0
        mov nivel_act,offset nivel1
     
otra:    
        tablero oponente,'O'
        tablero maquina,'X'


;espera seleccion oponente
        mouse on
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:
     ;toma la coordenada
        getmousex
        shr ax,4 ;divide por 16 para obtener coordenada letra
        sub ax,5 ;referencia desde cero de la posicion en la matriz
        cmp al,2  ;no valido si pulsamos fuera
        ja espera
        mov posx,al
        getmousey
        shr ax,4 ;divide por 16 para obtener coordenada letra
        sub ax,2 ;referencia desde cero de la posicion en la matriz
        cmp al,2    ;no valido si pulsamos fuera
        ja espera
        mov posy,al
     ;coloca el bit
        mov al,posy    ; posy*3+posx
        add al,posy
        add al,posy
        add al,posx

        cmp al,8       ; si pulsamos fuera no procesamos
        ja espera

        mov cl,al
        xor al,al   ; borra al
        stc    ; carry a 1
        rcr al,cl      ; situa el bit elegido
        ; comprueba que no esté seleccionada ya
   
        mov ah,oponente
        or ah,maquina
        mov ocupados,ah
        or ah,al     ;montamos nuevo bit
        cmp ah,ocupados   ; ha añadido bit nuevo?
        je  espera ; si no añade bit nuevo la posición está ya estaba ocupada
       
        or oponente,al   ; guarda la jugada
        call ver_respuesta
;presentamos la nueva posición del tablero
         ;si estado = 4 sigue el juego
        cmp estado,4
        jne sig01
        jmp otra
sig01:
       ;si estado=6 gana
        cmp estado,6
        je gano
        cmp estado,0ffh
        jne acierto
        gotoxy 10,20         ;error
        puts m_error
        jmp acabo
   
acierto:
       ;si estado=7 tablas
        gotoxy 10,20         ;ha acertado
        puts m_tablas
        jmp acabo
gano:
        mouse off
        gotoxy 10,20         ;ha acertado
        puts m_gana
acabo:    
        tablero oponente,'O'
        tablero maquina,'X'
        gotoxy 10,21
        puts nw_intento
        getch al             ;espera pulsación antes de salir
        upr                   ;convierte al en mayusculas
        cmp al,'S'
        jne  salir
        jmp nw
salir: setcursor on
        mouse off
        exit 0

tic_tac_toe endp


ver_respuesta proc near
; busca la respuesta a la situación del oponente en la tabla correspondiente
; devuelve estado=7 si gana, estado=6 si tablas y estado=4 si sigue el juego
;    0ffh= error
        mov si,nivel_act
comprueba:
        mov al,[si]    ;posibilidad
        cmp al,0        ;error fin de lista. No hay acción
        jne n_error
        mov estado,0ffh   ; marca error
        ret
n_error:
        cmp oponente,al  ;es la jugada hecha?
        je encontrado
sig_estado:
        add si,4   ; siguiente estado
        jmp comprueba
encontrado:
        mov al,[si+1]
        or maquina,al    ;añade al tablero de la máquina la jugada correspondiente
        mov al,[si+2]    ;dato siguiente estado
        cmp al,0          ;fin de la partida
        je _fin
        cmp al,1        ;tablas
        je _fin
        mov ax,[si+2]
        mov nivel_act,ax     ;pasamos el puntero del nivel a la lista del siguiente nivel
        xor al,al
        jmp _fin_ver


_fin:   or  al,2      ; devuelve al=6 si gana y al=7 si tablas
_fin_ver:            
        or  al,4      ;devuelve al=4 si sigue el juego
        mov estado,al
ret
ver_respuesta endp

_tablero proc near
; oponente viene en bl, y el simbolo a imprimir en bh
        mouse off
        shl bl,1
        jnc c2
        gotoxy 12,4
        putchar bh
c2:
        shl bl,1
        jnc c3
        gotoxy 14,4
        putchar bh
c3:
        shl bl,1
        jnc c4
        gotoxy 10,6
        putchar bh
c4:    
        shl bl,1
        jnc c5
        gotoxy 12,6
        putchar bh
c5:
        shl bl,1
        jnc c6
        gotoxy 14,6
        putchar bh
c6:
        shl bl,1
        jnc c7
        gotoxy 10,8
        putchar bh
c7:
        shl bl,1
        jnc c8
        gotoxy 12,8
        putchar bh
c8:
        shl bl,1
        jnc c9
        gotoxy 14,8
        putchar bh
c9:
        mouse on
        ret
_tablero endp
_end tic_tac_toe

miércoles, 24 de julio de 2013

AHORCADO (5/5)

    Ya tenemos las herramientas necesarias para hacer el juego. Las rutinas expuestas antes, no necesitamos guardarlas en librerías, pues son parte de este programa. Por lo tanto son parte del código principal.
    Este, por lo tanto, es el fichero .asm completo que habrá que compilar.
    En el usamos funciones de time, de stdio, de string, y de main.
    El ejecutable resulta de 5232 Bytes

   Es importante pedir la letra con getch, la almacenamos en letra, y luego la convertimos en mayúsculas con upr.

   El programa está preparado para ser un .exe. Para que sea .com debemos colocar la directiva "_modelo com" y linkarlo con una librería preparada para .com.
    Esta librería se formará compilando todas las rutinas expuestas anteriormente pero con esta directiva. y creando luego una libreria completa para .com
   En el caso de que se compile como .com habrá que pasar los datos al final del programa. Esto no lo podemos hacer ahora, pues se producen problemas de compilación.

AHORCADO.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 string.mac
include time.mac

_modelo exe
_stack 250

_data
;palabras
p1 db 9,"BARCELONA",0
P2 DB 4,"CASA",0
P3 DB 4,"CAMA",0
P4 DB 5,"ARBOL",0
P5 DB 7,"ARMARIO",0
P6 DB 5,"COJIN",0
P7 DB 5,"SUELO",0
P8 DB 4,"FLOR",0
P9 DB 3,"PAN",0
P10 DB 11,"ENCRUCIJADA",0
P11 DB 4,"HOJA",0
P12 DB 8,"CUADERNO",0
P13 DB 11,"ENSAMBLADOR",0
P14 DB 8,"PROGRAMA",0
P15 DB 7,"COLEGIO",0
P16 DB 6,"CAMARA",0

TABLA DW OFFSET P1
      DW OFFSET P2
      DW OFFSET P3
      DW OFFSET P4
      DW OFFSET P5
      DW OFFSET P6
      DW OFFSET P7
      DW OFFSET P8
      DW OFFSET P9
      DW OFFSET P10
      DW OFFSET P11
      DW OFFSET P12
      DW OFFSET P13
      DW OFFSET P14
      DW OFFSET P16

PAL_SEL DW 0
mascara DB "__________________________",0

a_buscar dw 0
letra db 0
fallos db 0
titulo db "AHORCADO",0
pregunta db "INDICA UNA LETRA",0
acierto db "!Enhorabuena! Acertaste",0
perdio db "!Lo siento! Has periddo",0
NW_intento db "Quieres intentarlo de nuevo? S/N",0
limpia db "    ",0
HORCA DB 218,196,196,196,0   ;"┌───┐"


_code
ahorcado proc far
        main   ; inicia
nw:
        call nw_pal    ;gernera una nueva palabra
        mov fallos,0   ;coloca el contador fallos a 0
        ;Preparamos la pantalla
        clrscr
        gotoxy 10,2     ;dibujamos horca
        puts titulo
        gotoxy 8,4
        puts horca
        gotoxy 8,5
        putchar 179
        gotoxy 8,6
        putchar 179
        gotoxy 8,7
        putchar 179
        gotoxy 8,8
        putchar 179
        gotoxy 8,9
        putchar 193
 
        gotoxy 10,10   ; muestra la mascara incial
        puts mascara
        gotoxy 10,13     ; hacemos la pregunta
        puts pregunta
_otro:
        gotoxy 29,13      ;limpia la ultima respuesta
        puts limpia
        gotoxy 29,13
        getch letra    ;pedimos la letra
        upr letra    ;convierte en mayuscula
        call buscar    ;busca la letra
        cmp bh,1       ; 1 si encuentra la letra
        je bien
        inc fallos     ; cuenta un fallo
        cmp fallos,8
        jne bien
        ;perido el juego
        gotoxy 11,4
        putchar 191  ;"┐"   ;dibuja la horca
        gotoxy 10,20         ;Perdiste
        puts perdio
        jmp  nw_int          

bien:
        gotoxy 10,10
        puts mascara
        call muneco
        cmp bl,1      ;1 si faltan letras
        jne _fin     ; estrucutra de saltos debido a que el salto relativo no llega hasta _otro
        jmp _otro
_fin:
        gotoxy 10,20         ;ha acertado
        puts acierto
nw_int:
        gotoxy 10,21
        puts nw_intento
        getch al             ;espera pulsación antes de salir
        upr                   ;convierte al en mayusculas
        cmp al,'S'
        jne  _salir
        jmp nw
_salir: exit 0

endp

nw_pal proc near
        push di
        push si
        random
        and ax,0fh    ; tomo numeros >16
        shl ax,1      ;multiplico por dos
        add ax,offset tabla   ;indexo a la tabla de punteros a palabras
        mov si,ax      ;paso la dirección a 'SI' para indexar
        mov ax,[si]    ; recupero la dirección de la palabra de la tabla de punteros
        mov pal_sel,ax  ; almaceno la dirección de la palabra
        mov si,ax        ; paso esta dirección a si para indexar
        mov di,offset mascara  ; usa 'DI' como indexador de mascara
        mov al,[si]   ; leo el numero de letras de la palabra
ini:
        mov byte ptr [di],'_'   ;borra la mascara
        inc di             ; incrementamos puntero busqueda
        dec al           ; decremento el número de letras
        jnz ini
        mov byte ptr [di],0 ; pongo final de cadena
        pop si
        pop di
ret
nw_pal endp

; busca la letra
; devuelve bl=1 si la encuentra la letra
;          bh=1 si faltan letras
buscar proc near
        push di
        push si
        push cx
        mov bx,0  ;borra banderas
        mov si,pal_sel
        mov di,offset mascara
        mov cl,[si] ;numero de letras a contador de busqueda
        inc si ;salta la longitud de la palabra
prueba:
        mov al,letra
        cmp byte ptr [si],al ;comprueba la letra pasada en al
        jne otra
        mov [di],al ; almacena la letra en mascara
        mov bh,1  ; marca bandera letra encontrada
otra:
        cmp byte ptr [di],"_"
        jne sigue
        mov bl,1  ; bandera palabra incompleta
sigue:
        inc si
        inc di
        dec cl
        jnz prueba
        pop cx
        pop si
        pop di
ret
buscar endp

;representación del muneco
; el contador está en la variable 'fallos'
muneco proc near
        push bx
        mov bl,fallos
        cmp bl,7
        jb s1
        gotoxy 12,8
        putchar '\'
s1:
        cmp bl,6
        jb s2
        gotoxy 10,8
        putchar '/'
s2:
        cmp bl,5
        jb s3
        gotoxy 11,7
        putchar 179   ;"│"
s3:
        cmp bl,4
        jb s4
        gotoxy 11,6
        putchar 179   ;"│"
s4:
        cmp bl,3
        jb s5
        gotoxy 12,6
        putchar '\'
s5:
        cmp bl,2
        jb s6
        gotoxy 10,6
        putchar '/'
s6:
        cmp bl,1
        jb fin
        gotoxy 11,5
        putchar 'O'
fin:
        pop bx
        ret
muneco endp
_end ahorcado








jueves, 20 de junio de 2013

PUTS Y GETS


   Para ir completando la librería que corresponde a STDIO y poder usarla en nuestro primer ejemplo complejo, necesitamos crear las funciones de entrada y salida de cadena. Es decir, aquellas que nos permitirán, introducir e imprimir por pantalla un texto.
    Estas son _gets, _puts y _putchar usadas en las macros scanf y printf, como una de sus opciones.
    Como se ve la función está creada apoyándonos en la macro rutina de main.mac. Por ello debemos incluir main.mac al comienzo.
    Esta función como las demás que he ido poniendo debe de compilarse y luego almacenarse en la librería. Si usáis mis .BAT, se hará con lib.bat y se creará o almacenará dentro de la librería MASM.LIB.
   Lo más evidente de esta rutina es que el _puts no utiliza la función del dos equivalente, sino trabaja directamente sobre la memoria de pantalla en la dirección B000H. Por ello es más rápida que la equivalente del DOS.
 
     PUTSGETS.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
_modelo exe
_code 
rutina _gets p1

        push es
        push di
        push dx
        push si
        mov dx, [bp].p1
        mov ah,0ah
        int 21h
        mov di, [bp].p1
        mov al, [di+1]
        xor ah, ah
        mov si, ax
        add si, di
        inc si
        inc si
        mov byte ptr [si],0
        pop si
        pop dx
        pop di
        pop es
        pop bp
        ret
_gets endp


;imprime un caracter con el color especificado en dh.
;el caracter esta en dl

rutina _putchar 
        mov caracter,al
        mov al,ah
        push ax
        mov ax,offset caracter
        push ax
        call _puts
        pop ax
        pop ax
        ret
 _putchar endp

rutina _puts p1,p2
     
        push es
        push SI
        push di
        push bx
        push dx
        push cx
        mov ax,40h
        mov es,ax
        mov dl,es:[4ah]
        mov al,es:[51h]
        xor dh,dh
        push dx
        mul dl
        xor dx,dx
        mov dl,es:[50h]
        add ax,dx
        shl ax,1
        mov di,ax
        mov al,es:[49h]
        cmp al,7
        jb sb800
        ja sa000
        mov ax,0b000h
        jmp listo

sb800:
        mov ax,0b800h
        jmp listo
sa000:
        mov ax,0a000h
 listo:
        mov bx,es:[4ch]
        sub bx,es:[4ah]
        sub bx,es:[4ah]
        mov es,ax
        mov si,[bp].p1
        mov ax,[bp].p2
        xchg ah,al
 _impr:
        mov al,[si]
        or al,al
        jz _fin_print
gestion:
        cmp al,0dh
        jnz s1
        pop dx
        push dx
        shl dx,1
        push ax
        mov ax,di
        div dl
        mul dl
        mov di,ax
        pop ax
        jmp short sin
s1:
        cmp al,0ah
        jnz s2
        pop dx
        push dx
        shl dx,1
        add di,dx
        jmp short sin
s2:
        cmp al,09h
        jnz con
        dec di
        dec di
        jmp short sin
 con:
        mov es:[di], ax
        inc di
        inc di
sin:
        inc si

;comprobar que di pasa de la longitud de pantalla y si es as¡ hacer un scroll
;de pantalla
        cmp di,bx
        jbe s3
        push ax
        push bx
        mov bh,ah
        mov ax,601h
        mov cx,0
        mov dx,184fh
        int 10h
        push es
        mov ax,40h
        mov es,ax
        sub di,es:[4ah]
        sub di,es:[4ah]
        pop es
        pop bx
        pop ax

 s3:
        jmp _impr

 _fin_print:
        pop dx
        shl dl,1
        mov ax, di
        div dl
        mov dh, al
        shr ah, 1
        mov dl, ah
        mov ah, 2
        mov bh, 0
        int 10h
        pop cx
        pop dx
        pop bx
        pop di
        pop SI
        pop es
        pop bp
        ret
_puts endp
_data 
caracter db 0,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