Ejemplo Reloj

Este ejemplo muestra como colocar la hora del sistema en el centro de la pantalla.


Se utiliza para ello la lectura de la hora del sistema con el servicio: 2CH de la interrupción 21h

Para esto se utilizará una cadena -arreglo- con el formato HH:MM:SS:CC, la cual se sustituirá cada valor obtenido como la hora, los minutos, los segundos y las centésimas, los cuales se sustituirán en sus respectivas letras HH, para la hora, MM para los minutos, etc. Al término de llenar la cadena con los minutos, segundos y centésimas se imprimirá en la pantalla, repitiendo el proceso hasta que oprimamos la tecla ESC.

Para obtener la hora del sistema se obtendrá con:
INT 21h / AH=2Ch - Leer la hora del sistema;
return: CH = hour. CL = minute. DH = second. DL = 1/100 seconds.

Así que obtendremos como podemos ver la hora en CH, esto hora tendrá dos dígitos 01 hasta 24 por ejemplo. Entonces lo que se tiene que hacer es poner las decenas -si hay- en la primera posición -si no hay pondrá cero- y las unidades en la segunda. esto lo hacemos con la instrucción AAM esta instrucción pasa las decenas a AH y las unidades a AL .

Solo sustituimos los valores respectivos en la posición de arreglo.
Por ejemplo, si la hora obtenida es la 1:35 P.M. al obtener la hora nos devolverá:

Lectura de la 1:35 PM.
CX DX
CH CL DH DL
0D 35 00 2F


Así, obtendremos 0D -hexadecimal- ósea 13 decimal, con AAM, obtendremos en AH las decenas -ósea 1- y en AL las unidades -ósea 3-.

Ahora, pondremos en la cadena su equivalente en el código ASCII, del 1 es 31h del 3 es 33h, aquí aplicamos un truco, ya que si observamos el valor de 0 es 30h, el de 1 es 31h, etcétera, es decir, sumamos 30h al número que queremos para obtener su código ASCII correspondiente.
Así que a AH sumamos 30h con la instrucción ADD ah,30h y lo mismo con AL ADD AL,30H
También podemos hacerlo en un solo paso con ADD AX,3030h
Ahora resta guardar en la cadena -recuerde que es un arreglo en ensamblador en realidad- el valor en su posición.
mov Hora[0],ah ; Aquí las decenas

mov Hora[1],al ; Aquí las unidades

Repetimos la misma acción para los minutos, segundos y las centésimas e imprimes la cadena. quedando como:
13:53:00:02

Finalmente repetimos hasta que sea la tecla de salida, para ello leemos una tecla con el servicio 1 de la int 16h, para que no se detenga si no hay tecla.

Sacamos la tecla del buffer con el servicio 0 de la Int 16h.

Finalmente verificamos que sea el código de la letra S o 83h y si es así terminamos sino repetimos todo nuevamente.

;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------

org 100h  


  mov ah,9
  mov dx,offset car
  int 21h

inicio:
  ;Leemos la hora
  mov ah,2ch
  int 21h
  
  ;DH, hora  
  xor ax,ax    ;Limpiamos
  
  mov al, ch   ;Pasamos decenas ah, unidades a al
  AAM  
  
  add ah, 48
  add al, 48    
  
  mov hora[0],ah  ;Guardamos en el arreglo
  mov hora[1],al  ;HH:... -> 12:... etc.
           
  ;Minutos 
  Mov al,cl
  AAM
  
  add ah, 48
  add al, 48 
  mov hora[3],ah
  mov hora[4],al        
  
  ;Segundos
  Mov al,dh
  AAM
  
  add ah, 48
  add al, 48 
  mov hora[6],ah
  mov hora[7],al        
             
  ;Centésimas
  Mov al,dl
  AAM
  
  add ah, 48
  add al, 48 
  mov hora[9],ah
  mov hora[10],al        
             
Cursor:
  
  mov ah,2       ;Ubicamos el cursor
  mov dh, ren
  mov dl, col
  int 10h
      
Imprimir:  
   
  mov ah,9             ;Imprimimos
  mov dx,offset hora   ;HH:MM:SS:CC
  int 21h
  
  ;Salir con S mayuscula 83 
  
  mov ah,01h           ;Hay tecla?
  int 16h
  jnz prefin           ;Si hay 
  jmp inicio           ;Si no repetimos
  
prefin:
  
  ; vaciamos la tecla del buffer
  mov ah,0
  int 16h
  
  ;Verificamos que sea la S
  
  cmp al,83
  jz fin               ;Si es S salimos
  jmp inicio           ;Si no iniciamos otra lectura...
fin:
  int 20h              ;Salimos
ret
         
col  db 35
ren  db 12         
Hora db "HH:MM:SS:CC$"  
Car  db "Oprime S para salir. $" 
Así queda.


Leer una cadena


En este ejemplo se propone obtener una cadena de hasta 10 caracteres en la pantalla.

La lectura se hace carácter x carácter y antes de alcanzar la longitud -10 caracteres- podemos dar enter para indicar que ya terminamos.

Una opción extra es mover el cursor con las flechas ← → y colocar el cursor en el índice. El índice que se lleva con el registro SI se controla que este entre 0 y el número a leer máximo, es decir, la longitud de la cadena.
Las flechas ←,↑,↓,→, -códigos 27,24,25,26 respectivamente- así, como las teclas de función, colocan en AL un código 0h, y en AH, el código ASCII de la tecla. Por eso en estos casos verificamos el contenido del registro AH.


Otra opción extra es la solicitud de un número. En este caso, debemos además de verificar las teclas especiales -las teclas que en AL tienen un 0 y en AH el código ASCII de la tecla- que sea un carácter valido. En el caso de los números 0,1,2,3,4,5,6,7,8 y 9; para números positivos El signo - para los negativos y el punto para los reales.

;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------

org 100h

;leer cadena
mov si,0
inicio:

mov ah,0
int 16h  

cmp al,13      ;Verificamos si es enter 13
jz imp

cmp al,8       ;BackSpace o retroceso 8
jnz sigue

