Vistas de página en total

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








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



martes, 21 de mayo de 2013

APROVECHANDO MAIN.MAC (Función FACTORIAL)

  Vamos ahora a pormenorizar un poco lo que hemos visto anteriormente.
  En el ejemplo de las rutinas de gráficos hemos visto como con un código inicial muy pequeño hemos generado un código más grande.
   ¿Pero que hemos hecho realmente?
  lo que hemos hecho es usar la pila como zona de paso de datos, es decir de interface entre la rutina y el programa que la llama. Pero para que no tengamos que estar contando los indices de pila y memorizando que el primero que metimos era el bp, el siguiente la dirección de retorno, el tercero el x, etc hemos usado una estructura.

Para ello vamos a ver otra rutina. En este caso parte de la librería MATH. La rutina de factorial.
Primero la vamos a ve generada con la estructura y luego con la macro rutina.

FAC.ASM (sin apoyarnos en main.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/>.
 ;estructura  paso de parámetros a través de pila. 
_parametros struc
        _bp dw ?
        _ret dw ?
        p1  dw ?     ;;primer sumando
        p2  dw ?     ;;segundo sumando
        p3  dw ?     ;;resultado
        p4  dw ?
        p5  dw ?
        p6  dw ?
        p7  dw ?
        p8  dw ?
 ends

; codigo
code segment byte public 'code'
      assume cs:code,ds:data
      public _fac
      extrn _mult:near
_fac proc near
        push bp
        mov bp,sp
        push bx
        push di
        mov bx,[bp].p1 , indexación a través de la estructura para recoger el parametro p1
        mov di,[bp].p2
        mov word ptr [di],1
        mov word ptr [di+2],0
        mov word ptr aux,0
        mov word ptr aux+2,0
 otro:
        mov ax,[bx]
        cmp aux,ax
        jnz no
        mov ax,[bx+2]
        cmp aux+2,ax
        jz fin
     no:
        add aux,1
        adc aux+2,0
        push di
        push di
        mov ax,offset aux
        push ax
        call _mult
        add sp,6
        jmp otro
   fin:
        pop di
        pop bx
        pop bp
        ret
_fac endp
code ends
data segment byte public 'data'
aux dw 0,0
data ends
end


  Como se puede apreciar el código está bastante claro al haber usado la estructura, ya que nos ha permitido direccionar fácilmente los datos de intercambio en pila.
  Pero ahora vamos a hacer el código usando main.mac y la macro rutina.


FAC.ASM (apoyarnos en main.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/>.

; codigo
include main.mac    ; incluimos las macros y nuestras propias directivas de compilación
extrn _mult 
_modelo exe         ;directiva propia para elegir forma de colocar la data en la función
_code                   ;directiva propia. definición del segmento de codigo
rutina _fac p1,p2   ;directiva propia  definición de función con parámetros
        push bx
        push di
        mov bx,[bp].p1 ; indexación a través de la estructura para recoger el parametro p1
        mov di,[bp].p2
        mov word ptr [di],1
        mov word ptr [di+2],0
        mov word ptr aux,0
        mov word ptr aux+2,0
 otro:
        mov ax,[bx]
        cmp aux,ax
        jnz no
        mov ax,[bx+2]
        cmp aux+2,ax
        jz fin
     no:
        add aux,1
        adc aux+2,0
        push di
        push di
        mov ax,offset aux
        push ax
        call _mult
        add sp,6
        jmp otro
   fin:
        pop di
        pop bx
        pop bp
        ret
_fac endp
_data          ;directiva propia  definición de zona de datos
aux dw 0,0
_end           ; directiva propia. Fin de programa. En este caso no damos nombre pues es librería.


  Como vemos ha quedado más simple.  Igualmente se podría realizar una macro para salvar todos los registros a pila al inicio, pero entonces el código crearía volcados y recuperaciones de registros a pila inútiles. Como lo que queremos con el ensamblador es no crear ni un solo byte innecesario, es mejor sacrificar esa comodidad si implica código basura.








domingo, 19 de mayo de 2013

¿COMO FUNCIONA "RUTINA"?

 Vamos a comprobar que sucedió con la librería GRAPHICS.ASM  al compilarla.
  Os muestro la parte del listado generación de programa y de publicación de variables.

 Pues aquí os pongo el listado generado por el compilador donde se desarrolla el código de forma completa.
  Este pues sería el código que deberíamos colocar si no hubiéramos creado nuestras macros.
   En un programa de 45 líneas tenemos 15 generadas por el precompilador. Esto sin contar que ya hemos publicado las funciones, y hemos creado una estructura de trabajo más aprosimada al "C" que al ensamblador.
     Básicamente mi macro "rutina nombre x1,y1,z1" equivale a "proc nombre arg x1,y1,z1" en el TASM.

     0     _code    
1   1 0000 code segment byte public 'code'
     2
     3     rutina _line x1,y1,x2,y2,color
1   4 *000 _linep struc
1   5 *000  01*(????????)      dd ?
2   6 *004  01*(????)  x1  dw ?
2   7 *006  01*(????)  y1  dw ?
2   8 *008  01*(????)  x2  dw ?
2   9 *00A  01*(????)  y2  dw ?
2   10 *00C  01*(????)  color dw ?
1   11 *00E _linep ends
1   12 0000     _line proc near
 1   13 *0000  55     push bp
 1   14 *0001  8B EC     mov bp,sp
    15
    16     ; espacio para la rutina
    17 0003  5D     pop bp
    18 0004  C3     ret
    19 0005     _line endp
    20
    21     rutina _putpixel x,y,color1
1   22 *005 _putpixelp struc
1   23 *000  01*(????????)      dd ?
2   24 *004  01*(????)  x  dw ?
2   25 *006  01*(????)  y  dw ?
2   26 *008  01*(????)  color1  dw ?
1   27 *00A _putpixelp  ends
1   28 0005     _putpixel proc near
1    29 *0005  55     push bp
1    30 *0006  8B EC     mov bp,sp
    31 0008  53     push bx
    32 0009  51     push cx
    33 000A  52     push dx
    34 000B  8B 46 0C     mov ax,[bp].color
    35 000E  B4 0C     mov ah,0ch
    36 0010  BB 0000     mov bx,0
    37 0013  8B 4E 04     mov cx,[bp].x
    38 0016  8B 56 06     mov dx,[bp].y
    39 0019  CD 10     int 10h
    40 001B  5A     pop dx
    41 001C  59     pop cx
    42 001D  5B     pop bx
    43 001E  5D     pop bp
    44 001F  C3     ret
    45 0020     _putpixel endp



Symbol Name  Type Value

??DATE  Text "08/05/13"
??FILENAME  Text "graphics"
??TIME  Text "15:34:19"
??VERSION  Number 0200
@CPU  Text 0101H
@CURSEG  Text CODE
@FILENAME  Text GRAPHICS
@WORDSIZE  Text 2
_LINE  Near CODE:0000
_PUTPIXEL  Near CODE:0005

viernes, 10 de mayo de 2013

_LIN_COMAND

   _LIN_COMAND - IMPLEMENTACIÓN DE  ARGC Y ARGV

  Una vez visto lo que queremos hacer y definido la parte exterior del programa, es decir lo que vemos y escribimos habitualmente, vamos a pasar al código almacenado en nuestras librerías.
   Para poder trabajar fácilmente, se crearon las liberías (.LIB). Estas son almacenes de código compilado, que serán recopiladas por el linker según vayan siendo declaradas.
   El programa declarará las librerías, que han de ser usadas, a través del compilador, y el linker las añadirá al código final, enlazando las llamadas a ellas con la posición donde coloca cada rutina. 
   Debido a que la unión la realiza el linker, el código fuente de las librerías ha de ser compilado y posteriormente almacenado en la librería.  Para ello usaremos el compilador, en este caso TASM, y posteriormente el gestor de librerías TLIB para almacenar el " código objeto" en la librería.
   Como todo esto es parte del manejo de los compiladores, no entraré en como se hace.
  Simplemente quiero recordar que la mayor parte del código a utilizar lo deberemos almacenar en las librerías. 
   Existen librerías ya construidas, que pueden ser usadas. Como el sistema que utilizo de paso de parámetros es el estandar de C, se pueden enlazar con nuestros programas cualquier rutina de las librerías de Borland C. En mi caso no existe librería C ya que, no hay código previo. Parto de cero. Todo el código es nuevo.
  Más adelante indicaré como aprovecharnos de funciones ya creadas en otras librerías, para realizar programas con apoyo de instrucciones más complejas.

 Como mostré en la declaración del Main.mac la macro main llama a una función que extrae los argumentos de la linea de comandos y los almacena en una estructura, para luego poder analizarlos individualmente. Esta función es la que hoy presento. La función _lin_comand.

   Como se ve en la definición de la función existe algunas novedades.
   Primero Public. Directiva de compilación que permite declarar el nombre como localizable por el linkador para poder asociar la rutina al resto del código. Public lo que hace es añadir una entrada en una tabla de referencias en la librería con el nombre y la dirección en del código dentro de la librería. De esta manera el linkador podrá tomar la función y añadirla al código en curso. Si no se declara no será localizable.
 Igualmente debemos publicar las variables que debamos alcanzar desde el exterior. En este caso   _argc y _argv, que son precisamente las que se declararon como extern en el argum.mac.
   
  La función _lin_comand recorre la linea de comandos del dos, y va tomando las palabras, almacenando la dirección de cada una en una lista de punteros llamada argv. El número de palabras lo guarda en argc.
  Esta función no será incorporada al main.mac si no se incluye la cabecera ARGUM.MAC



MAIN.ASM (Versión Clásica TASM2.0)
; 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 libreria del sistema operativo
code segment byte public 'code'
      assume ds:data, cs:code
      public _lin_comand
      public _argc
      public _argv
_lin_comand proc near
        push ds
        push es
        push dx
        push bx
        push cx
        push si
        push di
        xor cx, cx
        cld
        mov si, 81h
        mov ax, data
        mov es, ax
        mov di, offset _lista
        mov bx, 80h
        mov cl,[bx]
        rep movsb
        mov cl, [bx]
        inc cx
        push es
        pop ds
        cmp cx, 0
        ja anali
        mov _argc, 0
        jmp fin

    anali:
        mov bx, offset _argv
        mov di, offset _lista
        mov al,' '
    anali1:
        repe scasb
        cmp cx, 0
        je fin
        dec di
        inc cx
        mov [bx], di
        inc bx
        inc bx
        repne scasb
        inc _argc
        dec di
        mov byte ptr [di], 0
        inc di
        cmp cx, 0
        je fin
        jmp anali1

    fin:
        pop di
        pop si
        pop cx
        pop bx
        pop dx
        pop es
        pop ds
        ret
_lin_comand endp
code ends
data segment byte public 'data'
        _argc db 0
        _argv dw 16 dup(0)
        _lista db 20 dup(0)

data ends
end

Si aplicamos las macros de mejora de directivas mías definidas en main.mac quedará.

MAIN.ASM (Versión Propia con mis macros)
; 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
title libreria del sistema operativo

_modelo exe

_code
      public _lin_comand
      public _argc
      public _argv
_lin_comand proc near
        push ds
        push es
        push dx
        push bx
        push cx
        push si
        push di
        xor cx, cx
        cld
        mov si, 81h
        mov ax, data
        mov es, ax
        mov di, offset _lista
        mov bx, 80h
        mov cl,[bx]
        rep movsb
        mov cl, [bx]
        inc cx
        push es
        pop ds
        cmp cx, 0
        ja anali
        mov _argc, 0
        jmp fin

    anali:
        mov bx, offset _argv
        mov di, offset _lista
        mov al,' '
    anali1:
        repe scasb
        cmp cx, 0
        je fin
        dec di
        inc cx
        mov [bx], di
        inc bx
        inc bx
        repne scasb
        inc _argc
        dec di
        mov byte ptr [di], 0
        inc di
        cmp cx, 0
        je fin
        jmp anali1

    fin:
        pop di
        pop si
        pop cx
        pop bx
        pop dx
        pop es
        pop ds
        ret
_lin_comand endp

_data
        _argc db 0
        _argv dw 16 dup(0)
        _lista db 20 dup(0)
_end


  Como se ve hemos simplificado el programa y lo hemos acercado a TASM5.0. Además, ahora con solo cambiar la línea de"_model exe" a "_model com" podremos compilarla librería para realizar ficheros .com

martes, 7 de mayo de 2013

PRIMER PROGRAMA EJECUTABLE

  Como se ve, con una pocas instruciones, hemos creado un código, muy sencillo de leer y muy estructurado, en ensamblador. Tenemos que tener en cuenta que este cCon el vistas hasta ahora, parece imposible componer algo ejecutable de forma fácil. Pero, para adelantar lo que queremos conseguir, vamos a poner el código de un programa ".exe"

  En este caso el programa, no realizaría ninguna función. Simplemente ejecutaría y saldría al sistema de nuevo.

  En este código se puede ver el uso de cada una de las macro definidas en la cabecera main.
  El código se divide en tres partes:
       include - Directiva para incluir  la cabecera main, para que la lea las macros que definen nuestras nuevas directivas de compilación
       _data  Directiva propia. Definición del segmento de datos, para luego delcarar las varialbes
      _modelo - Directiva propia. Indica el modelo de programa que deseamos exe o com
       _stack - Directiva propia. Define la pila en 300 bytes
       _code  - Directiva propia. Define la zona de programa. Dentro declaramos el procedimiento. En este caso _vacio
       _end- Directiva propia. Fin de codigo. En este caso hay que indicar el nombre de larutina principal, ya que se trata del programa ejecutable.
      main - Función de inicialización cuyo código veremos posteriormente.
      exit - Macro de salida al sistema incluida en main.mac, en la que se indica el código de salida


   En este caso no incluimos la cabecera argum.mac, y por lo tanto no será incluido el código de la librería _lin_comand y no leeremos la linea de comando. 
   En este caso el programa no hace nada en particular. Eso lo dejaremos para cuando aumentemos las librerías. Ahora solo interesa ver la estructura base del código.
    Como vemos he puesto la data al final, para que pueda funcionar mi directiva _data con la de _modelo, y me permita cambiar el programa de exe a com. Si no ponemos la directiva _modelo el programa será exe


El código se puede compilar en el ensamblador en cualquier compilador anterior a MASM, pero como se ve la estructura es equivalente a TASM  2.0 y por supuesto puede compilarse en TASM2.0.
   

PRUEBA 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
title prueba1 
_modelo exe  ; define formato exe. DS y CS separados.   (equivale a .model compact en TASM)
_stack 300                           ; (equivale a .stack  en TASM)

_code                                   ; (equivale a .code en TASM)
_vacio proc far  
        main
        exit 0
_vacio endp
_data                                    ; (equivale a .data en TASM)
  help db "Ejemplo",10,13
_end vacio

domingo, 5 de mayo de 2013

MAIN

 MAIN.MAC - CABECERA PRINCIPAL


   Primero y ante todo decir que el código que voy a implementar no usa muchas directivas ya creadas en MASM y TASM.  Debido a que yo daba clases de Ensamblador y a que comencé con ASM, preferí inicialmente crear directivas propias a usar las que tenía el compilado TASM 2.0. (rutina en vez de proc, modelo en vez de model, _data en vez de .data... etc). De esta forma podía demostrar que realmente las directivas eran definibles. 
    Por eso, aunque muchos digan que lo que estoy haciendo  ya está construido en el compilador, quiero que vean que muchas de las directivas del TASM 2.0 son prescindibles, y que un buen programador puede usar un pequeño compilador y realizar cualquier tarea.
    Esto es importante para los que hemos tenido que compilar con otros compiladores mucho más simples, por ejemplo para otros microprocesadores, y en los que hemos querido aplicar las mismas reglas de programación que con el 8086.
    
     Por eso ruego paciencia. Primero aplicaré mis directivas, y veremos como resulta un código casi idéntico al del ensamblador TASM 2.0.  Así veremos, sin necesidad de desensamblar, lo que realmente hacen esas directivas, que simplifican el código, pero que ocultan cosas, al programador, que se deben conocer y entender.
    Sin embargo, si pensamos usar standares y acoplarnos a códigos de alto nivel, nos conviene usar las directivas incorporadas en el compilador TASM, para compatibilizar de forma sencilla el código con otros lenguajes de alto nivel.
   Por eso a partir de la entrada 50 del blog haré una comparativa de las dos formas y comenzaré a aplicar directamente el código TASM 2.0.

FUNCIONES ACOPLADAS EN MAIN.MAC
    

  Todo lo que iré poniendo ahora será para generar ficheros .exe. Más adelante, Cuando hayamos implementado programas ya con las directivas del TAM completas, lo generaremos en .com.

 Como siempre habrá una cabecera ".mac", bueno ".inc" si se desea, con las macros y definiciones de las funciones. Cuando simplifique los programas a versión completa las llamaré ".inc" para distinguirlas.

  En esta cabecera, como cabecera de inicialización de programa incluyo algunas sentencias de precompilación, que servirán para asignar memoria, segmentos, pila y por supuesto la estructura de lista de argumentos.
       
     Rutina (equivale a proc+ arg en TASM)
     Permite crear estructura para el paso de parámetros través de pila, de esta manera será muy sencillo declarar una función y pasarla hasta 10 variables . Declara  al tiempo la función como publica, al modo que lo hace "C", pero sin apenas darnos cuenta. Se verá mejor cuando coloque la función Graphics.

  _modelo (equivale a model en TASM)
     Sirve para definir el tipo de programa .com o .exe. si no se usa es .exe. Esto se usará paa definr los segmetos
      EN esta macro creamos una constante que podemos identificar en la macro _data, para asignar la zona de datos a DS o CS, según el programa sea . com o .exe. Esto no evitará tener que utilizar dos librerías (una para como y otra para exe) , si no queremos tener que compilar todas las librerías cada vez que hagamos un programa.
   Pero sí nos permitirá tener un programa único para cada librería y una de muy  forma simple compilarlo para uno y otro modo.

  _code (equivale a .code en TASM) 
      Nos define el comienzo de la zona de código.

  _data (equivale a .data en TASM) 
    Nos define el comienzo de la zona de datos. Puede estar antes o después del code, aunque en las funciones es recomendable que esté detrás.

   _end  (equivalente a end en TASM)
        Cierra el programa en caso un programa se debe indicar el nombre de la rutina principal
  _stack (equivale a .stack en TASM)
         Nos inicializa la pila al tamaño indicado en NUMERO

   Todas estas macros crean un entorno de trabajo equivalente al estandar de TASM y MASM, pero sin usar su directivas. Como solo usa if y macro con ellas puede crearse el entrono equivalente a TASM pero en el compilador inicial ASM. Todas estas macros pueden ser eliminadas y substituidas por las directivas equivalentes del TASM 2.0. Cosa que haremos más adelante.

   Con estas  macros podemos ver como se pueden crear no solo llamadas a funciones sino nuevas directivas de compilación. A partir de la entrada 50 del blog veremos como crear con las macros directivas de PROGRAMACIÓN ESTRUCTURADA tales como FOR o WHILE.

 Otras macros más interesantes aún pues no las tiene el TASM son:

   dim - Permite crear una variable compleja tomando una estructura como plantilla.
   asigdata - Nos permitirá reasignar una zona de memoria al segmento de datos.

   of_reg- devuelve la dirección del registro indicado de una tabla que se encuentre en memoria, creada bajo una estructura.

    exit- Fin de programa con salida al sistema.

   encriptar y desencriptar- Funciones especiales que permitirán encriptar parte de los datos del programa, de manera que no sean legibles mediante un Dump del código, pero si sean legibles una vez inicializado el programa.

   string, char, integer Definición de los tres tipos de variables más importantes. Serán usadas en la inicialización de los datos, por lo que están incluidas en el main como definición de variables.

   main - comienzo del programa. Es la encargada de llamar a la linea de comandos si se definieron parámetros y la encargada de asignar la zona de datos si se definió con la macro _data. Así mismo prepara el PSP para que la salvar la dirección de vuelta al sistema.

     Dentro del main existe una directiva por la cual si no se ha añadido la cabecera argum.mac, y por lo tanto no se ha definido la variable externa _line_comand, no se llamará a la función de la librería correspondiente. De esta forma, si no necesitamos argumentos no consumiremos código innecesario.
  Main parece una forma de iniciar el programa pero es mucho más, en realidad  inicializa el programa., reserva la memoria, recoge los argumentos de la línea de comando, y prepara la ejecución. Por ello tomé este nombre para crear una rutina especial, a la que llamaré siempre al inicio del programa ejecutable. Se encargará de inicializar la memoria, la pila del sistema y recoger los argumentos de la linea de comandos, para que posteriormente mediante argv argc  tratarlos.
   En el caso del main  no incluimos la función directamente en la cabecera, pues en este caso el tamaño de la función supera al código de llamada.

  Esta rutina no tendrá argumentos, y será llamada simplemente main
 
   Con esta cabecera estamos creando un entorno de trabajo equivalente al TASM completo, pero sin usar sus directivas más complejas.


MAIN.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/>.
   ;Declaracion de una rutina (función) con paso de variables
    Esta macro crea una estructura de compilación para ser usada  posteriormente en la recogida de los datos pasados a la función.

;define modelo .com o .exe para definir forma de colocar assume en _data
_modelo macro tipo
   tipo equ 1
endm


rutina macro nombre,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10
   nombre&p struc
         dd ?
   irp arg,<arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10>
          ifnb <arg>
             arg  dw ?
          endif
        endm
    nombre&p  ends
        public nombre
nombre proc near

        push bp
        mov bp,sp
        endm


_end macro nombre
 ends  
   end nombre
endm

;genera la cabecera de datos
_data macro
ifndef com
    ends  ;asegura el cierre del segmento anterior
    data segment byte public 'data'
endif
endm

_code macro
    code segment byte public 'code'
    assume cs:code
ifdef com
  assume ds:code
else
    assume ds:data ; esto nos obliga a definir siempre un data aunque sea vacío
 endif
endm

;genera una pila con el tama¤o indicado
_stack macro NUMERO
     pila segment byte stack 'stack'
          db NUMERO dup (0)
     pila ends
     assume ss:pila
 endm


;coloca en pila de direccion del PSP para salir al dos y llama
;a la gesti¢n de la linea de comandos si se ha usado parametros
main macro
    push ds
    xor ax, ax
    push ax
ifdef _lin_comand
    call _lin_comand
endif
ifdef data
    asigdata data
endif
endm

;asigna un nuevo segmento de datos de trabajo
asigdata macro etiq
    assume ds:etiq
    mov ax, etiq
    mov ds, ax
endm

;dimensiona una tabla de numero de elementos con una estructura regis
dim macro tablas,regis,numero
        tablas regis numero dup (<>)
endm


; devuelve la direccion de un registro en una tabla en memoria
of_reg macro dest,lista,numero
      mov dest,offset lista[numero*type(lista)]
endm

;Sale al sistema devolviendo un codigo
exit macro codigo
     mov ah,4ch
ifdif <codigo>,<al>
     mov al,codigo
endif
     int 21h
endm

;encripta una zona de datos con un codigo dado
encriptar macro inicio,bytes,codigo
ifndef _encriptar
     extrn _encriptar:near
endif
         xor ax,ax
         push ax
         mov ax,codigo
         push ax
         mov ax,bytes
         push ax
         lea ax,inicio
         push ax
         call _encriptar
         add sp,8
 endm

;desencripta una zona de datos con un codigo dado
desencriptar macro inicio,bytes,codigo
ifndef _encriptar
        extrn _encriptar:near
endif
         mov ax,28h
         push ax
         mov ax,codigo
         push ax
         mov ax,bytes
         push ax
         lea ax,inicio
         push ax
         call _encriptar
         add sp,8
 endm

;define una cadena de entrada de texto para el scanf
string macro nombre,long
     nombre db long+1,0,long+2 dup (0)
endm

char macro var,ini
  ifb <ini>
      var db ?
  else
      var db ini
  endif
endm

integer macro var,ini
  ifb <ini>
      var dd ?
  else
      var dd ini
  endif
endm