Vistas de página en total

martes, 14 de enero de 2014

EMULADOR 8051 (3/12) (REGISTROS)

    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     
           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
           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.
             
       Como la rutina no la vamos a colocar en el punto de ejecución en que esté en este momento el programa, deberemos hacer algo para que se enlacen. Para esto,  usaremos una pequeña instrucción de salto asignada a la dirección de volcado de la rutina. Así antes de ejecutar la rutina copiaremos el valor que tiene  la memoria de la dirección IP actual indicada en DIR_cur,copiaremos la instrucción de salto a la nueva rutina, la ejecutaremos y restauraremos posteriormente los tres byte originales en la dirección del IP (Instruction pointer) a su valor original.
           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.