dec si         
mov cad[si],"$"
;Leer cursor
mov ah,3
int 10h     
dec dl   ;Una columna menos en cursor tambien
;mover cursor
mov ah,2
int 10h
mov ah,9
mov al," "
mov cx,1
mov bl,15
int 10h

jmp inicio 

sigue:
mov ah,9         ;Imprimir caracter
mov cx,1         ;Veces
mov bl,15        ;Color
int 10h
;Leer cursor
mov ah,3
int 10h     
;mover cursor
mov ah,2
inc dl           ;Incrementamos columna
int 10h
    

;Mostrar el caracter leido
mov cad[si],al 
mov cad[si+1],"$"

cmp si,10        ;Numero de caracteres
jz imp    

inc si

jmp inicio 
imp:
;Leer cursor
mov ah,3
int 10h     
;mover cursor
mov ah,2 
inc dh
mov dl,0
int 10h

mov ah,9
mov dx,offset cad
int 21h
fin:
int 20h

ret     

Cad  db 10 dup(32)


              
Primer ejemplo con retroceso.
;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------

GotoXY MACRO x, y
  PUSH AX  
  PUSH BX
  PUSH DX

    ;Poner cursor
  mov ah,2
  mov dh, y  ;Ren
  mov dl, x  ;Col
  mov bh,0
  int 10h
  
  POP DX  
  POP BX
  POP AX
ENDM

impC  MACRO CAR,No
  PUSH AX  
  PUSH BX
  PUSH CX
  PUSH DX

  
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  mov ah,9
  mov al,CAR
  mov bh,0
  mov bl,00011111b
  mov cx,No
  int 10h
  
  mov ah,3
  int 10h
  
  mov ah,2  
  add dl,No
  int 10h
  
  POP DX
  POP CX
  POP BX
  POP AX
ENDM 

Imp MACRO Cad
  Push ax
  Push dx       
        
  mov ah,9
  mov dx,offset Cad
  int 21h
  
  Pop dx
  Pop ax
ENDM
  
org 100h
  mov ah,0
  mov al,03h
  int 10h               
  
  GotoXY Col, Ren
  
  
  ;Imprimir texto
  Imp text
          
          
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  IMPC 91,1
  
  ImpC " ",10
  
  ImpC "]",1
  
  GotoXY 14, Ren
  mov ah,0
  mov al,0    ;Usaremos al como contador...
  mov si,0
inicio:   
  mov ah,3
  int 10h
  
  ;leer caracter
  mov ah,0
  int 16h
  
  
  cmp al,8
  jz Retro  
  
  ;Si es enter Salir.
  cmp al,13 
  jz fin    
  
  cmp al,0
  jz inicio
  jmp Imprime
Retro: 
  cmp si,0
  jz inicio

  dec si             ;Decrementamos el indice
  mov al," "   
  mov cad[si],"$"    ;Ponemoss fin de cadena $
  ;Leemos cursor
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  ImpC Al,1          ;e imprimimos un espacio
                    ;como esta macro mueve el 
  mov ah,3           ;cursor una posición 
                    ;lo regresamos
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor otra verz
  mov ah,2
  int 10h
  
  jmp inicio
Imprime:
  cmp si,10
  jz inicio

  impC AL,1     
Guarda:   

  ; Almacenamos la letra en el arreglo
  mov cad[si],al
  mov cad[si+1],"$" 
  inc si 

  jmp inicio 

Fin:     
  GotoXY 10,10    
  Imp Text2
  Imp Cad
  
  mov ah,0
  int 16h
  
  INT 20H
ret
        
Long db 10         
Ren  db 5
Col  db 5                   
Cad  db 20 dup(32),"$"                   
Text db "Nombre : $"  
Text2 db "La Cadena es $"

                                
              
Segundo ejemplo retroceso pero no con ← y →, ya con macros.
;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------

GotoXY MACRO x, y
  PUSH AX  
  PUSH BX
  PUSH DX

    ;Poner cursor
  mov ah,2
  mov dh, y  ;Ren
  mov dl, x  ;Col
  mov bh,0
  int 10h
  
  POP DX  
  POP BX
  POP AX
ENDM

impC  MACRO CAR,No
  PUSH AX  
  PUSH BX
  PUSH CX
  PUSH DX

  
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  mov ah,9
  mov al,CAR
  mov bh,0
  mov bl,00011111b
  mov cx,No
  int 10h
  
  mov ah,3
  int 10h
  
  mov ah,2 
  
  add dx,No
  int 10h
  
  POP DX
  POP CX
  POP BX
  POP AX
ENDM  

iCC  MACRO Cad,Color
  PUSH AX  
  PUSH BX
  PUSH CX
  PUSH DX
  PUSH SI

  mov SI,0
ini_icc:
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  mov ah,9
  mov al,CAD[si]
  
  cmp al,0
  jz fin_icc
  mov bh,0
  mov bl,00011111b
  mov cx,1
  int 10h
  
  mov ah,3
  int 10h
  
  mov ah,2  
  add dl,1
  int 10h 
  inc si
  jmp ini_icc
fin_icc:  
  
  pop si
  POP DX
  POP CX
  POP BX
  POP AX
ENDM  

iCC2  MACRO Cad,Color
  PUSH AX  
  PUSH BX
  PUSH CX
  PUSH DX
  PUSH SI

  mov SI,0
ini_icc2:
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  mov ah,9
  mov al,CAD[si]
  
  cmp al,0
  jz fin_icc2
  mov bh,0
  mov bl,00011111b
  mov cx,1
  int 10h
  
  mov ah,3
  int 10h
  
  mov ah,2  
  add dl,1
  int 10h 
  inc si
  jmp ini_icc2
fin_icc2:  
  
  pop si
  POP DX
  POP CX
  POP BX
  POP AX
ENDM

Imp MACRO Cad
  Push ax
  Push dx       
        
  mov ah,9
  mov dx,offset Cad
  int 21h
  
  Pop dx
  Pop ax
ENDM

