Ensamblador
2
- Escribir un programa que escriba el mismo carácter en las 2000 posiciones de la pantalla:
pantalla EQU 0B800h ;Direccion física de comienzo de la pantalla
;------------------------------------------------------------------------------
;Definición del segmento de codigo
;------------------------------------------------------------------------------
CODE SEGMENT
assume cs:code
START PROC
mov ax,pantalla ;Cargar la dirección de la coordenada 0,0 de la
mov ds,ax ;pantalla
xor bx,bx ;Ponemos bx a 0
pinta_caracter:
mov ds:[bx],byte ptr "V" ;Escribir el carácter en su coordenada
inc bx ;En lugar de sumar 2, se incrementa 2 veces porque
;consume menos ciclos de reloj del procesador
inc bx ;Cada posicion de la pantalla son 2 bytes,
cmp bx,2000*2 ;por eso bx va a llegar hasta 4000
jl pinta_caracter ;Si bx<4000 volvemos a pintar otro carácter
mov ax,4C00h ;
int 21h ;Terminar el programa
START ENDP
CODE ENDS
END START
- Hacer un programa que coja el carácter que se encuentre en la coordenada 0,0
de la pantalla en ese momento y lo copie por toda la pantalla. En los últimos
4 caracteres mostrar la palabra ETSI:
pantalla EQU 0B800h
;------------------------------------------------------------------------------
;Definición del segmento de codigo
;------------------------------------------------------------------------------
CODE SEGMENT
assume cs:code
START PROC
mov ax,pantalla ;Cargar la dirección de la coordenada 0,0 de la
mov ds,ax ;pantalla
xor bx,bx
mov dx,ds:[bx] ;Obtener el carácter de la coordenada 0,0
pinta_caracter:
inc bx
inc bx
mov ds:[bx],dx ;Copiar el carácter obtenido por toda la pantalla
cmp bx,1995*2 ;Dejamos los ultimos 4 caracteres sin rellenar
jl pinta_caracter
mov ds:[1996*2],byte ptr "E" ;En los ultimos 4 caracteres escribimos
mov ds:[1997*2],byte ptr "T" ;nuestro mensaje
mov ds:[1998*2],byte ptr "S" ;
mov ds:[1999*2],byte ptr "I" ;
mov ax,4C00h ;
int 21h ;Terminar el programa
START ENDP
CODE ENDS
END START
- Nos vemos en la necesidad ya de empezar a manejar el Turbo Debugger. No todos los programas que
hagamos tienen por qué mostrar algo por la pantalla. Veremos ahora un programa que realiza la
suma de los números 1+2+3+4+5+6+7+8+9+10=55=37h. La salida de esta suma se irá guardando
en el acumulador (AX). Con el TD podremos ir viendo como el registro AX va aumentando hasta llegar a 37
en hexadecimal, que va a ser el equivalente a 55 en decimal. Todo lo que veremos en el TD va a estar en
hexadecimal. Al principio puede parecernos un poco raro y no saber muy bien a que equivale, pero poco
a poco iremos aprendiendo a pensar en hexadecimal y binario :D.
Antes de nada les voy a mostrar los archivos .bat que he venido utilizando durante mi aprendizaje del
ensamblador:
- Para debuggear un programa puede utilizarse únicamente el programa deb.bat:
:-----------------------------------------------------------------------
:
: Fichero: deb.bat
:
: Descripcion:
: Ensamblar modulo fuente principal de un programa, crear modulo
: objeto y debuggearlo.
:
:-----------------------------------------------------------------------
:
echo off
if z%1 == z goto error
goto check
:error
echo *** error: falta nombre del modulo fuente ***
goto fin
:check
if exist %1.asm goto ensam
echo *** error: fichero %1.asm no existe ***
goto fin
:ensam
tasm /zi %1;
if exist %1.obj goto mensa
echo *** error en programa fuente ***
goto fin
:mensa
tlink /v %1
echo ... creado fichero %1.obj
td %1
:fin
Este archivo de procesamiento por lotes lo que hace es ensamblar el archivo, linkarlo
y por ultimo lanzar el Turbo Debugger para nuestro archivo. Claro está que todo
esto puede hacerse paso por paso, pero bueno, cada uno verá lo que prefiere.
Mi fichero t.bat no se diferencia en casi nada de deb.bat, la única diferencia es
que en lugar de td %1 debemos poner un %1 para que lo ejecute. De esta
manera t.bat lo que hace es ensamblar, linkar y ejecutar el programa.
Con estos programas ya estamos preparados para hacer frente al siguiente ejemplo, para
el cual veremos su resultado en el TD.
;------------------------------------------------------------------------------
;Definición del segmento de codigo
;------------------------------------------------------------------------------
CODE SEGMENT
assume CS:code
START:
xor ax,ax ;
mov cx,1 ;Inicializar
suma:
add ax,cx ;
inc cx ;
cmp cx,11 ;
jne suma ;Sumar 1+...+10=37h
mov ax,4C00h ;
int 21h ;Terminar el programa
CODE ENDS
END START
El siguiente programa es algo más sofisticado y potente. La teoría
la explicaremos después de ver el ejemplo.
- Realizar un programa que limpie la pantalla dejando el fondo azul y los caracteres rojos:
pantalla EQU 0B800h
;------------------------------------------------------------------------------
;Definición del segmento de pila
;------------------------------------------------------------------------------
PILA SEGMENT STACK "STACK"
db 40h dup(0)
PILA ENDS
;------------------------------------------------------------------------------
;Definición del segmento extra
;------------------------------------------------------------------------------
EXTRA SEGMENT
result dw 0,0
EXTRA ENDS
;------------------------------------------------------------------------------
;Definición del segmento de codigo
;------------------------------------------------------------------------------
CODE SEGMENT
assume cs:code,es:extra,ss:pila
START PROC
cld ;DF=0 (incrementar DI)
mov ax,pantalla
mov es,ax
xor di,di
mov ax,1C00h ;Fondo azul, caracteres rojos con intensidad
;Equivalente a: mov ax,0001110000000000b
mov cx,2000
rep stosw ;Repetirlo las 2000 veces
mov ax,4C00h ;
int 21h ;Terminar el programa
START ENDP
CODE ENDS
END START
Si quisiesemos poner los atributos de otra forma sólo hay que cambiar una línea.
Podríamos ponerla de la siguiente manera, por ejemplo:
mov ax,1100001000000000b ó mov ax,0C200h
si quisiesemos poner el fondo rojo con letras verdes.
Teoría para entender el ejercicio:
STOSW:
Se transfiere el registro AX a la palabra ES:[DI]. DI se actualiza en dos unidades.
Si la bandera de dirección es cero (DF=0), DI se incrementa, si DF=1, se decrementa.
Esto lo logramos con las instrucciones CLD o STD.
En CX hemos especificado el número de elementos de la cadena. En este caso las 2000
posiciones, son las 80x25 posiciones de la pantalla.
Para indicar en la memoria de pantalla como queremos el fondo y los caracteres podemos
hacerlo en sus 8 bits. Para indicar el carácter tenemos otros 8 bits. Cada número
o letra hexadecimal equivale a un nibble (4 bits):
código atributo (1 byte). Los bits son los siguientes:
7 - Utilizado para indicar si el carácter parpadea o no.
6 - Componente rojo del fondo
5 - Componente verde del fondo
4 - Componente azul del fondo
3 - Intensidad en los caracteres
2 - Componente rojo del carácter
1 - Componente verde del carácter
0 - Componente azul del carácter
Como vemos en nuestro ejemplo (0001 1100 0000 0000), hemos activado el componente azul del fondo,
la intensidad y el componente rojo de los caracteres.
código carácter (1 byte): Podemos elegir de la tabla ASCII aquel carácter que prefiramos.
Como carácter elegimos el 00h, que en la tabla ASCII va a equivaler a dejar el fondo sin
ningún carácter. Si quiesiesemos que apareciese el carácter 'V' en el fondo pues
cogeríamos el 56h.
Cuando ejecutemos el programa, si queremos volver a tener nuestra pantalla como
antes, basta con un un simple:
C:\>cls
Volveremos a tener la pantalla con letras blancas sobre fondo negro.
|
|