Ya podemos, decodificar el programa a ensamblador, y podemos ver el contenido de la memoria en formato de datos. ¿Pero que pasa con los registros de microcontrolador?
Eso no es accesible a través del bus, ya que no está dentro de la memoria. Por lo tanto parece imposible que podamos mostrarlo en la pantalla, sin que exista un programa uploader dentro del programa de microporcesador o de la tarjeta prototipo. Pero eso no es verdad.
Dado que tengo todo el control sobre la ejecución del microcontrolador, puedo parlo cuando quiera, accedera a la memoria y cambiarla cuando desee, e incluso ejecutar una instrucción en micropasos. Por ello, ¿porqué no puedo intervenir en la ejecuión de un programa de forma intempestiva? Pues eso... si puedo.
Por esto, si soy capaz de leer los registros, sin haber incorporado ninguna rutina previa en el prototipo. Me basta conque la memoria de programa sea ram, para que pueda modificarla en todo momento.
Si la memoria es ram, puedo volcar el programa y luego ejecutarle. Pero como los pulsos de reloj los controlo uno a uno desde el PC, puedo parar el programa en cualquier instrución, y claro puedo entretenermo lo que desee en ese punto.... Hasta puedo escribir y lleer en la memoria mientras tengo el procesador parado.... entonces, porque no substituir el programa.
Pues eso vamos a hacer. Para poder ver los registros, vamos a parar el programa en un punto de ruptura, y en ese punto que se pare querremos ver los registros. Pues entonces, vamos a escribir un pequeño programa dentro de la memoria, que nos guarde los valores de los registros en una zona de memoria.
Una vez copiado este programa lo vamos a ejecutar, y luego tomaremos los valores que nos haya copiado.
Para que sea transparente, este programa lo almacenaremos en la dirección 0 si nos encontramos ejecutando por encima de 255, y en 100h si estamos ejecutando por debajo.
El proceso sera básicamente este:
1 Elegimos el area de volcado de la rutina.
2 Toma la dirección de este area de memoria y se acopla a la instrucción de salto
2 Toma la dirección de este area de memoria y se acopla a la instrucción de salto
3 Salvaguarda en el pc el area de memoria 8051 que será ocupada por la rutina_reg,y el valor de los gegistros 90h bytes
4 Guarda la direccion actual de ejecución (IP) en dir_ini
5 Salvaguarda en PC el contenido de memoria donde irá la instrucción de salto (3 bytes)
6 Se coloca la instruccion de salto nueva en la actual dirección del IP dentro del 8051
7 Ejecutamos este salto
8 Se restaura la instrución original almacenada en el pc en el paso 5
4 Guarda la direccion actual de ejecución (IP) en dir_ini
5 Salvaguarda en PC el contenido de memoria donde irá la instrucción de salto (3 bytes)
6 Se coloca la instruccion de salto nueva en la actual dirección del IP dentro del 8051
7 Ejecutamos este salto
8 Se restaura la instrución original almacenada en el pc en el paso 5
9 Se coloca la rutina de volcado en la memoria del 8051
10 Ejecutaremos la rutina.
11 Recogeremos el valor de los registros. Los últimos 32 bytes de la memoria, del área temporal
12 Restauraremos las areas de memoria de instrucción y de datos usadas en el 8051.
Con todo esto logramos ejecutar un programa sin haber gastado un solo byte para este drive. Es un dirve de quita y pon y por lo tanto transparente.
Aquí queda la rutina.
REGISTRO.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 48iocent.mac
include window.mac
public prn_reg
.model compact,pascal
.data
extrn vez_reg:byte ;variables globales del emulador
extrn Dir_cur:word ;dirección actual del ip. Dirección de ejecución actual
;esta es la secuencia de código máquina del 8051 de la rutina de extracción
Rutina_reg db 90H,00H,70H,0E5H,80H,0F0H,0A3H,0E5H,81H,0F0H,0A3H,0E5H,88H,0F0H,0A3H,0E5H,89H,0F0H,0A3H
DB 0E5H,8AH,0F0H,0A3H,0E5H,8BH,0F0H,0A3H,0E5H,8CH,0F0H,0A3H,0E5H,8DH,0F0H,0A3H
DB 0E5H,90H,0F0H,0A3H,0E5H,98H,0F0H,0A3H,0E5H,99H,0F0H,0A3H,0E5H,0A0H,0F0H,0A3H
DB 0E5H,0A8H,0F0H,0A3H,0E5H,0B0H,0F0H,0A3H,0E5H,0B8H,0F0H,0A3H,0E5H,0D0H,0F0H,0A3H
DB 0E5H,0E0H,0F0H,0A3H,0E5H,0F0H,0F0H,0A3H,0E8H,0F0H,0A3H,0E9H,0F0H,0A3H,0EAH,0F0H
DB 0A3H,0EBH,0F0H,0A3H,0ECH,0F0H,0A3H,0EDH,0F0H,0A3H,0EEH,0F0H,0A3H,0EFH,0F0H
db 2
Dir_ini db 0,0 ;dirección inicial donde comienza el proceso. Usada para restaurar.
Salto db 2,0,0 ; insgtrucción de salto para pasar a la rutina
dir_salto dw 0
dato dw 0,0
Memo_ini db 90H dup (0) ;memoria inicial
Inst_ini db 5 dup (0) ;instrucción inicial
registros db 40 dup (0) ;buffer para los registros
;mensajes para pantalla
Mreg db "Registros",0
MR0 DB "R0=",0
MR1 DB "R1=",0
MR2 DB "R2=",0
MR3 DB "R3=",0
MR4 DB "R4=",0
MR5 DB "R5=",0
MR6 DB "R6=",0
MR7 DB "R7=",0
.code
extrn _trace:near
extrn Guarda:near
extrn Toma:near
prn_reg proc uses bx dx cx si
mov ax,Dir_cur ;valor de IP actual
cmp ax,255 ;Si se está ejecutando por encima del byte 255, se grabará la rutina temporal en byte 0
ja abajo
mov dir_salto,100h ;Si estamos por debajo de 255, lo haremos en la dirección 100h
jmp short tomar
abajo:
mov dir_salto,0
tomar:
mov dx,dir_salto ;tomamos la dirección deseada del salto y se acopla a la instrucción de salto
mov salto+1,dh
mov salto+2,dl
;se salvaguarda el area que será substituida por la rutina_reg
mov bx,offset Memo_ini ;almacena en pc la memoria del sistema
mov cx,90h ;longitud de la rutina_reg
call Toma ;toma la zona de la instruccion de salto
mov dx,Dir_cur ;Se guarda la direccion actual de ejecución en dir_ini
mov Dir_ini,dh ;para regresar a ella posteriormente
mov dir_ini+1,dl
mov bx,offset Inst_ini ;almacenamos el contenido de memoria donde irá la instrucción de salto
mov cx,3
call Toma
mov dx,Dir_cur ;coloca la instruccion de salto nueva en la actual dirección del IP
mov cx,3
mov bx,offset Salto
call Guarda
mov cx,24 ;ejecuta el salto (24 ticks)
call _trace
mov dx,Dir_ini ;recupera la instruccion original en la memoria del 8051
mov bx,offset Inst_ini
mov cx,3H
call Guarda
mov dx,dir_salto ;almacena la rutina de extracción de registros en la posición deseada
add dx,70h
mov dh,rutina_reg+1
mov dl,rutina_reg+2
mov dx,dir_salto ;almacena la rutina de registros
mov bx,offset Rutina_reg
mov cx,70h
call Guarda
mov cx,1480 ;ejecuta la rutina completa regresando automáticamente (1480 ticks)
call _trace
mov dx,dir_salto ;lee el valor de los registros copiados en memoria del 8051
add dx,70h
mov bx,offset registros ;al bufer del ordenador
mov cx,32
call Toma
mov dx,dir_salto ;restaura la memoria inical del sistema 8051
mov cx,90h
mov bx,offset Memo_ini
call Guarda
;refresca la ventana en pantalla con los valores leidos
cmp vez_reg,1
jz nvent
window 2,60,10,75,Mreg
nvent:
mov bx,offset registros + 18
gotoxy 61,3
printf MR0
printf word ptr [bx],@H
gotoxy 61,4
printf MR1
printf word ptr [bx+1],@H
gotoxy 61,5
printf MR2
printf word ptr [bx+2],@h
gotoxy 61,6
printf MR3
printf word ptr [bx+3],@h
gotoxy 61,7
printf MR4
printf word ptr [bx+4],@h
gotoxy 61,8
printf MR5
printf word ptr [bx+5],@h
gotoxy 61,9
printf MR6
printf word ptr [bx+6],@h
gotoxy 61,10
printf MR7
printf word ptr [bx+7],@h
ret
prn_reg endp
end prn_reg
No hay comentarios:
Publicar un comentario
Si tienes algún comentario, duda o sugerencia, o si quieres aportar algún código creado a partir de las librerías expuestas aquí, por favor, indícamelo.