LeeCad MACRO Cad,Long
  push si
  push ax
  push bx
  push cx
  push dx

  mov ah,0
  mov al,0    ;Usaremos al como contador...
  mov si,0
inicio:   
  mov ah,3
  int 10h
  
  ;leer caracter
  mov ah,0
  int 16h 
  
  cmp al,8
  jz Retro  
  
  ;Si es enter Salir.
  cmp al,13 
  jz fin 
  
  ;Si es flechas
  ;
  cmp ah,4Bh         ;Es Flecha Izq?
  jz FlechaI
  
  cmp ah,4Dh         ;Es flecha Der?
  jz FlechaD
  
  jmp Imprime
FlechaI:
  cmp si,0           ;Si es 0 
  jz inicio          ;No hace nada
  
  dec si             ;Sino decrementa
  ;Leemos cursor
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  
  Jmp inicio 
FlechaD:
  cmp Cad[si],"$"    ;Comparamos con el final
  jz inicio          ;si se alcanza inicio
  
  inc si             ;Sino decrementa
  ;Leemos cursor
  mov ah,3           
  int 10h     
  inc dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  jmp inicio
  
Retro:    
  cmp si,0           ;Si es 0 
  jz inicio          ;Regresar
  
  dec si             ;Decrementamos el indice
  mov al," "   
  mov cad[si],"$"    ;Ponemoss fin de cadena $
  ;Leemos cursor
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  ImpC Al,1          ;e imprimimos un espacio
                    ;como esta macro mueve el 
  mov ah,3           ;cursor una posición 
                    ;lo regresamos
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor otra verz
  mov ah,2
  int 10h
  
  jmp Inicio         ;Inicio
Imprime: 
  cmp si,Long        ;Si se alcanza limite
  jz inicio          ;ir a inicio
  
  impC AL,1     
Guarda:                               
  
  ; Almacenamos la letra en el arreglo
  mov cad[si],al     ;Poner fin de cadena
  mov cad[si+1],"$"  ;al final 
  inc si        

  jmp inicio         ;ir inicio
Fin:     

  Pop dx
  pop cx
  pop bx
  pop ax
  pop si

ENDM    

LeeNum MACRO Num, Long
  push si
  push ax
  push bx
  push cx
  push dx
    
  mov ah,0
  mov al,0    ;Usaremos al como contador...
  mov si,0

inicio1:   
  mov ah,3
  int 10h
  
  ;leer carácter
  mov ah,0
  int 16h 
  
  cmp al,8
  jz Retro1  
  
  ;Si es enter Salir.
  cmp al,13 
  jz fin1 
  
  ;Si es flechas
  ;
  cmp ah,4Bh         ;Es Flecha Izq?
  jz FlechaI1
  
  cmp ah,4Dh         ;Es flecha Der?
  jz FlechaD1
            
  ;Caracter Valido?
  cmp al,46
  jne Car1
  
  jmp Imprime1
Car1:
  cmp al,57          ;No Valido
  jg  Inicio1
  cmp al,46
  jl  inicio1        ;No valido
  cmp al, 47         ; /
  je  inicio1
  jmp imprime1       ;Car Valido
  
FlechaI1:
  cmp si,0           ;Si es 0 
  jz  inicio1         ;No hace nada
  
  dec si             ;Sino decrementa
  ;Leemos cursor
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  
  Jmp inicio1 
FlechaD1:
  cmp Cad[si],"$"    ;Comparamos con el final
  jz inicio1         ;si se alcanza inicio
  
  inc si             ;Sino decrementa
  ;Leemos cursor
  mov ah,3           
  int 10h     
  inc dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  jmp inicio1
  
Retro1:    
  cmp si,0           ;Si es 0 
  jz inicio1         ;Regresar
  
  
  dec si             ;Decrementamos el indice
  mov al," "   
  mov cad[si],"$"    ;Ponemoss fin de cadena $
  ;Leemos cursor
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor tambien
  mov ah,2
  int 10h
  ImpC Al,1          ;e imprimimos un espacio
                    ;como esta macro mueve el 
  mov ah,3           ;cursor una posición 
                    ;lo regresamos
  mov ah,3           
  int 10h     
  dec dl             ;Una columna menos el 
  ;mover cursor      ;cursor otra verz
  mov ah,2
  int 10h
  
  jmp Inicio1        ;Inicio
Imprime1: 
  cmp si,Long        ;Si se alcanza limite
  jz inicio1         ;ir a inicio
  
  impC AL,1     
Guarda1:                               
  
  ; Almacenamos la letra en el arreglo
  mov cad[si],al     ;Poner fin de cadena
  mov cad[si+1],"$"  ;al final 
  inc si        

  jmp inicio1        ;ir inicio
Fin1:     

  Pop dx
  pop cx
  pop bx
  pop ax
  pop si
ENDM    


org 100h
  mov ah,0
  mov al,03h
  int 10h               
  
  
  
  GotoXY 5, 5
  
  ;Imprimir texto
  Imp textC
          
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  IMPC 91,1 
  ImpC " ",15
  
  ImpC "]",1
  

  GotoXY 5, 6

  
  ;Imprimir texto
  Imp text
          
  ;Quedara asi: [0123456789]               
  ;Poner corchete izq    
  IMPC 91,1 
  ImpC " ",7
  
  ImpC "]",1

  mov ax,15              ;Ponemos el valor
  AAM                   ;Que se leera
  add ax,03030h
  mov AyudaC[20],ah
  mov AyudaC[21],al
  
  GotoXY 0,24
  iCC  AyudaC,00011111b

  
  GotoXY 14, 5
  
  LeeCad Cad,5
  
  GotoXY 10,10    
  Imp TextC2
  Imp Cad       
  
  
  
  mov ax,7              ;Ponemos el valor
  AAM                   ;Que se leera
  add ax,03030h
  mov Ayudan[21],ah
  mov Ayudan[22],al
  
  GotoXY 0,24
  iCC2  AyudaN,00011111b
    
  
  GotoXY 14, 6
  
  LeeNum Cad,5

  GotoXY 10,11    
  Imp Text2
  Imp Cad
  
  mov ah,0
  int 16h
  
  INT 20H
