Lab 06

Anuncio
Sexta Experiencia. Laboratorio de Estructuras de Computadores
02/2001
Simulador 8031.
Para aprender a emplear el simulador, se propone compilar una serie de programas
en lenguaje simbólico de máquina. En ellos se puede observar las formas empleadas para
definir variables, y además algunos de los mnemónicos de las instrucciones para el
procesador 8051.
Uno de los objetivos de la experiencia es analizar, empleando el simulador, algunos
segmentos de código assembler 8031, que tienen relación con el direccionamiento de
variables. También se analiza la programación de condiciones y lazos de repetición.
Otro objetivo es describir la misma situación que el programa assembler, pero
empleando el lenguaje C.
Luego se da el texto assembler de un programa que manipula variables y que
implementa estructuras alternativas y de repetición.
Para poder visualizar los cambios en cada una de las variables, debe ejecutarse el
simulador. Luego se debe cargar el texto del programa, el cual debe estar escrito en un
archivo de texto con extensión *.a51.
Una vez cargado, en el menú debug, marcando la opción Start se puede empezar la
simulación. Las casillas de verificación deben estar seteadas indicando que se va a efectuar
una simulación en un procesador de tipo 8051 (virtual machine).
Luego de realizar los pasos anteriormente expuestos, se observa que aparecen en
pantalla dos ventanas adicionales; una nos muestra el código del programa, mientras la otra
que se titula Main Registers despliega el estado actual del acumulador, PC, DPTR, entre
otros.
Para ejecutar el programa se debe presionar el botón GO de la barra de
herramientas, pudiendo observarse el progreso de éste al activar la opción animate de la
misma forma. También es posible variar la velocidad de ejecución del programa,
deslizando el control ubicado en la barra de herramientas hacia la derecha para hacerlo más
rápido o a la izquierda para lograr el efecto contrario. También existe la posibilidad de
ejecutar paso a paso y colocar breakpoints.
Si se quiere observar cualquier variable definida, basta con seleccionar en el menú
View la opción Data Dump la que es capaz de mostrar completamente una zona de datos, la
cual debe ser elegida desde el menú que aparece a continuación:
XRAM = RAM externa (Se observan las direcciones desde 0x0000 hasta 0xFFFF)
DATA = RAM interna desde la dirección 0x00 hasta 0x7F .
SFR = RAM interna desde la dirección 0x80 hasta 0xFF.
Bit
= RAM interna en la zona de bits, entre la dirección 0x20 y 0x2F, aunque se lista
desde 0x00 y 0xff , pero en bytes, donde 0x00 corresponde al primer bit del byte 0x20, y
así sucesivamente.
El procedimiento para agregar un watch es el siguiente:
En el menú view se selecciona la opción symbols, desplegándose una lista con todas
las variables que se están usando, tanto las definidas en Ram interna como externa del
programa (esta lista puede ser ordenada tanto por tamaño como por nombre).
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
1
Con las opciones que se muestran en la misma ventana es posible elegir una zona, siendo
las alternativas similares a las ofrecidas por el menú data dump.
Con el botón izquierdo del mouse se deben marcar las variables que se quieren observar,
para luego presionar la opción add watch de la misma ventana.
Para efectuar la traza de una variable, se marca la casilla de verificación trace en la ventana
watch en la variable que deseamos seguir. Luego en el menú options se escoge trace,
desplegándose una casilla de diálogo donde puede escogerse:
- On changes: Para observar sólo los cambios.
- Display relative time : Para observar el tiempo.
- Reset trace before to run : Para resetear la traza antes de empezar a ejecutar.
Entonces, en el menú view marcamos trace; apareciendo una ventana que nos
muestra el tiempo, el valor de PC, la instrucción realizada y el progreso de la o las variables
configuradas anteriormente.
En caso de necesitar ejecutar el programa instrucción por instrucción (paso a paso),
basta con presionar desde el teclado F7 ; o en su defecto , usar el botón step in de la barra
de herramientas.
Si se requiere detener la ejecución del programa en una instrucción determinada,
agregamos un breakpoint; esto es, posicionarse en la línea de código correspondiente para
presionar desde el teclado F5, o en su defecto con el botón derecho del mouse sobre la
misma línea de programa correspondiente las opciones toogle flag... toogle breakpoint.
Notar que de la misma forma puede detenerse el registro de la traza si
seleccionamos toogle flag ... toogle trace (o F4).
Efectuar programa para:
a) Definir dos contantes, c1 y c2, en EEPROM y formar la suma lógica(or) de c1 y c2 en el
acumulador.
Definir dos variables, v1 y v2, en RAM externa, en direcciones 0100h y 0101h. Efectuar
programa, que escriba 5 y 10 en v1 y v2; y luego formar la suma de v1 y v2 en el
acumulador. Usar símbolos para las variables.
Solución:
programa
ramexterna
SEGMENT CODE
SEGMENT XDATA
RSEG programa
org
0
jmp
start
;define segmento programa
; segmento para XDATA RAM
; se cambia a segmento de código.
; define la dirección de la primera instrucción.
; org es una orden al compilador, no al procesador.
; se va a la primera instrucción.
;DEFINICIONES DE DATOS EN RAM EXTERNA
RSEG ramexterna
; se cambia al segmento de dato externo
org
100H
; define la primera dirección de memoria que se
; empleará para almacenar los datos (RAM externa).
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
2
V1:
V2:
DS
DS
1
1
; definición e inicialización de variables.
RSEG programa
org
40h
; se vuelve a segmento texto
.
; define la primera dirección que se empleará para
; almacenar datos en ROM.
;Las constantes en rom pueden ir antes del código, como en Pascal
c1:
db
01h ;define constante
;la constante c2 se define al final.
start:
************** a = c1 or c2
mov dptr, #c1
; dptr = &c1
clr
a
; acumulador = 0 (offset cero).
movc a, @a+dptr ; a = *(dptr+a) Se emplea movc
mov r0, a
; r0 = c1
mov dptr, #c2
clr
a
movc a,@a+dptr
; a = c2
.
orl
a,r0
; a = c2 | c1
nop
; Indica no operación. (no hace nada).
;
;
******************V1 =5; V2 = 10; a = V1+ V2. Variables en RAM
mov dptr, #V1
; dptr = &V1
mov a, #5
; a = 5 Inmediata
movx @dptr, a
; *dptr = a Se emplea movx. V1 = 5
inc
dptr
; dptr++ Apunta a V2, ya que es adyacente a V1.
mov a, #10
; a = 10.
movx @dptr, a
; V2 = 10.
en este momento dptr apunta a V2. Y a tiene el valor de V2.
mov dptr, #V2
; dptr toma la dirección de v2.
movx a, @dptr
; Ahora trae v2 desde la RAM EXTERNA al acum.
mov r0, a
; Salva V2 en registro temporal
mov dptr, #V1
; dptr vuelve a tomar la dirección de v1.
movx a, @dptr
; a = V1
add
a, r0
; a = V1 + V2
b) Definir dos bits, b1 y b2, en RAM interna. Efectuar programa, que intercambie los
valores almacenados en b1 y b2.
Solución:
;**********************************
;sea el byte 20h que está en la zona de bits (20h a 2fh). Sean: b1 = 20h.0 y b2 = 20h.1
;se efectúa swap(20h.0 con 20h.1) se asume 21h.0 como temporal.
,En esta parte se van a definir 2 bits en la RAM interna, uno a continuación del otro, en el
;mismo byte, más un bit (en la misma memoria interna, pero en el byte siguiente ) que
;servirá de bit temporal. Ahora se ocupará el carry en vez del acumulador por estar dentro
;de la zona de 20-2f byte en la memoria.
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
3
clr
setb
mov
20h.0
20h.1
c, 20h.0
mov
mov
mov
mov
mov
21h.0, c
c, 20h.1
20h.0, c
c, 21h.0
20h.1, c
; b0 = 0 .
; b1 = 1
; El movimiento de bit al carry. c = b0
; El carry pertenece a PSW. Program status word.
; temp = c
; c = b1
; b0 = b1
; c = temp
; b1 = c
; Otra forma.
La diferencia con el anterior es que asigna símbolos(nombres) a los bits .
b1
equ
20h.0
; Con esta instrucción le asigna nombre al bit
; 20h.0. En este caso b1 representará a 20h.0.
b2
tmp
equ
20h.1
equ
21h.0
clr
b1
setb b2
; Ahora se hace lo mismo que la 1ª forma, pero con los nuevos nombres. Esta forma es más
; simple de manejar, pues se asocian las variables por sus nombres.
mov c, b1
mov tmp, c
mov c, b2
mov b1, c
mov c, tmp
mov b2, c
c) Definir dos variables, v1 y v2, en RAM interna. Efectuar programa, que escriba 5 y 10
en v1 y v2; y luego formar la resta de v1 y v2 en el acumulador. Usar assembler
simbólico.
c1) En la zona 00h a 1Fh Zona de registros
c2) En la zona 20h a 2Fh Zona de bits
c3) En la zona 30h a 7Fh Zona ram interna (direccioanamiento directo)
Solución:
;la zona de 00h a 1fh son los registros (32 registros divididos en cuatro grupos de ocho
registros cada uno. Se puede emplear un grupo a la vez).
;sea v1 en r0, v2 en r1
mov r0, #5
; coloca valor inmediato 5 en r0.
mov r1, #10
; r1= 10.
mov a, r0
; a = r0
subb a, r1
; a = r0 – r1
;la zona de bits de 20h a 27h se direcciona en forma directa
v12 equ
20h ; asigna a v12 el byte 20h de la zona de bits. (se utiliza un byte
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
4
; completo, a pesar de que esta zona permite manipular bit por bit).
21h
mov v12, #5
; asigna valor 5 a v12.
mov v22, #10
;asigna valor 10 a v22.
mov a, v12
clr c
; esta modificación la implementamos para obtener el resultado correcto de la operación de
resta. El resultado es un número negativo, por ello el bit carry del PSW queda con valor
uno desde la anterior operación que haya entregado un resultado semejante y siempre que
no sea reseteado.
subb a,v22 ; hace la resta v12 – v22. Y deja el resultado en ACC.
;la zona de borrador scratch pad, también puede direccionarse en forma directa
v13 equ
30h ; Se definen variables en la zona de direccionamiento directo; indirecto. En este caso, se accede a las variables en forma directa.
v23 equ
31h
mov v13, #5
mov v23, #10
mov a, v13
clr c
; clear c
subb a,v23
v22
equ
****************************
d) Programar: while ( R2 >= R4 )
{ if (R5<R6) R4++; else R2= R1-1;
R2--;
}
;************************Programación del while.
mov r2, #2 ;se asigna valores, para probar funcionamiento.
mov r4, #3
mov r1, #3
mov r5, #5
mov r6, #6
clr
c
while:
mov a, r2 ; puesto que en r2 hay un valor, lo traspasa al acumulador,
subb a, r4
; a = r2 – r4 > 0 si r2 >=r4 y el bit carry de la palabra de estado es cero. Si el resultado es
menor que cero, el bit mencionado es uno.
jc
fuera
; si r2>= r4 no hay c. Si r2 es mayor que r4, carry es cero y na hay bifurcación.
; Jc jump si carry es uno. Jnc jump si carry es cero.
;bloque de repetición
mov a, r5
subb a, r6 ; a = r5 – r6
jnc
els
; r5>=r6 no hay c, entonces r5<r6 carry
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
5
inc
jmp
mov
dec
mov
dec
jmp
els:
endfi:
r4
fi
a, r1
a
r2, a
r2
while
;incrementa r4 en uno.
; termina el if.
; a--
; repete el lazo.
fuera:
Hasta aquí, la forma de programación simbólica de la maquina 8051 es similar a como se
programaba para MIPS, en cuanto a las etiquetas, saltos, difiriendo en aspectos como las
operaciones de suma, resta y los direccionamientos y forma de acceder a los datos.
;**********************************
forever:
jmp forever
; es un salto sobre sí mismo. Se repite indefinidamente
;deja en estado de halt (pero en ejecución) al procesador
;no existe instrucción que detenga al 8051
;las constantes pueden ir después del código, como en C.
c2:
db
10h
;*****************************************************
end
Mostrar en el simulador las variables, y que se efectúan las operaciones programadas.
Si la casilla Options- L51 – Linker – Intel hex está marcada se genera código Intel
hexadecimal que puede cargarse en la EPROM que contiene el texto.
e) Compilar el siguiente programa y efectuar su simulación, viendo la puerta uno.
Observando como cambian de estado los bits de la puerta.
#include <reg51.h>
void main (void)
{ for(; ; ) { P1= 0x0; P1 = 0xFF;}
}
Lo mismo puede lograrse en assembler con
PROG SEGMENT CODE
RSEG PROG
start: mov P1,#00
mov P1,#255
jmp start
END
Laboratorio de Estructuras de Computadores.
Lab06
05-09-2001
6
Descargar