ret
        
Cad    db 20 dup(32),"$"                   
Text   db "N",163,"mero : $"  
Text2  db "N",163,"mero es $"  
Ayudan db "Escriba n",163,"mero hasta XX, Mueva el cursor con ",27,26," finalice con Enter.",0h

TextC  db "Nombre : $"  
TextC2 db "La Cadena es $"  
AyudaC db "Escriba texto hasta XX, Mueva el cursor con ",27,26," finalice con Enter.",0h

              
Tercer ejemplo con retroceso, ←,→, así como implementación del número.

Hay que mencionar que al integrar las macros tal como están puede causar conflictos ya que estas se insertan en realidad en donde se hace el llamado de la macro.
Por esa razón, el utilizar etiquetas -que son fijas- causa conflictos. Por lo tanto, si utiliza macros procure no utilizar etiquetas para los saltos.

En el tercer ejemplo notará, que para solucionar se crearon 2 macros para imprimir el carácter a color con etiquetas diferentes. Toca a usted el realizar los cambios para evitar errores.

Por último todos los problemas fueron resueltos utilizando el emulador 8086 y realizados para entornos de 16 bits.




Ejemplo protector pantalla

Ejemplo de un carácter que se mueve por la pantalla hasta tocar los bordes de la pantalla y cambia de dirección.

Lo que debemos hacer es hacer un ciclo infinito y que salga cuando se oprima una tecla. Para eso está el servicio 0 de la int 16h, pero recuerda sacar la tecla del buffer con el servicio 1 de la misma interrupción.

Una vez realizado esto es colocar el cursor en una posición x, y, una dirección de desplazamiento –en mi caso lo controlo con la variable incx e incy– con un valor cero que indica que no hay incremento y 1 que si lo hay.

Al llegar a un límite, por ejemplo el eje X -columnas- tiene 2, 0 y 79. Al llegar a 0 cambia de dirección y ahora incrementa X, por lo tanto pongo la variable incx en 1, para que se incremente al llegar a 79, pongo el valor de incremento en 0, lo que hace ahora es decrementar.

Al cambiar de dirección incluí una opción interesante. Se obtiene un número aleatorio -usando para esto el servicio 2ch de la interrupción 21h, ósea obtener la hora, y utilizo las centésimas para el número aleatorio.

aleat PROC near
    PUSH BX
    PUSH CX
    PUSH DX
    
    mov ah,02Ch
    int 21h
    
    ;Generamos un numero aleatorio entre 1 y 99
    ;Si es 0       inc 0   muy raro   1%
    ;Si es 1...29  inc 1   ocasional 29%
    ;si es 30..79  inc 2   frecuente 50%
    ;si es 80..99  inc 3   Raro      20%  
    
    cmp dl,0
    jz  cero_1
    cmp dl,30
    jbe uno_1
    cmp dl,79
    jbe dos_1
    mov al,3
    jmp re_1
cero_1:   
    mov al,0 
    jmp re_1
uno_1:
    mov al,1
    jmp re_1   
dos_1:
    mov al,2     
re_1:
    
    POP DX
    POP CX
    POP BX 
    ret
aleat endp                    
                 

De esta forma, divido las 99 posibles valores en 0, para 0, 1..29 para un valor de 1, 30 a 79 para un valor de 2 y 80a 99 para un valor de 3.

De esta forma 1% corresponde al cero, 29$ al 1, 50% al valor 2 y un 20% para el valor 3. Esto hace un comportamiento más o menos normal.

Como puede verse en el código del procedimiento, aleat no restauro el registro AX esto es así a propósito para poner en AL el valor aleatorio entre 0 a 3.
Al Devolver la llamada con:

push ax call aleat mov mx,al pop ax Guardo cualquier valor que tenga ax, genero el número aleatorio, lo almaceno -en el caso del código, el movimiento es en el eje X- y restauro el valor de AX y solo la variable -en este caso- mx que es la variable que utilizo para el incremento o decremento del desplazamiento del -en este caso_, eje X. Lo mismo para el eje Y. Esto lo hacemos cada que llegamos a un limite tanto en el eje X como en el Y.

Antes de poner el cursor que rebota, guardo en la pila los valores del cursor, de esta forma pongo el cursor a mover y antes de regresar a hacer otro ciclo, restauro el cursor, y pongo ahora un espacio, en el mismo lugar del cursor.

Esto tiene como efecto que se vea como si el cursor fuera avanzando por la pantalla.

Finalmente oculte el cursor al empezar el screensaver ocultando el cursor con el servicio 1 de la interrupción 10h. Al salir restauramos el cursor.

Unos toques para entrar y otros para salir como hacer un ClearScreen -CLS- para limpiar la pantalla. etc.

Para probarlo se compiló y se utilizó DOSBox, para ejecutarlo y verlo a toda su velocidad. Para hacer esto montamos la unidad con Mount C: <Directorio en C>

Sin embargo al ejecutarlo va tan rápido que no se ve el efecto deseado, afortunadamente podemos reducir la velocidad de ejecución, oprimiendo ctrl+f11 y ctrl+f12 para reducir y aumentar los ciclos por reloj, y ctrl+f7 y ctrl+f8 para reducir los frames.

En mi caso obtuve una velocidad satisfactoria al reducir a 1 el ciclo por reloj y 0 el frameskip. Pero es tu caso debes probar hasta obtener el resultado dependiendo de la velocidad de tu PC.

;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------


Titulo Macro
    ; Iniciamos moviendo el cursor
    mov ah,2
    mov dh,0
    mov dl,20   ;Columna 20,0 
    int 10h
    
    lea dx, tit1
    mov ah, 9
    int 21h        ; output string at ds:dx  
    
    ; moviendo el cursor
    mov ah,2
    mov dh,1
    mov dl,15   ;Columna 15,1 
    int 10h 
  
    lea dx, tit2
    mov ah, 9
    int 21h        ; output string at ds:dx  
      
Titulo endm

data segment
    ; Area de datos      
    Tit1 db "Universidad Aut",162,"noma de Guerrero",10,13,"$"
    Tit2 db "Programa para mover un caracter por la pantalla","$"
    pkey db "presione una tecla...$" 
    autor  db "Realizado por Rub",163,"n Rodr",161,"guez Camargo.","$"
    x    db 0
    y    db 0  
    mx   db 0
    my   db 0    
    incx db 0   ;0=no
    incy db 1   ;1=si
    
    color db 61
    col_n db 7
ends

stack segment
    dw   128  dup(0)
ends

code segment
start:
  ; Asigna  de datos
    mov ax, data
    mov ds, ax
    mov es, ax
    
    mov color, 7
    call cls
    
    Titulo
    
    ; moviendo el cursor
    mov ah,2
    mov dh,2
    mov dl,25   ;Columna 15,1    
    int 10h 
                  
    lea dx, pkey
    mov ah, 9
    int 21h        ; output string at ds:dx  
    
    ; Esperar una tecla....    
    mov ah, 1
    int 21h
    
    ;Hacemos un CLS y ponemos la pantalla
    ;al centro.    
    mov color,61
    call cls
        
    ;ok ahora ponemos el cursor en el centro. 
    
    ;Iniciamos las variables
    ;x para las columnas y Y para los renglones
    mov x,40
    mov y,12
    
    ; moviendo el cursor
    mov ah,2
    mov dh,y   ;Renglon 12
    mov dl,x   ;Columna 40,12   
    mov bh,0
    int 10h    
    
    ;mov ah,9       ;Lo eliminamos porque
    ;mov al,176     ;no se guardara su posicion
    ;mov bl,87
    ;mov bh,0
    ;mov cx,1
    ;int 10h 
    
    ;Ocultamos el cursor para que no se vea solo el caracter.
    mov ah,1
    mov ch,32
    int 10h
    
    
    ;Repetimos hasta que lleguemos a 0
    ;Vamoa a iniciar con mov hacia la izq.
    mov mx,1     ;Avance en x
    mov my,1     ;AVance en Y
    
inicia:  ;-> esta es una etiqueta    
    
    ;Si Dec entonces restamos el my o my
    mov al,incx    
    cmp al,1  ;Comparamos si es hacia arriba
              ;Esto pone la bandera zf=1 si 
              ;es asi
              ;Asi que buscamos que brinco dar
    jb NegX   ;Salta si al, menor que 1
    mov al,x
    add al,mx
    mov x,al
    jmp CompY               
NegX:  
    mov al,x
    sub al,mx
    mov x,al

CompY:    
    ;Comparamos ahora en Y
    mov al,incy   
    cmp al,1
    jae NegY  ;Salta si al, es mayor o igual 
    mov al,y
    add al,my
    mov y,al
    jmp imprime
NegY:    
    mov al,y
    sub al,my 
    mov y,al      ;Incrementamos mov Y  
    
Imprime:                                             
    ; moviendo el cursor  
    
    mov ah,2
    mov dh,y   ;Renglon 12
    mov dl,x   ;Columna 40,12   
    mov bh,0  
    push ax
    push bx
    push cx
    push dx
    int 10h 
    mov ah,9
    mov al,176
    mov bl,87
    mov bh,0
    mov cx,1
    int 10h
    
    ;Verifica si es 0 para cambiar de direccion
LiInfX:    
    mov al,x
    cmp al,0
    jnz LimInfY
    ;Si es cero, invertimos el movimiento
    mov incx,1
    push ax
    call aleat
    mov mx,al
    pop ax
LimInfY:
    mov al,y
    cmp al,0
    jnz LimSupX    
    mov incY,0
    ;Aleatorio
    push ax
    call aleat
    mov my,al
    pop ax
LimSupX:
    mov al,x
    cmp al,79
    jbe LimSupY  ;Si es menor
    mov incx,0
    ;Aleatorio
    push ax
    call aleat
    mov mx,al
    pop ax 
LimSupY:
    mov al,y
    cmp al,24
    jnz SalidaKey
    mov incy,1
    ;Aleatorio
    push ax
    call aleat
    mov my,al
    pop ax
SalidaKey:    
    ;Leemos una tecla si hay Fun1h int 16h
    mov ah,01
    int 16h 
    jnz fin
    ;Restauramos el cursor y ponemos ' ' es su lugar
    pop dx
    pop cx
    pop bx
    pop ax
    mov ah,9
    mov al," "
    mov bl,61  ;Mismo color de fondo
    mov bh,0
    mov cx,1
    int 10h    
    jmp inicia
    
fin:
    
    ; Esperar una tecla.... 
    mov color,7   
    call cls
    
    Titulo

    ; moviendo el cursor
    mov ah,2
    mov dh,2
    mov dl,20   ;Columna 15,1    
    int 10h 
                  
    lea dx, autor
    mov ah, 9
    int 21h        ; output string at ds:dx  

    ;Mostramos el cursor porque lo ocultamos
    mov ah,1
    mov ch,6
    mov cl,7
    int 10h

    
    mov ah, 1
    int 21h
    
    mov ax, 4c00h ; exit to operating system.
    int 21h    
ends

          
aleat PROC near
    PUSH BX
    PUSH CX
    PUSH DX
    
    mov ah,02Ch
    int 21h
    
    ;Generamos un numero aleatorio entre 1 y 99
    ;Si es 0       inc 0   muy raro   1%
    ;Si es 1...29  inc 1   ocasional 29%
    ;si es 30..79  inc 2   frecuente 50%
    ;si es 80..99  inc 3   Raro      20%  
    
    cmp dl,0
    jz  cero_1
    cmp dl,30
    jbe uno_1
    cmp dl,79
    jbe dos_1
    mov al,3
    jmp re_1
cero_1:   
    mov al,0 
    jmp re_1
uno_1:
    mov al,1
    jmp re_1   
dos_1:
    mov al,2     
re_1:
    
    POP DX
    POP CX
    POP BX 
    ret
aleat endp          
              
cls Proc near  
    push dx
    push cx
    push bx
    push ax
    mov ah,06
    mov al, 25    
    mov bh,color
    mov ch,0
    mov cl,0
    mov dh,24
    mov dl,79
    int 10h
        
    pop ax
    pop bx
    pop cx
    pop dx
    ret
cls endp

end start ; set entry point and stop the assembler.

                 
Imagen antes de empezar.
Imagen al ejecutarlo.
imagen al terminar.

Algo que note es que al revisar que llegue comparo en algunos con cero o 79, es decir, con el valor máximo o mínimo que puede tener como coordenadas el cursor, en lugar de verificar que sea menor o igual o mayor o igual, según sea el caso, esto provoca que en ocasiones pueda verse que se pierde el cursor y tarde en aparecer por que se sale del límite. pero esto se realizó así para fines didácticos y corregir eso ya les toca a ustedes. Saludos.


Canción de Martinillo

Ejemplo de una melodía reproduciendo por el altavoz de la PC.

El manejo del sonido tiene su base en el clip 8253 y/o 8454. ver apuntes UANL para consultar más sobre la teoría.
El problema principal radica en el manejo de control del tiempo, cada autor que he encontrado, realiza una forma para detener el tiempo suficiente para que la nota toque correctamente. algunos realizan una rutina de retardo que solo consume tiempo con el fin de acercarse a los microsegundos que debe tocarse una nota, de igual manera con las pausas. Entre nota y nota debe haber una pausa. Pero la velocidad de cada máquina hace que el problema de tocar alguna nota sea más complicado el manejo de los tiempos que él hace que toque la nota correcta. Ya que el tocar alguna nota musical se traduce a simples matemáticas.
Así pues, utilizo un ejemplo de la referencia citada y lo modifique para hacer que toque la nota en la frecuencia correcta.
Con el DOSBox podemos reducir la velocidad de ejecución del programa, porque aun el método usado para detener el tiempo. no funciona. Así que vamos a utilizar este pequeño truco. Al tocar una nota la divido en entre 1193180 y el resultado es la frecuencia de la nota, al tocar una nota imprimo en pantalla cual nota es. Aquí se puede utilizar el colocar o dibujar en pantalla el efecto que queremos que se produzca al tocarse la nota, según el instrumento. Cada instrumento tiene una frecuencia para su nota. Yo en el ejemplo pondré para piano.
Entre una estrofa y otra, pongo una pausa e imprimo un guion '-' para separar.
Así pues, el resultado se ve como en la imagen final.

.model tiny
org 100h

.code
   call nSol   ;F
   Call nLa    ;G
   Call nSi    ;A
   call nSol   ;F
   
   call pausa
   
   Call nSol   ;F           
   Call nLa    ;G
   Call nSi    ;A
   Call nSol   ;F 
   
   call pausa
          
          
   Call nSi     ;A
   Call nDo6    ;b6, 
   Call nRe6    ;C6
   
   call pausa
          
          
   Call nSi   
   Call nDo6
   Call nRe6  
              
   call pausa
          
          
   Call nRe6    ;C6
   Call nMi6    ;D
   Call nRe6    ;C
   Call nDo6    ;B6
   Call nSi
   Call nSol
      

   call pausa
              
   Call nRe6 
   Call nMi6  
   Call nRe6
   Call nDo6
   Call nSi
   Call nSol
    
   call pausa
              
   Call nLa 
   Call nRe   
   Call nSol  
   
   call pausa
   
   Call nLa
   Call nRe
   Call nSol
   
   ret   

   pausa proc         
      MOV AH,9
      MOV DX,offset tPausa
      int 21h 
    
     call demora
     ret
   endp 
   
   demora proc             
     dem: loop dem
     ret
   endp 
   

   
   nDo proc
      MOV AH,9
      MOV DX,offset tDo
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,4561        ; 1.193.180 / 261 Hz (nota Do) = 4561
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp

   nDoS proc

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,4307         ; 1.193.180 / 277 Hz (nota Do#) = 4307
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp 
   
   nDo6 proc
      MOV AH,9
      MOV DX,offset tDo6
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,1140        ; 1.193.180 / 1046 Hz (nota Do6) = 1140
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp
   
   nRe proc
      MOV AH,9
      MOV DX,offset tRe
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,4072        ; 1.193.180 / 293 Hz (nota Re) = 4072
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp
   
   nReS proc

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,3836        ; 1.193.180 / 311 Hz (nota Re#) = 3836
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp 
   
   nRe5 proc
      MOV AH,9
      MOV DX,offset tRe5
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,2032         ; 1.193.180 / 587 Hz (nota Re5) = 2032
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp
   
   nRe6 proc           
      MOV AH,9
      MOV DX,offset tRe6
      int 21h 
    

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,1016        ; 1.193.180 / 1174 Hz (nota Re#) = 1016
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp
   
   nMi proc

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,3626         ; 1.193.180 / 329 Hz (nota Mi) = 3626
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp

   nMi6 proc           
      MOV AH,9
      MOV DX,offset tMi
      int 21h 


      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,905         ; 1.193.180 / 1318 Hz (nota Mi6) = 905
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp
   
   nFa proc
      MOV AH,9
      MOV DX,offset tFa
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,3626         ; 1.193.180 / 349 Hz (nota Fa) = 3418
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado
      ret
   endp

   nSol proc
      MOV AH,9
      MOV DX,offset tSol
      int 21h 

      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,3043        ; 1.193.180 / 392 Hz (nota Sol) = 30431
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL    
    
     ret
   endp
   
   nLa proc
      MOV AH,9
      MOV DX,offset tLa
      int 21h 

     MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

     OUT     43h,AL          ; programar contador 2
     MOV     AX,2711        ; 1.193.180 / 440 Hz (nota LA) = 2711
     JMP     SHORT $+2
     OUT     42h,AL
     MOV     AL,AH
     JMP     SHORT $+2
     OUT     42h,AL          ; frecuencia programada
     JMP     SHORT $+2
     IN      AL,61h
     OR      AL,00000011b
     JMP     SHORT $+2
     OUT     61h,AL          ; altavoz sonando
     MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
     IN      AL,61h
     AND     AL,11111100b
     JMP     SHORT $+2
     OUT     61h,AL    

      ret
   endp 

   nSi proc
      MOV AH,9
      MOV DX,offset tSi
      int 21h 
      
      MOV     AL,10110110b    ; contador 2, modo 3, operaci?n 11b, datos binarios

      OUT     43h,AL          ; programar contador 2
      MOV     AX,2420        ; 1.193.180 / 493 Hz (nota SI) = 2420
      JMP     SHORT $+2
      OUT     42h,AL
      MOV     AL,AH
      JMP     SHORT $+2
      OUT     42h,AL          ; frecuencia programada
      JMP     SHORT $+2
      IN      AL,61h
      OR      AL,00000011b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz sonando
      MOV     CX,0
     ;demora:     LOOP    demora          ; esperar un cierto tiempo por el peor m?todo
     call demora
      IN      AL,61h
      AND     AL,11111100b
      JMP     SHORT $+2
      OUT     61h,AL          ; altavoz callado 
      
      ret
   endp  
   
.data
   tDo   db " Do $"    
   tRe   db " Re $"
   tMi   db " Mi $"
   tFa   db " Fa $"
   tSol  db " Sol $"
   tLa   db " La $"
   tSi   db " Si $"
   
   tDo6  db " Do6 $"    
   tRe6  db " Re6 $"
   tMi6  db " Mi6 $"
   
   tRe5  db " Re5 $"
   
   tPausa db "-$"
end
                 
Así quedo...


Gráfica

Ejemplo de cómo poner una imagen gráfica en ensamblador.

Colocando pixeles por la pantalla es lo que se hace en ensamblador con el servicio 0ch de la interrupción 10h
Para dibujar una línea, podemos utilizar la teoría de la línea recta y conociendo el desplazamiento en X o Y, podemos decidir cómo dibujar la línea y que eje utilizar para conociendo -por ejemplo, el eje X, calcular en qué posición debe ir en Y.
De esta manera dibujando pixel x pixel podemos dibujar la línea. Quizá un poco complicado, pero así lo debe hacer cualquier lenguaje de programación de alto nivel, desde luego tomando en cuenta más factores.

Para hacer un dibujo, es otro problema que resulta menos complicado y quizá más interesante.

Vamos a dibujar un insecto, que será el principio de todos los juegos, no quiero decir que todos los hacen así, sino que este es mi método para dibujar una imagen. Tanto que em BMP y otros formatos hacen casi lo mismo. este insecto se podrá dibujar, después volver a dibujar la imagen 2, y luego borrar. Repetir esto según se quiera.

Seleccionamos una imagen a copiar -si tienes mucha imaginación o te gusta diseñar, puedes empezar directamente a dibujar- y utilizando una hoja cuadriculada, iremos pintando con color, los cuadros conforme a la imagen.

Para hacerlo más sencillo utilizare una matriz de 16 x (lo que me dé la imagen)

Como no soy muy bueno dibujando -modestia parte pero si dibujo bien- o quizá un tanto flojo -o práctico, depende el punto de vista 🌝-, utilizaré una herramienta como Excel u hoja de cálculo.

Ahí, pinto cada color de celda y hago 2 imágenes, la 2a con ligeros cambios para simular movimiento.


Puede ver a la izquierda una imagen y a la derecha otra con pequeños cambios en las patas para simular el movimiento.

Ahora lo que hacemos es colocar el color que corresponde a la cada pixel -celda o cuadro del cuaderno, según tu herramienta de trabajo elegida-

Ahora debes construir el código, que tendrá el arreglo, por ejemplo DB 0,6,6,0,0,15,0,0,15,0,0,6,6,0 Que corresponde a la 2a línea, y así sucesivamente hasta terminar.

Yo me ayude de Excel y en la celda S, construí una fórmula que me construyera el código en ensamblador, para no hacerlo en forma manual y evitar cometer errores..

Ahora solo copio y pego dicho código en ensamblador.

Lo siguiente es solo construir una rutina que ubique el pixel y tome el color que se va a pintar, pixel x pixel.

Tome en cuenta que aquí será un arreglo con las 16x24 renglones = 384, cada 16 debemos pasar al siguiente renglón en la pantalla. hasta llegar a los 23 renglones o los 384 valores. El índice del arreglo utilice el registro Si y a partir de la dirección del arreglo + desplazamiento, obtengo el color.

;     Univesidad Autonoma de Guerrero
;         Facultad de Ingenieria
;  Programacion del Microprocesador 8086
;  Escrito  por: Ruben Rodriguez Camargo
;  -------------------------------------

data segment
    Tit1 db "Universidad Aut",162,"noma de Guerrero",10,13,"$"
    Tit2 db "Programa para dibujar un insecto en la pantalla",10,13,"$"
    pkey db "presione una tecla...$" 
    autor  db "Realizado por Rub",163,"n Rodr",161,"guez Camargo.","$"
    cuca DB 0,6,0,0,0,0,0,0,0,0,0,0,0,0,6,0,             ;Color 0=Negro, 6=Cafe
        DB 0,0,6,6,0,0,15,0,0,15,0,0,6,6,0,0,           ;15=Blanco
        DB 0,0,0,0,6,6,6,6,6,6,6,6,0,0,0,0,
        DB 0,0,0,0,0,0,8,6,6,8,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,8,6,6,8,0,0,0,0,0,0,
        DB 0,15,15,0,0,0,8,6,6,8,0,0,0,15,0,0,
        DB 15,0,0,15,0,0,8,6,6,8,0,0,15,0,15,0,         ;8=gris,
        DB 0,0,0,0,15,8,0,6,6,0,8,15,0,0,0,0,
        DB 0,15,15,0,8,6,12,6,6,12,6,8,0,0,15,0,
        DB 15,0,0,8,6,6,12,6,6,12,6,6,8,15,0,15,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,15,15,0,         ;12=rojo
        DB 0,15,15,15,8,6,12,6,6,12,6,8,15,0,0,15,
        DB 15,0,0,0,0,8,6,6,6,6,8,0,,0,0,0,
        DB 0,0,0,15,15,15,8,6,8,8,15,15,15,,0,0,
        DB 0,0,15,0,0,0,8,6,8,0,0,0,0,15,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
  Cuca2 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
        DB 0,0,6,6,0,0,10,0,0,10,0,0,6,6,0,0,
        DB 0,6,0,0,6,6,6,6,6,6,6,6,0,0,6,0,
        DB 0,0,0,0,0,0,8,6,6,8,0,0,0,0,0,0,
        DB 0,15,0,0,0,0,8,6,6,8,0,0,0,0,15,0,
        DB 0,0,15,0,0,0,8,6,6,8,0,0,0,15,0,0,
        DB 15,0,0,15,0,0,8,6,6,8,0,0,15,0,0,0,
        DB 0,15,0,0,15,8,0,6,6,0,8,15,0,0,0,15,
        DB 0,0,15,0,8,6,12,6,6,12,6,8,0,0,15,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,15,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 0,0,0,8,6,6,12,6,6,12,6,6,8,0,0,0,
        DB 15,0,0,8,6,6,12,6,6,12,6,6,8,0,15,15,
        DB 0,15,0,8,6,6,12,6,6,12,6,6,8,15,0,0,
        DB 0,0,15,15,8,6,12,6,6,12,6,8,15,0,0,0,
        DB 0,0,0,0,0,8,6,6,6,6,8,0,0,0,0,0,
        DB 0,0,15,15,15,15,8,6,8,8,15,15,15,15,0,0,
        DB 0,0,0,0,0,0,8,6,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,
        DB 0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,0

    r   dw 10           ;Renglon=10 
    C   dw 10
    X   dw 10           ;En Columna 10, 0-320
    y   dw 10           ;   renglon 10, 0-200  
    Color db 7          ;Fondo negro letra blanca.
ends

stack segment
    dw   128  dup(0)

ends

code segment
start:          

Titulo Macro
    ; Iniciamos moviendo el cursor
    mov ah,2
    mov dh,0
    mov dl,20           ;Columna 20,0 
    int 10h
    
    lea dx, tit1
    mov ah, 9
    int 21h             ; output string at ds:dx  
    
    ; moviendo el cursor
    mov ah,2
    mov dh,1
    mov dl,15           ;Columna 15,1 
    int 10h 
  
    lea dx, tit2
    mov ah, 9
    int 21h             ; Imprime Escuela
      
Titulo endm

    ; Asigna segmentos a los registros:
    mov ax, data
    mov ds, ax
    mov es, ax

    
    Call Cls            ; Limpiamos la pantalla.
                  
    Titulo              ; Imprimie los titulos
                
    lea dx, pkey
    mov ah, 9
    int 21h             ; Imprimir Presiona una tecla...
    
    ; wait for any key....    
    mov ah, 1
    int 21h             ; Espera la tecla
    
        
    ;modo grafico
    mov ah,0h
    mov al,13h
    int 10h             ;320x200

    ;Colocamos las coordenadas a dibujar
    mov x,10
    mov y,10
    lea bx, cuca
    Call Dib
    
    Mov x,30
    mov y,10
    lea bx, cuca2
    call Dib
    

fin:           
    
    lea dx, pkey
    mov ah, 9
    int 21h             ; Imprime Presiona una tecla

    mov ah, 1           ; Espera una tecla
    int 21h


    ;restauramos modo grafico
    mov ah,0h
    mov al,3h
    int 10h

    Titulo

    ; moviendo el cursor
    mov ah,2
    mov dh,2
    mov dl,20           ; Columna 15,1    
    int 10h 
                  
    lea dx, autor
    mov ah, 9
    int 21h        

    ;Mostramos el cursor porque lo ocultamos
    mov ah,1
    mov ch,6
    mov cl,7
    int 10h

    
    mov ax, 4c00h       ; Salir a SO
    int 21h 
    
; Procedimiento para dibujar la cucaracha
; Requiere colocar en X y Y la posicion a dibujar
; en bx, la direccion de la imagen a dibujar..
  
Dib Proc   
    push si
    push ax
    push bx
    push cx
    push dx
    
    mov si,0
    mov c,0  
    mov ax,y
    mov r,ax
  
@inicio:
    
    ;dibujamos la cucaracha
    ;lea bx, cuca    
    xor cx,cx
    mov ah,0ch
    mov al,[bx + si] 
    mov cx,c 
    add cx,x
    mov dx,r
    int 10h   
    inc si     
    ;llegamos al final
    cmp si, 368             ;Es el tamaño del arreglo, 16 col x 23 Reng=368
    jz  @fin
    ;llegamos a la columna? Sig Renglon
    mov ax,si
    mov dl,16               ;Numero de columnas 16
    idiv dl
    cmp ah,0
    jnz @otr
    inc r
    mov c,0
@otr:       
    inc c 
    jmp @inicio      
@fin:
    
    pop dx
    pop cx
    pop bx
    pop ax
    pop si
    ret
Dib endp    

;Requiere poner en color
;el color del fondo a limpiar.
cls Proc near  
    push dx
    push cx
    push bx
    push ax
    mov ah,06
    mov al, 25    
    mov bh,color
    mov ch,0
    mov cl,0
    mov dh,24
    mov dl,79
    int 10h
        
    pop ax
    pop bx
    pop cx
    pop dx
    ret
cls endp


ends

end start ; set entry point and stop the assembler.

                 
Así quedo...

Una vez obtenido esto, se me ocurrió combinar el programa screensaver y en lugar de colocar un carácter, modificarlo para que en modo gráfico pintara la primera, imagen, luego la segunda, luego limpiara, pasara a la siguiente coordenada y repitiera esto hasta que presionemos una tecla.

El resultado se muestra a continuación. No pongo el código pero con gusto se lo enviare a los que me lo soliciten.

Así queda.


Comentarios

Escribe algún comentario.


Para informes y/o demostraciones ponemos a su disposición:

Tel. 74 7131 1223
Email: ruben_@yahoo.com