practica curso ingenieria-industrial electronica

Upload: daniel-franco-morales

Post on 28-Feb-2018

228 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    1/23

    1

    ESCUELA POLITCNICA SUPERIOR.

    Grado en Ingeniera Electrnica y doble grado Ingeniera Elctrica yElectrnica.

    Informtica. Curso 2014-2015.

    PRACTICA DE CURSO. SIMULADOR DE CPU

    INDICE

    Introduccin..................................................................................................................................................................1Recursos .......................................................................................................................................................................3Definicin de la CPU a simular....................................................................................................................................3Programa ejemplo.........................................................................................................................................................6Funcionamiento del programa simulador .....................................................................................................................6Formato del fichero de entrada al simulador ................................................................................................................7Control de excepciones de la CPU ...............................................................................................................................8

    Probando el ejemplo en el simulador grfico ...............................................................................................................8Ejercicios preliminares ...............................................................................................................................................10Ejercicios con sentencias condicionales. ....................................................................................................................11

    Campos de una instruccin. ........................................................... .................................................................. ........................11Decodificacin de instrucciones usando C. ..................................................................... ........................................................12

    Ejercicios con bucles. .................................................................................................................................................15Ejercicios con vectores ...............................................................................................................................................16Ejercicios con ficheros................................................................................................................................................18

    Introduccin

    Este boletn contiene la descripcin completa de la prctica de curso de este ao: un simulador de CPU.Un simulador de CPU es un programa que acta interpretando las instrucciones de una CPU y ejecutndolas en un entorno

    virtual. El sistema que se emula puede existir realmente, o bien ser un entorno completamente inventado. El simulador esuna herramienta de uso comn cuando se realizan prototipos de sistemas basados en microcontroladores, ya que por lo generales ms sencillo depurar el programa de control en un simulador del microcontrolador, y luego, una vez libre de errores, grabar

    dicho programa en el microcontrolador.

    Entorno de programacin Easy68K con ensamblador y simulador del

    procesador Motorola 68000

    Simulador de PIC PIC Simulator IDE.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    2/23

    2

    En la industria informtica, la simulacin va un paso ms all, y existen aplicaciones que pueden emular a un computador

    completo. Esto se consigue gracias a una tcnica denominada virtualizacin, y permite, por ejemplo, ejecutar un PCcompleto con Windows dentro de un ordenador Mac. Tambin permite tener un nico servidor, es decir, una nica mquinafsica, ejecutando varias instancias de PCs con Linux o Windows. Dicho de otra forma: en el mismo espacio y con los mismosrecursos con los que se mantiene un nico servidor, pueden existir, de forma virtualizada, mltiples servidores.

    VMWare Fusion ejecutando un PC virtualizado con Windows 7 dentro de un

    ordenador Mac con OS X como sistema anfitrin.

    VirtualBox virtualizando Ubuntu Linux dentro de un PC que ejecuta Windows

    7 como sistema anfitrin.

    En el terreno empresarial y domstico, los emuladores se utilizan para ejecutar aplicaciones que originalmente seescribieron para versiones obsoletas de un ordenador, o sistema operativo, y que deben seguir funcionando aunque los tcnicosactualicen los ordenadores o el sistema operativo. Esto ocurre cuando la empresa que desarroll la aplicacin ya no da soportepara nuevas versiones del sistema operativo, o bien resulta que la propia empresa ya no existe. En el hogar, los emuladores seutilizan sobre todo en el campo del entretenimiento, al permitir ejecutar en un ordenador videojuegos que originalmente

    existan como circuitos electrnicos discretos, o grandes placas con memoria y microprocesador, pero que an siguen siendoperfectamente vlidos para jugar y divertirse.

    DosBOX (emulador de MS DOS) en un PC con Windows XP ejecutando

    AutoCAD 2.5 (arriba) y Word Perfect 6.0 (abajo)

    MAME (Multi-Arcade Machine Emulator) emulando en un PC con

    Windows todo el sistema de microprocesador, memoria, etc, que se observaen la placa de circuito impreso en la foto superior. El juego es Street Fighter

    II.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    3/23

    3

    RecursosPara ayudaros en la realizacin de esta prctica se dispone del siguiente material, disponible salvo que se diga otra cosa, en

    Enseanza Virtual.

    Este boletn.

    Libro de teora de la asignatura (Fundamentos de Informtica para la Ingeniera Industrial) disponible en versinimpresa en la biblioteca de la E.P.S.

    Todos los ejercicios y plantillas descritos en este boletn, resueltos (en formato ejecutable) para comprobarvuestras soluciones. Disponible para su descarga como fichero ejercicios_simulador.zip. Cuando en un ejerciciohable de descargar un fichero o plantilla, aqu estar.

    Simulador grfico de la Universidad de Oviedo. Es una versin avanzada del simulador que nosotros mismosharemos. Su archivo de ayuda contiene una descripcin de la CPU que vamos a simular.

    Programa ensamblador y simulador (ste ltimo, slo ejecutable), para hacer vuestros propios programas, o

    ensamblar los que se os den ya escritos, para probar en vuestro simulador y en el que se os entrega, a fin decomprobar su correcto funcionamiento.

    Definicin de la CPU a simular.

    La aplicacin consiste en un simulador para una CPU sencilla que consta de 8 registros generales de 16 bits, denominadosR0, R1, R2, ...., hasta R7; una serie de banderas binarias de condicin, y un registro contador de programa PC, de tamaosuficiente para direccionar la memoria de programa disponible. La CPU es la misma que se describe en el Simulador de CPUde la Universidad de Oviedo, disponible en descarga en la web. Tambin es la misma CPU que se describe al principio del

    tema 2 de teora.

    Esta CPU usa un sistema de memoria unificado para programa y datos (arquitectura Von Neumann). La memoria seimplementar como un vector de elementos de 16 bits sin signo. El tamao del vector ser la cantidad de memoria disponible,

    y se podr ajustar en tiempo de compilacin asignando el valor adecuado a la constante TMEMORIA.

    Se define el siguiente juego de instrucciones en forma tabulada:

    La primera columna indica el nmemotcnico de la instruccin. Esta es una abreviatura de la accin que realiza lainstruccin, tal como MOV por move, SUB por substract, JMP por jump, etc.

    El formato de la instruccin es la secuencia, escrita en formato binario, de esa instruccin. Es decir, describe qucampos tiene esa instruccin y qu hay en cada campo. En la prctica 3 se empezar a usar esto.

    La descripcin indica qu hace la instruccin.

    La columna Excepciones indica si esta instruccin puede generar alguna excepcin. Una excepcin cualquier

    suceso no contemplado en el flujo normal de un programa, y habitualmente significa que algo est mal escrito omal codificado en ese programa.

    La columna Ejemplo muestra un ejemplo de uso de esa instruccin, detallando los contenidos de los registrosantes y despus de ejecutar la instruccin. Cuando as sea necesario, tambin se detallar el contenido de lamemoria y las banderas de condicin.

    Nemotcnico Formato de lainstruccin (binario)

    Descripcin Excepciones Ejemplo de uso

    Instrucciones de movimiento (cdigo de clase de instruccin 00)Todas estas instrucciones estn encaminadas a dar valores a los registros, bien leyendo el valor desde memoria, desde otro registro, o desde la propia

    instruccin. Tambin hay instrucciones que escriben datos de un registro a memoria.

    Un caso especial en esta clase de instruccin es la instruccin STOP, ya que no es una instruccin de movimiento propiamente dicha.

    MOV Rd,Rs 00 000 Rd Rs 00000 Copia el valor que est

    almacenado en el registro Rs,al registro Rd.

    No tiene. MOV R3,R5

    Binario: 00 000 011 101 00000bHexadecimal: 03A0h

    Antes de esta instruccin:

    R3 = 1C40h R5 = 9B23h.Despus de esta instruccin:

    R3 = 9B23h

    MOV Rd,[Ri] 00 001 Rd Ri 00000 Lee un valor de 16 bits de lamemoria, en la direccin

    indicada por el valor del

    registro Ri, y lo guarda en elregistro Rd.

    Excepcin de memoria,si la direccin desde la

    que se quiere leer est

    fuera de rango. En talcaso, el registro Rd no

    se altera.

    MOV R7,[R1]Binario: 00 001 111 001 00000b

    Hexadecimal: 0F20h

    Antes de esta instruccin:R1 = 0300h R7 = 1234h La posicin 0300h

    de memoria contiene el valor 8D01h.

    Despus de esta instruccin:R7 = 8D01h

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    4/23

    4

    Nemotcnico Formato de la

    instruccin (binario)

    Descripcin Excepciones Ejemplo de uso

    MOV [Ri],Rs 00 010 Ri Rs 00000 Escribe el valor de 16 bits que

    est en el registro Rs, a la

    direccin de memoriaindicada por el valor del

    registro Ri

    Excepcin de memoria,

    si la direccin a la que

    se pretende escribir estfuera de rango.

    MOV [R4],R0

    Binario: 00 010 100 000 00000b

    Hexadecimal: 1400hAntes de esta instruccin:

    R0 = FF12h R4 = 12ABh La posicin

    12ABh de memoria contiene el valor 2855h.Despus de esta instruccin:

    La posicin 12ABh de memoria contiene el

    valor FF12hMOVL Rd,inm8 00 100 Rd inm8 Guarda en el byte menos

    significativo del registro Rd el

    valor inm8.

    No tiene. MOVL R5,5AhBinario: 00 100 101 01011010b

    Hexadecimal: 255Ah

    Antes de esta instruccin:R5 = 1812h

    Despus de esta instruccin:

    R5 = 185Ah

    MOVH Rd,inm8 00 101 Rd inm8 Guarda en el byte ms

    significativo del registro Rd el

    valor inm8

    No tiene. MOVH R0,EFh

    Binario: 00 101 000 11101111b

    Hexadecimal: 28EFhAntes de esta instruccin:

    R0 = 6B03h

    Despus de esta instruccin:R0 = EF03h

    STOP 00 111 00000000000 Para la ejecucin del

    programa. Se termina lasimulacin.

    No tiene. STOP

    Binario: 00 111 00000000000Hexadecimal: 3800h

    Instrucciones lgico-aritmticas (cdigo de clase de instruccin 01).Todas estas instrucciones actualizan las banderas de condicin despus de realizar la operacin.

    - Si el resultado de la operacin es 0, ZF vale 1, en otro caso, 0.- El valor de SF ser el valor del bit ms significativo del resultado.

    - Si al realizar la operacin hubo desbordamiento (el resultado no cabe en un entero de 16 bits en complemento a 2) entonces OF vale 1, en otro caso, vale 0.

    - Si al realizar la operacin hubo acarreo (el resultado no cabe en un entero de 16 bits en formato de binario natural) entonces CF vale 1, en otro caso, vale 0.ADD Rd,Rs1,Rs2 01 00000 Rd Rs1 Rs2 Suma el contenido del registro

    Rs1 con el de Rs2, y el

    resultado lo guarda en el

    registro Rd.

    No tiene. ADD R2,R6,R7

    Binario: 01 00000 010 110 111b

    Hexadecimal: 40B7h

    Antes de esta instruccin:R2 = 883Eh R6 = 12FFh R7 = A003h

    Despus de esta instruccin:

    R2 = B302hZF=0, SF=1, CF=0, OF=0

    SUB Rd,Rs1,Rs2 01 00001 Rd Rs1 Rs2 Resta el contenido del registro

    Rs1 menos el de Rs2, y elresultado lo guarda en el

    registro Rd.

    No tiene. SUB R0,R1,R4Binario: 01 00001 000 001 100b

    Hexadecimal: 420Ch

    Antes de esta instruccin:

    R0 = 0A1Ch, R1 = 5982h, R4 =9BB0hDespus de esta instruccin:

    R0 = BDD2h

    ZF=0, SF=1, CF=0, OF=0

    OR Rd,Rs1,Rs2 01 00010 Rd Rs1 Rs2 Realiza la operacin OR

    (suma lgica, en C es el

    operador | ) entre el contenidodel registro Rs1 y Rs2. El

    resultado se guarda en el

    registro Rd.

    No tiene. OR R2,R3,R4

    Binario: 01 00010 010 011 100bHexadecimal: 449Ch

    Antes de esta instruccin:

    R2 = 9B10h R3=E004h R4=38C8h

    Despus de esta instruccin:R2=F8CCh

    ZF=0, SF=1, CF=0, OF=0

    AND Rd,Rs1,Rs2 01 00011 Rd Rs1 Rs2 Realiza la operacin AND

    (producto lgico, en C es el

    operador & ) entre el

    contenido del registro Rs1 y

    Rs2. El resultado se guarda enel registro Rd.

    No tiene. AND R2,R3,R4

    Binario: 01 00011 010 011 100b

    Hexadecimal: 469ChAntes de esta instruccin:

    R2 = 9B10h R3=E004h R4=38C8h

    Despus de esta instruccin:

    R2=2000h

    ZF=0, SF=0, CF=0, OF=0

    XOR Rd,Rs1,Rs2 01 00100 Rd Rs1 Rs2 Realiza la operacin XOR (o

    exclusivo lgico, en C es eloperador ) entre el contenido

    del registro Rs1 y Rs2. El

    resultado se guarda en el

    registro Rd.

    No tiene. XOR R2,R3,R4

    Binario: 01 00100 010 011 100bHexadecimal: 489Ch

    Antes de esta instruccin:

    R2 = 9B10h R3=E004h R4=38C8hDespus de esta instruccin:

    R2=D8CCh

    ZF=0, SF=1, CF=0, OF=0

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    5/23

    5

    Nemotcnico Formato de la

    instruccin (binario)

    Descripcin Excepciones Ejemplo de uso

    COMP Rs1,Rs2 01 00111 Rs1 Rs2 000 Compara el contenido del

    registro Rs1 con el del registro

    Rs2. En realidad lo que hacees restar Rs1 menos Rs2, pero

    no guarda el resultado en

    ningn registro de destino,solamente actualiza las

    banderas de condicin.

    No tiene. COMP R2,R7

    Binario: 01 00111 010 111 000b

    Hexadecimal: 4EB8hAntes de esta instruccin:

    R2 = AA15h R7 = 79F0h

    Despus de esta instruccin:ZF=0, SF=0, CF=1, OF=1

    NOT Rds 01 01000 Rds 000000 Realiza la operacin NOT(complemento a 1) del valordel registro Rds, y lo

    almacena en el mismo

    registro.

    No tiene. NOT R4Binario: 01 01000 0100 000000bHexadecimal: 5080h

    Antes de esta instruccin:

    R4 = 1234hDespus de esta instruccin:

    R4 = EDCBh

    ZF=0, SF=1, CF=0, OF=0

    INC Rds 01 01001 Rds 000000 Incrementa el valor del

    registro Rds

    No tiene INC R1

    Binario: 01 01001 001 000000b

    Hexadecimal: 5240hAntes de esta instruccin:

    R1 = 90BFh

    Despus de esta instruccin:R1 = 90C0h

    ZF=0, SF=1, CF=0, OF=0

    DEC Rds 01 01010 Rds 000000 Decrementa el valor delregistro Rds

    No tiene DEC R7Binario: 01 01010 111 000000b

    Hexadecimal: 55C0h

    Antes de esta instruccin:R7 = 4098h

    Despus de esta instruccin:

    R7 = 4097hZF=0, SF=0, CF=0, OF=0

    NEG Rds 01 01011 Rds 000000 Realiza el complemento a 2

    del valor del registro Rds

    No tiene NEG R6

    Binario: 01 01011 110 000000b

    Hexadecimal: 5780hAntes de esta instruccin:

    R6 = 80B2h (-32590 en decimal)

    Despus de esta instruccin:R6 = 7F4Eh (32590 en decimal)

    ZF=0, SF=0, CF=0, OF=0

    CLR Rds 01 01100 Rds 000000 Pone a 0 el registro Rds No tiene CLR R3Binario: 01 01100 011 000000b

    Hexadecimal: 58C0h

    Antes de esta instruccin:R3 = F12Fh

    Despus de esta instruccin:

    R3 = 0000hZF=1, SF=0, CF=0, OF=0

    Instrucciones de salto incondicional (cdigo de clase de instruccin 10)JMP desplaz 10 desplaz El valor de 14 bits desplaz es

    extendido con signo a 16 bits,y se le suma al valor actual del

    registro PC, obteniendo la

    direccin de la siguienteinstruccin a ejecutar.

    Excepcin de memoriasi la direccin destino

    de salto est fuera del

    rango de la memoria

    disponible.

    JMP -23Binario: 10 11111111101001b

    Hexadecimal: BFE9h

    Antes de esta instruccin:PC = 0120h

    Despus de esta instruccin:

    PC = 0109h

    Instrucciones de salto condicional (cdigo de clase de instruccin 11)BR cond desplaz 11 cond desplaz condcodifica la condicin que

    ha de cumplirse:

    000 C, Salto si CF=1001 NC, Salto si CF=0

    010 O, Salto si OF=1

    011 NO, Salto si OF=0

    100 Z, Salto si ZF=1

    101 NZ, Salto si ZF=0110 S, Salto si SF=1

    111 NS, Salto si SF=0

    Si la condicin se cumple, elvalor de 11 bits desplazse

    extiende con signo a 16 bits, y

    se le suma al valor actual del

    registro PC, obteniendo ladireccin de la siguienteinstruccin a ejecutar.

    Si la condicin no se cumple,

    no se modifica PC.

    Excepcin de memoria

    si la direccin destino

    de salto est fuera delrango de la memoria

    disponible.

    BR S,+42

    Binario: 11 110 00001000010b

    Hexadecimal: F042hAntes de esta instruccin:

    PC = 3200h

    SF=0Despus de esta instruccin:

    PC = 3200h (no se modifica PC, al no

    cumplirse la condicin)

    BR NZ,+42

    Binario: 11 101 00001000010bHexadecimal: E842h

    Antes de esta instruccin:

    PC = A004hZF=0Despus de esta instruccin:

    PC = A02Eh (se modifica PC, al cumplirse la

    condicin)

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    6/23

    6

    Programa ejemploPara comprobar el correcto funcionamiento del simulador, puede emplear el programa de ejemplo mostrado en la siguiente

    tabla, que al ejecutarse, guarda en las posiciones de memoria 0000h a 000Fh las potencias de 2, desde 20hasta 2

    15inclusive.

    El cdigo de este programa est pensado para que comience a ejecutarse a partir de 0010h. En la siguiente tabla mostramosel cdigo (slo el cdigo, no los datos) del programa, que comienza en 0010h. En las direcciones anteriores, 0000h a 000Fh

    estarn los datos que este programa escribe.

    Las direcciones de memoria se dan habitualmente en hexadecimal, as que hemos empleado ese formato en este ejemplo.

    Direccin Nmemotcnico Formato binario Hex. Comentario

    0010 MOVH R0,00h 00 101 000 00000000 2800

    0011 MOVL R0,00h 00 100 000 00000000 2000

    Estas dos instrucciones cargan el registro R0 con el valor 0000h. Como slo puedecargarse un valor inmediato a una mitad del registro, usamos dos instrucciones, una paracada mitad. R0 contendr la direccin de memoria donde iremos escribiendo cadapotencia.

    0012 MOVH R1,00h 00 101 001 00000000 2900

    0013 MOVL R1,01h 00 100 001 00000001 2101

    Usamos el mismo mtodo para cargar el registro R1 con el valor 0001h. R1 es el valor decada potencia. Ir cambiando a 2,4,8,16, Al principio vale 1, que es 20.

    0014 MOVH R2,00h 00 101 010 00000000 2A00

    0015 MOVL R2,10h 00 100 010 00010000 2210

    Y el mismo mtodo para que R2 valga 0010h (que es 16 en decimal). R2 es un contadorque va decrementndose cada vez que se escriba una potencia. Vamos a escribir 16resultados.

    0016 CLR R3 01 01100 011 000000 58C0 Ponemos a 0 el registro R3. Lo usaremos ms tarde.

    0017 MOV [R0],R1 00 010 000 001 00000 1020 Guardamos el valor actual del registro R1 en la direccin de memoria apuntada por R0

    0018 ADD R1,R1,R1 01 00000 001 001 001 4049 Hacemos R1R1+R1, o lo que es lo mismo, R1R1*2, con lo que R1 contiene ahora lasiguiente potencia de 2 a escribir.

    0019 INC R001 01001 000 000000

    5200Incrementamos R0 para que apunte a la prxima direccin de memoria en donde hay queescribir.

    001A DEC R2 01 01010 010 000000 5480 Decrementamos R2 para indicar que ya hemos escrito una potencia.

    001B COMP R2,R3 01 00111 010 011 000 4E98 Comparamos R2 con cero (R3). R2 ser cero cuando hayamos escrito las 16 potencias.

    001C BR NZ,-6 11 101 11111111010 EFFA Si no es cero, saltamos 6 posiciones hacia atrs contando desde la posicin de memoriasiguiente a esta (001D). Es decir, saltamos a 001D-0006=0017h. Con esto volvemos haciaatrs al punto donde escribimos la siguiente potencia en memoria.

    001D STOP 00 111 00000000000 3800 Fin de la ejecucin. Salimos del simulador.

    Funcionamiento del programa simuladorLa aplicacin comenzar mostrando un mensaje de bienvenida con el ttulo SIMULADOR DE CPU. E.P.S. CURSO

    2014-2015. y en la lnea siguiente, el nombre completo del alumno.

    A continuacin, leer desde disco un fichero llamado memoria.txtque contiene los contenidos iniciales de la memoria del

    procesador. Este fichero podr estar en la misma carpeta que la aplicacin, por lo que no hay que especificar la trayectoriacompleta del mismo. En estos contenidos se incluye el cdigo del programa que ha de ejecutarse, y los datos iniciales si loshubiera, y las direcciones de memoria de carga y ejecucin. Su formato se detalla en la siguiente seccin.

    El fichero debe existir, pero no es obligatorio que el contenido de dicho fichero cubra por completo la memoria del

    procesador. A este fin, las posiciones de memoria no usadas se rellenan con 0s. Ms adelante en este documento se muestra elformato concreto que debe tener el fichero memoria.txty un ejemplo. Si no encuentra este fichero, el simulador emitir unmensaje de error en pantalla y terminar su ejecucin.

    Una vez ledo el fichero y cargados sus datos a la memoria de la CPU, la simulacin comienza estableciendo el valor de

    todos los registros a 0, e inicializando el registro PC con la direccin de ejecucin leda desde el fichero de memoria. Lasimulacin ir leyendo y ejecutando cada instruccin hasta ejecutar una instruccin STOP. Cuando esto ocurre, la simulacinterminar, y se mostrar por pantalla un mensaje indicando en qu direccin de memoria de programa se ha detenido elprograma, junto con un listado de todos los registros y sus valores actuales en formato hexadecimal. Por ltimo se escribir el

    fichero resultados.txtcon el contenido de la memoria actual. Hecho esto, la aplicacin terminar. El formato de este ficheroser el mismo que el usado para memoria.txt. La direccin de carga y ejecucin en resultados.txt sern las mismas que se

    leyeron inicialmente de memoria.txt.

    Al ejecutar el simulador desde C-Free o desde la consola, usando el programa de ejemplo, aparecer algo como esto enpantalla:

    SIMULADOR DE CPU. E.P.S. CURSO 2014-2015Miguel Angel Rodriguez Jodar.

    Programa terminado con normalidad. Se encontro STOP en 001D.R0 = 0010R1 = 0000R2 = 0000R3 = 0000R4 = 0000

    R5 = 0000R6 = 0000R7 = 0000ZF=1 SF=0 CF=0 OF=0

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    7/23

    7

    Formato del fichero de entrada al simuladorEs un fichero de texto con nmeros

    de 16 bits escritos en formatohexadecimal. Cada nmero estar enuna lnea.

    El primer nmero indica la

    direccin de memoria donde seva a cargar la informacin del

    fichero. Puede tomar cualquiervalor desde 0000h hastaTMEMORIA-1. En elsimulador, supondremos queeste nmero es una direccin dememoria vlida, es decir, no

    obligamos a que vuestrosimulador tenga que realizareste chequeo.

    El segundo nmero indica ladireccin de memoria donde

    comenzar la ejecucin delprograma que se encuentra en elfichero. Puede tomar cualquier

    valor desde 0000h hastaTMEMORIA-1. Este segundo

    nmero no tiene por qu serigual que el primero ya que unfichero de memoria puedecomenzar definiendo un bloque

    de datos y despus el cdigo,como de hecho pasa con el

    programa de ejemplo. Estesegundo nmero esprecisamente el valor inicialque tendr el registro PC

    (contador de programa).

    El tercer nmero y siguientes

    son los datos que se encuentranconsecutivamente en la

    memoria, comenzando en la direccin de memoriaespecificada por el primer nmero (ver figura).

    As, el programa anterior puede transcribirse a un fichero con

    este contenido, que puede crearse en Windows con cualquier editorde textos, como el Bloc de Notas:

    memoria.txt (cada nmero en una lnea de texto por separado)

    0000 0010 0000 0000 0000 0000 0000 00000000 0000 0000 0000 0000 0000 0000 00000000 0000 2800 2000 2900 2101 2A00 221058C0 1020 4049 5200 5480 4E98 EFFA 3800

    Para ahorrar espacio en la pgina, hemos mostrado el contenido usandoocho nmeros por lnea, pero al crear vuestros propios ficheros de memoriapara el simulador, cada nmero hexadecimal debe ir en una lnea (tal y comose muestra en la figura de la derecha). La lnea final que aparece enla figura no debe escribirse en el fichero. Es slo para indicar visualmente queah termina el fichero de texto.

    El primero nmero que hay en el fichero es 0000h, que significa que elcdigo y los datos del programa estarn almacenados en memoria a partir de ladireccin 0000h de memoria. El segundo nmero es 0010h, e indica que la

    primera instruccin que ha de ejecutarse es la que est en la direccin 0010h. Al

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    8/23

    8

    ser esta una mquina Von Neumann, los datos y el cdigo comparten la memoria, as que el contenido de memoria.txt contiene

    tanto el cdigo, como las posiciones de memoria donde irn los datos de salida. Los siguientes 16 valores son todos 0000h, yson los valores iniciales de las posiciones de memoria desde la 0000h hasta 000Fh. En la siguiente posicin de memoria, en la0010h se ubicar el valor 2800h, que es la versin en hexadecimal de la instruccin MOVH R0,00h tal y como se puede ver enla tabla del programa de ejemplo. El ltimo nmero que aparece en el archivo es 3800h, que es el cdigo de STOP, la ltimainstruccin de nuestro programa.

    A efectos de simplificar la lectura de este fichero, el simulador asumir que el fichero, de existir, es correcto. Es decir, que

    se ajusta al formato descrito. Esto significa que una vez abierto el fichero siempre podremos asegurar que habr al menos dosvalores en l: el valor de la primera direccin de memoria, y el valor inicial del PC, y en ese orden.

    Control de excepciones de la CPUSi durante la ejecucin del programa la CPU se encuentra con una excepcin, la simulacin terminar en ese mismo

    momento, mostrando por pantalla un mensaje describiendo el tipo de excepcin que ha ocurrido y el cdigo completo (lainstruccin en formato hexadecimal) de la instruccin que lo ha producido. Tambin se mostrarn en pantalla el contenido

    actual de todos los registros, pero no se crear el fichero resultados.txt.

    En la siguiente captura se ha modificado el programa cambiando la instruccin de salto condicional que est en la direccin001C, de EFFA a EBFF). El cambio afecta al valor de desplaz de esta instruccin. Al ejecutar de nuevo el programa con el

    simulador ocurre esto:

    SIMULADOR DE CPU. E.P.S. CURSO 2014-2015Miguel Angel Rodriguez Jodar.

    La instruccion (EBFF) en 001C intento saltar a una direccion de memoria ilegal.R0 = 0001R1 = 0002R2 = 000FR3 = 0000R4 = 0000R5 = 0000R6 = 0000R7 = 0000ZF=0 SF=0 CF=0 OF=0

    Las posibles excepciones que pueden ocurrir durante la ejecucin de un programa, y que nuestro simulador debe detectar,

    son:

    Que se intente ejecutar una instruccin que no existe.

    Que se intente leer un valor desde una posicin de memoria ilegal (fuera de rango).

    Que se intente escribir un valor a una posicin de memoria ilegal (fuera de rango).

    Que se intente realizar un salto (condicional o incondicional) a una posicin de memoria ilegal (fuera de rango).

    Para las excepciones que tienen que ver con direcciones ilegales, recordar que la memoria que maneja nuestro simuladorest limitada a TMEMORIA elementos, y TMEMORIA puede ser un nmero pequeo. En la captura de pantalla precedente, elvalor de TMEMORIA que tiene el simulador estaba fijado en 1000 posiciones de memoria. A qu direccin de memoria

    pretenda saltar la instruccin modificada?

    Probando el ejemplo en el simulador grficoEl Simulador de CPU de la Universidad de Oviedo es una versin grfica del simulador objeto de esta prctica. Aqul

    permite ejecutar el programa paso a paso, o ciclo a ciclo. Nuestro simulador no requiere ejecucin paso a paso, ni ciclo a ciclo,sino que ejecutar el programa que se le cargue de forma no interactiva, es decir, a la mayor velocidad posible. Por ello,nuestro simulador tiene una caracterstica que no posee la versin grfica: la instruccin STOP. Esta instruccin no existe en elsimulador grfico, y cuando la intente decodificar, mostrar esta ventana de error en pantalla:

    Es decir, para el simulador grfico, la instruccin STOP es una instruccin invlida y por ello muestra una excepcin.OJO! es una excepcin para el simulador grfico, para nuestro simulador, STOP es una instruccin vlida. El resto deinstrucciones que no sean vlidas en nuestro simulador tampoco lo sern en el simulador grfico.

    Para probar el ejemplo de la seccin anterior, crea un fichero de texto con el Bloc de Notas conteniendo el programa deejemplo: un nmero hexadecimal en cada lnea. Grbalo en disco con un nombre sencillo, como por ejemplo potencias.prg.Este simulador espera que los ficheros de entrada tengan extensin PRG en lugar de TXT como usaremos nosotros.

    Una vez tengas este fichero creado, procede de esta manera:

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    9/23

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    10/23

    10

    Ejercicios preliminaresEstos ejercicios estn pensados para realizarse despus de la explicacin en clase de teora de la organizacin de una CPU.

    No se necesita programar nada en C, pero s usaremos el simulador grfico de CPU disponible en Enseanza Virtual.

    EJERCICIO 1.

    Haz de CPU y usando lpiz y papel para representar la memoria y los registros, ejecuta una a una las instrucciones que hay

    en el programa de ejemplo de este boletn. Llega al menos dos veces hasta la instruccin BR NZ (a esto se le llama hacer latraza de un programa).

    Este ejercicio, aun pareciendo el ms pueril, es quizs el ms importante para comprender cmo funciona esta CPU, y porende, cmo debe simularse. Trabaja siempre que puedas en hexadecimal. Aunque no lo parezca, es ms cmodo que trabajaren decimal, al menos para CPU y este ejemplo.

    EJERCICIO 2.

    Carga y realiza la simulacin grfica del programa de ejemplo tal como se ha descrito. Realiza la simulacin hasta que seejecute la instruccin STOP y el simulador grfico muestre el error de instruccin no vlida. Entonces, usa la ventana delEditor Hexadecimal para comprobar que el programa ha escrito los valores que se esperaban a partir de la posicin 0000h de

    memoria. Recuerda que, si el programa se ha ejecutado correctamente, a partir de esa posicin vers potencias de 2, es decir: 1,2, 4, 8, 16, 32, 64, etc, pero como el editor hexadecimal muestra contenidos en hexadecimal, se vern como 0001, 0002, 0004,

    0008, 0010, 0020, etc.

    EJERCICIO 3.

    En la tabla de instrucciones se especifica que la instruccin BR cond desplaz suma el valor desplaz al valor actual del

    registro PC. Qu valor tiene el registro PC cuando se realiza esa suma? Sigue apuntando el valor de PC a la instruccin queestamos ejecutando (el salto condicional) o ya no? Para averiguarlo, durante la simulacin, al llegar a la instruccin BR NZ,ejectala ciclo a ciclo (F7).

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    11/23

    11

    Ejercicios con sentencias condicionales.A continuacin se proponen una serie de ejercicios, que estn destinados a sentar las bases del programa que implementa el

    Simulador de CPU, objeto de la prctica de este ao.

    Al principio, propondremos pequeos programas y funciones, que solucionan algunos de las cuestiones que se exponen enel enunciado de dicha prctica. Estos programas, quizs no estn relacionados entre s, al menos al principio.

    Poco a poco, iremos haciendo programas y funciones cada vez ms grandes y complejos, re-usando cdigo de los ejerciciosque se han ido haciendo, hasta eventualmente, conseguir el objetivo final, de haber escrito un programa que simula el

    comportamiento de una CPU.

    Para empezar, y dado que hemos hecho ejercicios en donde el programa hace una cosa u otra en funcin de ciertacondicin, vamos a aprovechar lo aprendido para resolver algunos pequeos problemas que se plantean en la prctica del

    simulador. Nos estamos refiriendo a discernir qu hacer una vez que tenemos metido en una variable, el cdigo de lainstruccin que se va a ejecutar. Dependiendo del valor que tenga ese cdigo de operacin, habr que hacer unas cosas, u otras.Esta fase de la simulacin se corresponde con la fase de decodificacin de una instruccin.

    Es recomendable guardar los resultados de cada sesin en un pendrive o dispositivo similar. Usaremos los resultados deestos pequeos ejercicios para escribir porciones de la prctica, ms grandes.

    Campos de una instruccin.

    Lo primero que aprenderemos es a decodificar instrucciones de la CPU. Una instruccin es en esencia un valor de 16 bits

    que, por comodidad, expresaremos en hexadecimal (4 dgitos hexadecimales). Dentro de esos 16 bits est codificada toda lainformacin que necesita la CPU para ejecutar la instruccin (tipo de instruccin, operandos fuente, y operandos destino): sonlos camposde la instruccin.

    Decodificar una instruccin es extraer la informacin de todos los campos que estn dentro de ella. Hay campos que

    existirn o tendrn un significado diferente en funcin del valor de otro campo.

    Los diferentes campos de una instruccin son los siguientes:

    Cdigo de clase de instruccin (existe en todas las instrucciones y siempre est situado en el mismo sitio).

    Cdigo de instruccin (slo si el cdigo de clase define ms de una instruccin).

    Operando destino (hay instrucciones en que este operando tambin es operando fuente).

    Operandos fuente (puede haber ninguno, uno o dos).

    Valor inmediato (slo en las instrucciones en las que se defina este valor).

    El cdigo de clase de instruccin es el nico cdigo que debe existir en todas las instrucciones. Ocupa siempre los dos bitsms significativos de la instruccin, y por tanto su valor puede ser 00, 01, 10 11 (0,1,2 3). En el enunciado de la prctica seofrece ms informacin sobre los cdigos de clase de una instruccin.

    El cdigo de instruccin existe slo si el cdigo de clase agrupa ms de una instruccin (en nuestra CPU esto sucede conlos cdigos de clase 00 y 01, ya que los cdigos de clase 10 y 11 definen, cada uno, una nica instruccin). El tamao delcdigo de instruccin depende de cul sea el cdigo de clase: para el cdigo de clase 00, el cdigo de instruccin ocupa tresbits; para el cdigo de clase 01, ocupa cinco bits. El tamao del cdigo de instruccin indica cuntas instrucciones diferentespueden definirse dentro de una clase de instruccin. As, podemos ver que pueden existir hasta 8 instrucciones de clase 00, y

    32 instrucciones de clase 01. En la CPU, no todas las combinaciones posibles del cdigo de instruccin tienen por qu estarusadas. Puede haber cdigos de instruccin que no identifiquen a ninguna instruccin conocida de la CPU. Por ejemplo, noexiste una instruccin con cdigo de clase 00 y cdigo de instruccin 110. Si la CPU se encontrara con una instruccin as,

    tiene que informar de una excepcin.

    El cdigo de tipo de instruccin, si existe, aparece en la instruccin ocupando los siguientes bits despus del cdigo declase.

    Por ejemplo, la instruccin 258Ah se puede expresar en binario como 0010 0101 1000 1010. Los dos bits mssignificativos son 00, as que sta es una instruccin de movimiento (ver enunciado de la prctica).

    Si es una instruccin de movimiento, el cdigo de tipo de instruccin existe y ocupa los siguientes tres bits. En nuestro casoesos tres bits tienen el valor 100. Segn la tabla de instrucciones de la prctica, es una instruccin MOVL Rd,Inm8.

    Sabiendo en este punto qu instruccin es, podemos decodificar los operandos que necesita: en este caso, esta instruccin

    necesita un operando que es un registro destino (Rd) cuyo cdigo ocupa tres bits, y un valor inmediato de 8 bits, que ocupacomo es de esperar, ocho bits. En la tabla de instrucciones de la prctica vemos dnde estn posicionados cada uno de estoscampos. Para este ejemplo, el valor de Rd ser 101 (5) y el valor inmediato de 8 bits, 1000 1010 (8Ah).

    As, la instruccin decodificada es: MOVL R5,8Ah

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    12/23

    12

    Decodificacin de instrucciones usando C.

    Para extraer cada uno de los campos usaremos los operadores de C que proveen operaciones lgicas. Concretamenteusaremos el operador AND, y adems, un operador existente en C para realizar operaciones de desplazamiento de bits.

    El operandor AND lgico en C se denota con el smbolo &. Es un operador binario, pero a diferencia del operador &&, queopera con valores booleanos, ste opera bit a bit. Es decir, que por ejemplo, la expresin 6 & 3 en C realiza el AND binarioentre el nmero 6 (110) y el nmero 3 (011), as:

    2010

    &011

    110

    2011&1103&6 2(2(

    El operador de desplazamiento de bits se denota en C con el smbolo >> si el desplazamiento es a la derecha, y

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    13/23

    13

    ins>>14

    Una vez que tenemos el campo posicionado, hay que enmascarar los bits no usados. El enmascaramiento es una operacinAND aplicada a un nmero que asla determinados bits de dicho nmero, los cuales quedan con su valor original. El resto debits queda a 0.

    En nuestro caso, nos interesa dejar con su valor original a los dos bits que contienen el cdigo de clase, y que previamente

    hemos llevado hasta el extremo derecho del valor de 16 bits. Es decir, en este ejemplo nos interesa dejar intactos a los bits 0 y1. El resto estarn a 0. Para ello usaremos este valor de mscara:

    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1

    Que en decimal sera el nmero 3.

    Cuando hagamos la operacin AND entre el valor desplazado, conseguido anteriormente, y esta mscara, obtendremos:

    C1 C0

    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1

    0 0 0 0 0 0 0 0 0 0 0 0 0 0 C1 C0

    En C, esto se aplicara as (partiendo de la expresin anterior donde desplazamos el campo a la derecha):

    (ins>>14)&3

    Supongamos que queremos guardar el cdigo de clase de instruccin en la variable clase. Lo haramos as:

    clase = (ins>>14)&3;

    Ahora podemos preguntar por el valor de clase, y segn qu valor tenga (0,1,2 3) sabremos si hay o no cdigo deinstruccin y cmo se extrae.

    Por ejemplo, supongamos que queremos extraer el cdigo de instruccin para el caso en que el cdigo de clase sea 0, yguardar el valor de dicho cdigo en la variable codins. Miramos la tabla de instrucciones y vemos que el cdigo de instruccinen este caso ocupa 3 bits (I2, I1, I0), as:

    I 2 I 1 I 0

    El desplazamiento necesario aqu ser de 11 posiciones.

    ins>>11Y la mscara necesaria ser:

    0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1

    Con lo que la operacin final queda en C:

    codins = (ins>>11)&7;

    EJERCICIO 6

    Escribe un programa en C (descargable en la web como simej6.c) que incluya una funcin que llamaremos obtclase(obtener clase). Esta funcin toma como argumento un valor entero de 16 bits, sin signo, que representa una instruccin, ydevuelve un nmero entero sin signo como resultado de las operaciones descritas anteriormente para hallar la clase de unainstruccin. Este nmero entero, por fuerza, estar comprendido entre 0 y 3.

    Para probar esta funcin, aade al programa en C (a main) dos variables enteras, de 16 bits, sin signo, llamadas: ins, yclase.

    El programa pedir al operador por teclado un nmero en formato hexadecimal (es decir, usa %xdentro descanf), que se

    almacenar en una variable entera (por ejemplo, la podemos llamar aux). A continuacin, el contenido de auxse asigna a lavariable ins. Este nmero guardado en insser una instruccin de 16 bits de la CPU virtual. El programa usar la funcinobtclase para guardar en la variable clase el cdigo de clase de la instruccin, devuelto por la funcin. Finalmente, y enfuncin del valor de clase (que ser 0, 1, 2, 3) mostrar por pantalla un mensaje indicando a qu clase pertenece lainstruccin entrada por teclado (0: movimiento, 1: artimtica, 2: salto incondicional o 3: salto condicional).

    La razn de usar la variable aux(por auxiliar) en elscanf()es porquescanf()no reconoce las variables de tiposhort int,como ins, y para ella, una variable de tiposhort intes como si fuera de tipo int. Lo malo es que una variable de tipo intocupa 4bytes, y unashort int, 2, con lo que al guardar el valor que se ha ledo de teclado, en el caso de una variable short int,scanf

    escribe fuera del espacio asignado a esa variable. Usando una variable auxiliar que sea intevitamos este error. La asignacinins=auxalmacena en la variable ins, de forma segura, lo que se ha ledo en aux.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    14/23

    14

    Es decir, que cada vez que queramos leer de teclado (o en su momento, de fichero) un dato en formato hexadecimal con laintencin de guardarlo en una variable que sea de tiposhort int, haremos esto:

    short int ins;int aux;......

    scanf (%x, &aux); /* leemos de teclado y guardamos en variable INT */

    ins = aux; /* el valor de la variable entera lo copiamos en la variable de tipo SHORT INT */

    EJERCICIO 7

    Escribe otra funcin a la que llamaremos obtcodigo(obtener cdigo de instruccin). Esta funcin toma dos argumentos: elprimero es un valor entero de 16 bits, sin signo, que representa una instruccin, y el segundo es un nmero entero querepresenta su cdigo de clase (que habremos averiguado previamente usando la funcin obtclasecon la misma instruccin), ydevuelve un nmero entero con signo como resultado de las operaciones descritas anteriormente para hallar el cdigo de unainstruccin.

    En esta primera versin de obtcodigo, slo vamos a calcular el cdigo de la instruccin suponiendo que la clase de lainstruccin sea siempre 0. Esta suposicin es necesaria para simplificar este ejercicio, ya que el cdigo de una instruccin secalcula de distinta manera segn cul sea la clase de dicha instruccin. As, para esta primera versin de obtcodigo (lamejoraremos en siguientes ejercicios), sencillamente ignoraremos el segundo argumento por ahora, el que representa el cdigode clase de la instruccin.

    Incorpora esta funcin al programa que ests escribiendo en el ejercicio 6. La nueva versin del ejercicio 6 es un programaque pide por teclado una instruccin, calcula su cdigo de clase, y si dicho cdigo de clase es 0, entonces calcula adems sucdigo de instruccin. Para esto es para lo que usamos las dos funciones que hemos definido. Una vez calculado el cdigo, loimprimir en hexadecimal en pantalla. Probad este programa nicamente con instrucciones de la clase 0, ya que para otrasclases, su comportamiento estar indefinido.

    EJERCICIO 8

    Ampla la funcin obtcodigopara que calcule tambin los cdigos de las instrucciones cuyo cdigo de clase es 1, 2 y 3, e

    decir, el de todas las instrucciones. Ahora s que usamos el segundo parmetro de obtcodigo, que en la versin primera eraignorado, para segn qu clase tenga la instruccin, calcular el cdigo de instruccin de una forma u otra.

    Para las instrucciones de la clase 2, en las que no hay cdigo, sencillamente se devuelve 0.

    Para las instrucciones de clase 3, el cdigo que se calcula y devuelve ser el cdigo de la condicin. Como este cdigoocupa 3 bits, igual que en el caso de las instrucciones de clase 0, en realidad las instrucciones de clase 0 y 3 se tratarn de lamisma formas.

    Una vez realizada la ampliacin modifica el programa del ejercicio 6 para que muestre en pantalla la clase y el cdigo de lainstruccin tecleada.

    Para probar los programas de los ejercicios 6, 7 y 8, usa los ejemplos de instrucciones que hay en la tabla de instrucciones

    del enunciado de la prctica.

    Los programas escritos en estos ejercicios, sobre todo el del ejercicio 8, nos permiten discernir, dada una instruccin leda,saber de qu clase es, y dentro de la clase, saber cul de ellas es. Una vez que tengamos una instruccin identificada, podemosseguir decodificando el resto de sus campos para obtener los operandos que necesita. Una vez se saben los operandos, estamoslistos para ejecutar la instruccin, es decir, hacer los cambios y operaciones necesarias en los registros de la CPU segn la

    instruccin que hemos ledo.

    En una CPU real, las instrucciones se leen directamente de memoria y se van decodificando. Por diversas causas, puedenaparecer instrucciones desconocidas, o instrucciones cuyos operandos no son correctos. Cuando esto pasa, la CPU no puedeejecutar la instruccin y ocurre una excepcin. Las excepciones ocurren con muchsima frecuencia: la mayora de dichasexcepciones son benignas, es decir, no conducen a tener que abortar ningn programa que se est ejecutando en el

    ordenador, pero hay veces en que esto no es as, y una excepcin obliga al sistema operativo a terminar bruscamente unprograma. Quizs el ejemplo ms conocido sea la ventana que aparece en Windows cuando un programa sufre un error (casisiempre, por estar mal escrito).

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    15/23

    15

    Ejercicios con bucles.

    EJERCICIO 9

    Usando como partida la plantilla de nombre simej9.c , escribe una funcin que se llamar simulador. De momento, estafuncin no tiene argumentos de entrada, ni devuelve ningn valor a la salida. Es decir, su prototipo ser:

    void simulador (void);

    Esta funcin usar un bucle que pedir instrucciones (nmeros hexadecimales de 4 dgitos, o 16 bits) por teclado al usuario.Incorpora tambin al programa las funciones obtclasey obtcodigo, para que la nueva funcin pueda calcular el cdigo de clasey el cdigo de instruccin de la instruccin recin introducida y mostrarlo por pantalla. El programa repetir las operaciones depedir instruccin y mostrar cdigo y clase mientras la instruccin leda no sea STOP. Cuando la instruccin leda sea STOP, elbucle terminar y mostrar un mensaje como ste:

    Fin de programa, Codigo de operacion ledo es STOP

    Para que el programa sea ms claro, se aconseja definir una constante (usando #define), de nombre STOP y de valor0x3800 (que es el cdigo de operacin de STOP en hexadecimal, tal y como se puede comprobar en la tabla de instruccionesdel enunciado de la prctica.)

    EJERCICIO 10

    Modifica la funcinsimuladordel ejercicio anterior para que declare una variable entera llamadapc, inicializada a 0, y la

    incremente dentro del bucle. Dentro del bucle debe mostrar un mensaje como:

    Dame instruccin en la direccin %4.4X:

    Al ejecutarse, %4.4X se sustituir por el valor de la variablepc (aparecer como un nmero hexadecimal de 4 dgitos,

    relleno con ceros a la izquierda). La idea es que mientras que el programa se ejecuta, el usuario hace el papel de memoria dela CPU, y va suministrando instrucciones a medida que la CPU las pide. El nmero que aparece en el mensaje de cortesa sera

    la direccin de memoria donde est la instruccin que la CPU quiere leer. Al comenzar esta direccin en 0, el valor depcse

    convierte, de facto, en una cuenta de instrucciones.

    Cuando el bucle termina, el mensaje final cambia a ste:

    Fin de programa, Codigo de operacion ledo es STOP. Se leyeron ninstrucciones

    Donde nes el valor depctras el bucle (por ahora, coincide con el nmero de instrucciones ledas)

    EJERCICIO 11

    Vamos a darle algo de cuerpo al simulador: tenemos un programa, el del ejercicio 10, que constituye el bucle principalde emulacin de la CPU: mientras no se termine la emulacin, la CPU debe seguir leyendo instrucciones. Una vez quetenemos un nuevo cdigo de operacin de instruccin, tendremos que preguntar cul es, para segn sea uno u otro, realizar lasoperaciones pertinentes.

    Modificar la funcin simulador para que, dentro del bucle y una vez que tenemos una nueva instruccin introducida porteclado, el programa la decodifique e imprima por pantalla el mnemotcnico de dicha instruccin (STOP, MOVH, MOVL,etc). Para ello ser muy til la construccin if-else if-else ifvista en la prctica Condiciones. Al principio, decodificasolamente las instrucciones cuyo cdigo de clase sea 0 (las instrucciones de movimiento). Luego ve ampliando la funcin,aadiendo ms if-else ifpara decodificar el resto de instrucciones. El esquema de esta decodificacin, que estara en el cuerpodel bucle, sera as:

    LEEinstruccin en variable ins/* usa en realidad, auxpara leer la instruccin como se ha avisado */codclase obtclase(ins)=codins (i= obtcodigo ns, codclase)SEGN HACERcodclase CASO 0: SEGN HACER /* instrucciones de carga y almacenamiento */codins CASO 0: ...

    CASO 1: ...CASO 2: ...CASO 4: ...CASO 5: ...CASO 7: fin_simulacion=1 /* se ha leido la instruccin STOP */POR DEFECTO: EXCEPCION

    FIN SEGUNCASO 1: /* instrucciones aritmtico-lgicas */CASO 2: /* salto incondicional */CASO 3: /* salto condicional */

    FIN SEGUN

    Recuerda que las secuencias if-else if terminan con un else (sin un if a continuacin). Ese ltimo else es el caso que seejecuta cuando ninguna de las anteriores condiciones se cumple. Para nosotros esto pasa cuando nos encontramos con un

    cdigo de instruccin para el que no hay una instruccin definida. Entonces, el programa debe imprimir la palabraEXCEPCION.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    16/23

    16

    Ejercicios con vectoresEn simulador tenemos una memoria. Esta memoria, segn las especificaciones, es de elementos de 16 bits. En C un

    elemento de 16 bits sin signo es de tipo unsigned short.

    Vamos a aadir la memoria a nuestra CPU. Adems, vamos a aadir tambin los registros generales R0 a R7.

    EJERCICIO 12

    El programa de este ejercicio lo haremos en un fichero aparte, no nos basaremos en ejercicios anteriores. Ms tarde,juntaremos el cdigo de este ejercicio con los anteriores. Usaremos como plantilla el ficherosimej12a14.c

    En el programa, define primero una constante (usando #define) que d un valor a TMEMORIA. Para empezar, un valor de

    100 no est mal. Declara un vector de TMEMORIA elementos, donde cada elemento ser de 16 bits. Por ejemplo, as:

    #define TMEMORIA 100 // Esto se pone justo despus de los #include

    Ya dentro del cdigo, hay que declarar e inicializar este vector. Para declarar el vector, llmalo mem. Segn lasespecificaciones de la prctica, los elementos no usados de la memoria estarn a 0, as que comenzaremos por inicializar todala memoria a 0. Como son muchos elementos, conviene hacerlo con un bucle, que inicialice cada elemento.

    Escribe una funcin que llamaremosInicializarMemoria, con este prototipo:

    void InicializarMemoria (unsigned short m[], int tmem);

    Dentro de la funcin, mser el vector que contiene a la memoria, y tmem, un valor entero que indica cuntos elementostiene el vector. La funcin se encargar de poner un 0 en cada elemento de m.

    A esta funcin la llamaremos desde main()de esta forma:

    InicializarMemoria (mem, TMEMORIA);

    Nuestra CPU necesita 8 registros, que en la especificacin estn nombrados como R0, R1, R2, etc. Cmo es mejorhacerlo? 8 variables llamadas r0,r1,,r7? O un vector de 8 elementos r[8]? Antes de decidirte por uno u otro, piensa en loque tendras que hacer para, por ejemplo, implementar una instruccin como ADD Rd,Rs1,Rs2, donde hay que coger el valordel registro nmeros1, sumarlo con el valor del registro nmero s2, y el resultado guardarlo en el registro de nmero d. Losvalores des1,s2y destaran en sendas variables.

    Una vez que lo hayas pensado, declara los registros generales, e inicialzalos todos al valor 0.

    EJERCICIO 13

    La memoria est inicializada a 0, pero esto slo, no nos vale para el simulador. La memoria debe contener el programa quese va a ejecutar (y el resto, a 0). En este ejercicio, vamos a rellenar parte de la memoria con un programa. En la prctica finalesto se hace leyendo un fichero. Nosotros de momento vamos a leer desde el teclado.

    Escribe una funcin a la que llamaremos CargarMemoria, con este prototipo:

    void CargarMemoria (unsigned short m[]);

    Que ser llamada desde main()as:

    CargarMemoria (mem);

    Esta funcin necesita poder leer y modificar una serie de variables que tambin se necesitan en otros puntos del programa.Si definimos esas variables dentro de la funcin, no podrn ser usadas por otras funciones. Para remediarlo, usaremos variables

    globales, que son variables que pueden ser ledas y modificadas por cualquier funcin.

    Una variable global es toda variable que se declare fuera de una funcin. Nosotros definiremos las variables globalesdespus de los #includes y #defines, y antes de los prototipos.

    Aade una variable global que llamaremos pc. Ya sabes para qu sirve. Aade como variables globales a los registros y alvector mem.

    La funcin CargarMemoriapide por teclado (con su correspondiente mensaje de cortesa) un valor en hexadecimal, que

    ser la posicin de memoria a partir de la cual se va a almacenar el programa. Este valor deber guardarse tambin en unavariable global, que llamaremospos_origen. Copiamos su valor a otra variable (sta, local), que llamaremospos_actual.

    A continuacin, pediremos al usuario por teclado la direccin, en hexadecimal, de la primera instruccin a ejecutar una vez

    que comience la simulacin. Dnde hay que guardar este valor? En una variable que represente a un registro del procesadorque seale a la prxima instruccin a ejecutar. Esa tambin es una variable global. Mantendremos adems una copia de estevalor en otra variable global.

    A continuacin, el programa ir pidiendo al usuario valores hexadecimales. Cada valor se ir guardando en la memoria, en

    el elemento (direccin) que indique la variable pos_actual. A cada nuevo valor introducido en memoria, la direccin(pos_actual) donde se almcena, se ir incrementando. Esto se repetir MIENTRAS QUEhaya an datos que introducir.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    17/23

    17

    Cuando se lee de un fichero, existe una forma de detectar que no hay ms datos para introducir. Este sistema tambin sepuede usar para el teclado. Simplemente hay que saber que el teclado se llamastdin. La forma de saber si ya no hay ms datos

    para introducir por teclado es usando la funcinfeof()con el parmetrostdin. Por ejemplo, el siguiente programa:

    #include

    int main(){int n;

    printf (Dame un numero (pulsa Ctrl-Z para terminar): );fflush (stdin);scanf (%d, &n);while (!feof(stdin)){printf (Tu numero es: %d\n, n);printf (Dame otro numero (pulsa Ctrl-Z para terminar): );fflush (stdin);scanf (%d, &n);

    }}

    Pide nmeros por teclado al usuario y los va imprimiendo en pantalla, hasta que el usuario, en respuesta a una peticin deun nmero pulsa las teclas Ctrl y Z simultneamente. Esta pulsacin va a ser nuestra forma de decirle al ordenador que noqueremos introducir ms nmeros (en otros sistemas operativos, como Linux u OS X, se usa la combinacin Ctrl-D en lugar deCtrl-Z).

    Al pulsar esta combinacin de teclas, aparecer en pantalla la secuencia ^Z (el carcter ^se asocia a control). Pulsando

    Introse enva la secuencia ascanf.

    La llamada a la funcinfeof(stdin)devuelve VERDADERO si la ltima vez que se pidieron datos por teclado, el usuariopulso Ctrl-Z. Devuelve FALSO si no fue as. De esa forma, el bucle se lee como Mientras NO se haya pulsado Ctrl-Z

    El algoritmo a implementar en la funcin CargarMemoriaes ste:

    LEERdireccion origen de los datos en variablepos_origenpos_actualpos_origenLEERdireccion inicial de ejecucin en variablepcpc_inicialpcLEERinstruccinMIENTRASQUEen la ultima lectura no se haya pulsado ctrl-z HACER

    Copiar a la direccionpos_actualde memoria el valor de instruccinIncrementarpos_actualLEERinstruccin

    FINMIENTRAS

    Al finalizar este bucle, en la variable pos_actual estar el valor de la primera direccin de memoria libre, tras haberintroducido el programa y los datos. Este valor lo guardaremos en una variable global a la que llamaremos pos_final. Ahoratenemos acotada la porcin de memoria que hemos inicializado con los valores que se han ledo de teclado: es la porcin queva desde la direccin guardada en pos_origen hasta (sin llegar) a la direccin guardada en pos_final. Esta informacin lausaremos en el siguiente ejercicio.

    Atencin:no olvidarse de que las lecturas por teclado de valores que vayan a guardarse en variables de tiposhort intdebenhacerse usando una variable auxiliar que sea entera, para acto seguido, asignar el valor de esa variable entera a la querealmente usaremos, de tiposhort int. Ver ejercicio 6 para ms detalles.

    EJERCICIO 14

    Escribe la funcin GrabarMemoria, con el siguiente prototipo:

    void GrabarMemoria (unsigned short m[], unsigned short pc, unsigned short origen, unsigned shortfin);

    Esta funcin imprime por pantalla en hexadecimal, y un nmero en cada lnea, los siguientes valores:

    El valor de origen

    El valor depc

    Todos los valores almacenados en memoria, desde la posicin origen, hasta la posicin justo anterior afin.

    Desde main()la llamaremos as:

    GrabarMemoria (mem, pc_inicial, pos_origen, pos_final);

    Prueba este programa introduciendo el cdigo escrito en el recuadro titulado como memoria.txtde la pgina 5 de este

    boletn. Los valores hexadecimales que all hay han de introducirse de izquierda a derecha, y de arriba abajo. Los dos primeros

    valores corresponden a la direccin de origen, y direccin inicial de ejecucin. Los contenidos que van a memoria comienzanen realidad en el tercer nmero (0000). Despus de introducir el ltimo nmero (3800), cuando pida el siguiente, pulsa Ctrl-Zpara indicar que se han terminado los datos de entrada. En ese momento se mostrar la salida impresa generada porGrabarMemoria, que debe coincidir con el contenido del recuadro.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    18/23

    18

    Ejercicios con ficheros.

    EJERCICIO 15

    Partiendo del programa del ejercicio 14, vamos a cambiar el comportamiento de la funcin GrabarMemoria. Ahora mismo,los datos se vuelcan en la pantalla. Modifcalo para que dichos datos se vuelquen en un fichero de nombre resultados.txt taly como se pide en los requisitos del simulador (ver boletn del simulador). Al probar esta nueva versin veremos que ya no se

    imprimen los datos de memoria al final, como pasaba en el ejercicio 14, sino que aparecen en el fichero mencionado.Comprueba que el fichero se ha generado correctamente abrindolo con el Bloc de Notas.

    EJERCICIO 16

    Haremos otra modificacin al programa, partiendo del ejercicio 14. La funcin CargarMemoria ahora no inicializa elvector de memoria desde teclado, sino desde fichero.

    Cambiaremos tambin su prototipo: originalmente esta funcin no devuelve nada. Ahora s devuelve un entero. Modifica el

    prototipo para reflejar este cambio. El valor que devuelve se explica a continuacin:

    Puede ocurrir que el fichero memoria.txt no pueda abrirse para lectura. En ese caso, la funcin CargarMemoria debedevolver 0 para indicar error. Si la lectura se realiz con xito, devolver 1. Puedes tomar como gua el diagrama de flujo de la

    seccin Programacin modular del tema 3 de teora, donde se ha refinado esta funcin.

    Para probar esta nueva funcin junto con la modificada en el ejercicio 13, crea un fichero memoria.txtusando el Bloc deNotas. Hay un ejemplo de este fichero en el boletn de la prctica del Simulador. Tambin puedes crear el fichero memoria.txtusando el ensamblador suministrado en las herramientas de testeo del simulador, en Enseanza Virtual.

    Si todo va bien, al ejecutarse el programa se crear un fichero resultados.txtcuyo contenido debe ser idntico a memoria.txt

    Ha llegado el momento de unir las funciones GrabarMemoria, CargarMemoria, eInicializarMemoriaen el programa cuyaplantilla se llamasimcpu.c . A partir del siguiente ejercicio se irn incorporando otras funciones que ya tenamos escrita a estemismo programa. Esta plantilla es la ltima que usaremos, y contiene al simulador completo.

    EJERCICIO 17

    Del ejercicio 11, rescata la funcinsimulador. Esta funcin, recordemos, iba pidiendo instrucciones por teclado al usuario,y mostrndolas por pantalla, hasta que el usuario tecleaba la instruccin STOP, o bien se produca una excepcin.

    Vamos a hacer algunos cambios a esa funcin. Para empezar, copia la funcin a la nueva plantilla donde ya hemos copiadoel resto de funciones. Copia tambin las funciones obtclase()y obtcodigo()que son usadas por esta funcin. En la plantilla yaestn definidos los prototipos de todas estas funciones, as que slo hace falta copiar las implementaciones.

    En segundo lugar, vamos a cambiar el prototipo de la funcin. El original era:

    void simulador (void);

    El nuevo prototipo ser ste:

    int Simulador (void);

    Lo que devuelve la nueva versin de Simuladores un 0 si la simulacin se ha producido sin excepciones, y distinto de 0 sihubo una excepcin. Ahora mismo, la nica excepcin que estamos tratando es la de instruccin incorrecta, as que a esaexcepcin le asignaremos el valor 1. En la funcin Simuladorpor tanto aadiremos una variable excepcion, que inicialmente

    valdr 0, y ocasionalmente, cuando nos encontremos con un cdigo de instruccin que no tiene correspondencia con ningunainstruccin definida, valdr 1. Luego veremos otros tipos de excepciones que se pueden producir en la ejecucin, que harnque esta variable tome otros valores diferentes de 0 y 1.

    A continuacin viene el cambio ms grande de todos: la nueva funcin Simuladorya no lee instrucciones desde el teclado,sino que las leer de la memoria, es decir, el vector mem. Eso significa que dentro de la funcin Simulador, donde aparece un

    cdigo similar a ste:

    printf (Dame instruccin en la direccin %04.4X: , pc);fflush (stdin);scanf (%04.4X, &aux);ins = aux;

    Debe cambiarse por una instruccin que lea el elemento pc-simo del vector mem. Por supuesto, ya no hay mensajes de

    cortesa ni lectura de teclado en esta funcin. El elemento ledo se pasa directamente a la variable ins. Ya no hace falta aqula variable entera auxpara poder leer nmeros hexadecimales de teclado sin peligro puesto que ya no leemos de teclado en estafuncin.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    19/23

    19

    La variable pc, por otra parte, ya no se inicializar a 0, sino que se inicializar al valor que tenga la variable global

    pc_inicial, y cuyo valor fue ledo del fichero en la funcin CargarMemoria.

    Al final de todos estos cambios, lo que tenemos es una funcin que se encarga de, dentro de un bucle, ir leyendo de formasecuencial instrucciones desde el vector mem. El ndice que se usa para acceder a memes el valor depc, que se incrementaren 1 justo despus de haber ledo la instruccin.

    La instruccin leda es decodificada, y su mnemotcnico se imprime en pantalla.

    Esto contina as hasta que la instruccin leda es STOP, o bien se produjo una excepcin. En el primer caso, Simuladordevuelve 0. En el segundo caso, devuelve 1. El bucle whileque controla la lectura de instrucciones debe terminar no solamentesi se encuentra STOP, sino tambin si la ltima instruccin gener una excepcin.

    Al terminar el bucle de simulacin se mostrar un mensaje de que se ha terminado porque se encontr STOP (como

    tenamos hasta ahora) o bien mostrar que se ha terminado porque ha ocurrido una excepcin. El mensaje de excepcincontendr la direccin de memoria donde ha ocurrido dicha excepcin (OJO! Porque la variable pcestar apuntando no a ladireccin de la instruccin incorrecta, sino a la siguiente) y la instruccin en s (en formato hexadecimal ambos valores).

    Ya tenemos un programa que es capaz de cargar un programa para nuestra CPU desde un fichero. El programa, una vez

    cargado, es ledo por el simulador que va mostrando las instrucciones a medida que las lee y decodifica. Como lasinstrucciones no se ejecutan, el registro PC siempre va incrementndose en 1 cada vez, ya que an no se estn ejecutando las

    instrucciones de salto que pudieran cambiar su valor.

    Por ltimo, nuestro programa es capaz de generar un fichero con el contenido de la memoria. En este momento, repetimos,como el programa realmente no se ejecuta, el contenido de la memoria no ha cambiado, as que el fichero resultados.txt

    debera tener el mismo contenido que memoria.txt, salvo que durante la lectura e identificacin de alguna de las instruccionesse cometiera alguna excepcin. Si esto pas, vers que el fichero resultados.txtno se genera (mira en maincomo la funcinGrabarMemoria slo es llamada cuando el resultado de la funcin Simuladores igual a 0, es decir, cuando no se produjoninguna excepcin durante la simulacin).

    El resto de los ejercicios hasta el ltimo muestran cmo implementar la ejecucin de las instrucciones del simulador.

    Mostraremos paso a paso cmo implementar la ejecucin de alguna de las instrucciones de movimiento (clase 0) y una de lasinstrucciones aritmtico-lgicas (clase 1). El resto tendrs que hacerlas t por tu cuenta.

    Todas las instrucciones que componen nuestra CPU van a operar sobre registros y/o memoria. Cuando una instruccinnecesite leer o escribir a un registro, acceder a la posicin adecuada del vector de registros. Cuando tenga que escribir o leer a

    memoria, tendr que hacer lo propio con el vector mem.

    Adems, las instrucciones aritmtico-lgicas, tras su ejecucin, tendrn que actualizar las banderas de la ALU segn elresultado de la operacin.

    Las instrucciones de salto operarn adems sobre el registro PC, modificndolo si es necesario.

    EJERCICIO 18

    Vamos a implementar el comportamiento de las instrucciones MOV, MOVH y MOVL. Estas son instrucciones de clase 0.Las modificaciones se harn sobre el cdigo de la funcin Simulaciondel ejercicio 17.

    Localiza el punto en tu cdigo, dentro de la cadena de if-else if (o switch/casesi has optado por implementarlo as) dondese ha identificado correctamente la instruccin MOV. Seguramente ser la primera instruccin que identificas. El punto dondese ha identificado es precisamente donde haces el printf (MOV Rd, Rs\n);. Pon ese printfen un comentario (por ejemplo,poniendo dos barras // delante de l, o encerrando toda la orden entre un /* y un */). Es mejor dejarlo como comentario que

    borrarlo, ya que al dejarlo de comentario recordamos que ah es donde se ejecuta esa instruccin. Si ocurre algn error ytenemos la necesidad de saber qu instrucciones se estn ejecutando en nuestro programa, podemos descomentar la lnea con

    printfy volver a ver esa informacin.

    Tenemos que averiguar los valores de los operandos Rd y Rs para la instruccin en curso. Rd y Rshacen referencia anmeros de registros, por lo que los valores de cada uno de estos estar entre 0 y 7. Un valor entre 0 y 7 se codifica con 3 bits.

    Repasando la tabla con el juego de instrucciones encontramos:

    Nemotcnico Formato Descripcin Excepciones Ejemplo

    MOV Rd,Rs 00 000 Rd Rs 00000 Copia el valor que est

    almacenado en el registro Rs,

    al registro Rd.

    No tiene. MOV R3,R5

    Binario: 00 000 011 101 00000b

    Hexadecimal: 03A0hAntes de esta instruccin:

    R3 = 1C40h R5 = 9B23h.

    Despus de esta instruccin:R3 = 9B23h

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    20/23

    20

    Partiendo del formato de la instruccin en binario, obtenemos que RdyRsocupan las posiciones de bit 8 a 10 (siendo laposicin 0 la de ms a la derecha) paraRd, y las posiciones 5 a 7 para Rs. Usaremos la misma tcnica que para averiguar el

    cdigo de clase y de instruccin: desplazamientos y mscaras.

    Para averiguar el valor deRd, habr que desplazar la instruccin leda (que suponemos que est en la variable ins) 8 lugaresa la derecha, y seguidamente aplicarle una mscara que deje slo 3 bits. Usaremos una variable entera llamada rdpara guardar

    este valor, que quedara as:

    rd = (ins>>8)&7;

    Anlogo procedimiento para obtener el valor deRs, que guardaremos en la variable rs:

    rs = (ins>>5)&7;

    Ahora ya tenemos los nmeros de registro para el registro fuente y el registro destino. La instruccin MOV lo que hace escopiar el valor almacenado en el registro nmeroRsal registro nmero Rd.Nuestros registros son elementos de un vector quese llama R, as que la accin de MOV se implementara as:

    R[rd] = R[rs];

    Esta instruccin no modifica las banderas de la ALU ni genera excepciones, con lo que no hay que hacer nada ms paraimplementarla. Ahora nuestro simulador es capaz de ejecutar una instruccin: MOV.

    Para MOVL y MOVH (y de hecho, para el resto de instrucciones) el procedimiento es anlogo: se decodifican los

    operandos de la instruccin usando desplazamientos y mscaras, y escribiremos en C las acciones que comportan la ejecucin

    de la instruccin.MOVH y MOVL se parecen a MOV en tanto que escriben un nuevo valor en el registro marcado como Rd. Se diferencian

    ambas de MOV en que sta ltima modifica el registro completo, mientras que MOVL y MOVH slo modifican una mitad (lamitad baja L, o la mitad alta H). Esto tambin lo resolveremos con mscaras y desplazamientos.

    MOVH. Tiene dos operandos: un nmero de registroRd, y un valor inmediato de 8 bits. El primero est en las posicionesde bit 8 a 10, y el segundo est en las posiciones de bit 0 a 7.

    Decodificar ambos operandos es sencillo. Ms incluso para el valor inmediato ya que no requiere desplazamiento, slo lamscara. Supongamos que tenemos los operandos ya decodificados en las variables enteras rde inm8. La accin de modificarla parte alta (los bits 8 a 15) del registro de destino se hara as:

    R[rd] = (R[rd]&0x00FF) | (inm8

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    21/23

    21

    Instruccin Formato binario Operando 1 Operando 2 Operando 3 Accin

    MOV Rd,Rs 00 000 Rd Rs 00000 rd = (ins>>8)&7; rs = (ins>>5)&7; NO TIENE R[rd] = R[rs];

    MOV Rd,[Ri] 00 001 Rd Ri 00000 rd = ri = NO TIENE

    mar = R[ri];if (mar < TMEMORIA)R[rd] = mem[mar];

    elseexcepcion = 2;

    MOV [Ri],Rs 00 010 Ri Rs 00000 ri = rs = NO TIENE

    MOVL Rd,inm8 00 100 Rd inm8 rd = inm8 = NO TIENE

    MOVH Rd,inm8 00 101 Rd inm8 rd = inm8 = NO TIENER[rd]=(R[rd]&0x00FF) |(inm8

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    22/23

    22

    Hemos aadido un ejemplo de cmo se codifica una instruccin que podra generar una excepcin: en la instruccin delectura de memoria, si se lee ms all del lmite de la memoria. La variable excepcionaqu ya no tiene nicamente 0 1, sino

    que toma ms valores. Aconsejamos estos:

    0 para indicar que no hay excepcin.

    1 para indicar una excepcin por instruccin invlida.

    2 para indicar una excepcin durante una lectura a memoria (direccin fuera de rango , mostrada ya en la tabla).

    3 para indicar una excepcin durante una escritura a memoria (direccin fuera de rango).

    4 para indicar una excepcin por destino de salto fuera de rango de memoria.

    As, se puede usar un cdigo como el siguiente para mostrar la excepcin causada:

    switch (excepcion){case 0:

    printf ("Programa terminado con normalidad. Se encontro STOP en %4.4X\n", pc-1);break;

    case 1:printf ("EXCEPCION. Instruccion (%4.4X) desconocida en %4.4X\n", ins, pc-1);break;

    case 2:printf ("EXCEPCION. La instruccion (%4.4X) en %4.4X intento leer la direccion %4.4X\n", ins, pc-1, mar);break;

    ...

    ... etc

    ...}

    Este cdigo se aadir al final de la funcin Simulador; cuando ya ha terminado el bucle de simulacin. Se imprime unmensaje indicando si la simulacin termin correctamente o no, y la causa. Despus de imprimir, la funcin retornar con el

    valor de la variable excepcion.

    Despus de rellenar la tabla, implementa sobre la funcin Simuladortodas las instrucciones de la clase 0. Para ello, hazcomo has hecho en el ejercicio 18, pero para el resto de las instrucciones de esa clase.

    Algunas de las instrucciones de esta clase pueden generar una excepcin de tipo 1 (lectura de memoria en direccin fuerade rango) o 2 (escritura a memoria en direccin fuera de rango). La condicin de fuera de rango se testea con el valor de mary la constante TMEMORIA. Si mar es igual o mayor que TMEMORIA, est fuera de rango (mirar ejemplo en laimplementacin de la instruccinMOV rd,[ri] en la tabla anterior).

    Para probar tu primera versin del simulador, ya casi completo, escribe algn programa de prueba con el ensambladorsuministrado, o usa alguno de los tests preparados a tal efecto.

    EJERCICIO 20

    Por otra parte, las instrucciones de la clase 1 (aritmtico-lgicas) deben actualizar las banderas de la ALU despus de laejecucin. La operacin de actualizacin se realiza mediante una funcin que hemos llamado ActualizaALU. Este es suprototipo:

    void ActualizaALU (unsigned short op1, unsigned short op2, unsigned short res16, int res32);

    Hemos aadido un ejemplo de instruccin de esa clase: la instruccin de suma. En este caso, el resultado de la operacin, esdecir, la suma, se guardar temporalmente en una variable entera de 32 bits (un int) que hemos llamado temp. Acto seguido,ese valor se traslada al registro de destino, que al ser de 16 bits, se quedar slo con parte del resultado. La actualizacin de laALU ocurre en ltimo lugar, llamando a la funcinActualizaALU.

    Normalmente, el resultado almacenado en temp coincidir con el que luego tendr el registro de destino. Esto ocurrir

    siempre que el resultado de la operacin no exceda de 16 bits. Pero si ha excedido, tenemos que detectarlo de alguna forma, ysta es viendo el resultado que debera haber dado la operacin, y el resultado que se ha guardado. De ah que a la funcin

    ActualizaALUse le entreguen dos parmetros: el valor de 16 bits guardado en el registro de destino, y el valor de hasta 32 bits,

    resultado original de la operacin. Veremos en un momento que esto se usa para averiguar el valor del flag de acarreo (CF).

    Esta funcin debe actualizar convenientemente las banderas de la ALU. Recordemos que stas son: ZF (flag de cero), SF(flag de signo), CF (flag de acarreo) y OF (flag de overflow). Para ello, supondremos que existen, como variables globales, las

    variableszf,sf, cfy of. Estas variables valdrn 0 1 durante la ejecucin de un programa. Al iniciarse la simulacin, todasvalen 0 (recuerda aadir esto al principio de la funcin Simulador).

    Las operaciones aritmticas que soporta esta ALU son las siguientes: ADD, SUB, COMP, INC y DEC. Recuerda que lasrestas (SUB, COMP y DEC) son en realidad sumas, en las que al segundo operando se le ha cambiado el signo.

    Para hallar el valor del bit de acarreo recuerda que en una ALU que opera con N bits, el acarreo es el valor del bit N

    (contamos las posiciones de los bits comenzando en 0). En nuestro caso, el valor que tenga el bit 16.

    El flag de overflow (OF), al igual que el de acarreo, slo se actualiza para operaciones aritmticas. Para otras operaciones

    que no sean stas, valdr 0.

  • 7/25/2019 Practica Curso Ingenieria-Industrial Electronica

    23/23

    OF valdr 1 si los signos de los dos operandos op1y op2son iguales, pero el signo del resultado de 16 bits no coincide conellos. Es decir, que vale 1 si op1 y op2son positivos, pero res16es negativo, o si op1 y op2son negativos, pero res16 es

    positivo. Para el resto de casos vale 0.

    El flag de signo (SF)se comprueba sobre el valor de 16 bits. En un nmero de 16 bits en formato de complemento a 2, qubit guarda el signo y qu valores toma segn el signo del resultado? Usa desplazamientos y mscaras para quedarte con el valor

    de ese bit. El valor del flag de signo es el valor que tenga ese bit.

    El flag de cero (ZF)es el ms sencillo de averiguar. Se comprueba tambin sobre res16.

    En total, esta funcin tendr que realizar cuatro sentencias condicionales, uno para cada flag, y en funcin del resultado,poner la variable que representa a ese flag a 1 a 0.

    Dado que hay instrucciones ALU que no son aritmticas, sino lgicas, y en stas hemos dicho que tanto CF como OF

    valdrn 0, simplemente, despus de llamar a ActualizaALU (que a lo mejor ha cambiado estos flags), las pondremosdirectamente a 0. Por ejemplo, la parte final de la implementacin de la instruccin XOR rd,rs1,rs2, que es una instruccinlgica, quedara as:

    op1 = R[rs1];op2 = R[rs2];temp = op1^op2; /* el operador ^ es el XOR en lenguaje C */R[rd] = temp;ActualizaALU (op1, op2, R[rd], temp); /* aqu es posible que OF y/o CF se pongan a 1 */of = 0;cf = 0;/* esta instruccin no es aritmtica, as que ponemos estos dos flags a 0 */

    Escribe el cuerpo de la funcinActualizaALU. El prototipo lo tienes ya escrito. Una vez escrita, ya se pueden implementartodas las instrucciones de la clase 1 en la funcin Simulador.

    Puedes pasar a probar esta nueva versin del simulador escribiendo pequeos programas con el ensamblador, o bien usando

    alguno de los programa-test suministrados.

    EJERCICIO 21

    El operando desplazen las instrucciones JMP y BR es un poco especial. En el primero, dicho operando ocupa 14 bits, y en

    el segundo caso, 11 bits. En C no existen variables que tengan exactamente ese tamao, as que al usar desplazamientos ymscaras, acabamos guardando este valor en una variable de 16 (shortint) 32 bits (int).

    El valor, en ambos casos, debe considerarse como en complemento a 2. Es decir, puede ser positivo o negativo. Cuando es

    positivo no es problema, ya que un nmero positivo que ocupa 11 14 bits, tiene el mismo valor que si se guarda en unavariable que tenga 16 bits, estando los bits no usados a 0.

    Pero si es negativo, s que hay un problema. Pongamos por ejemplo que el valor de desplazes de 14 bits, y es ste (encomplemento a 2 de 14 bits): 11111011000000 . Si pasamos este valor a decimal sale -320.

    Si durante el proceso de decodificacin de este valor lo metemos en una variable de 16 bits (short int) tenemos esto:0011111011000000 . Tomado como un nmero en complemento a 2, resulta que este valor es positivo (su bit ms significativovale 0). Pasado a decimal vale 16064, que no tiene nada que ver con el -320 que debera salir.

    El problema est precisamente al guardar este valor en una variable que tiene espacio para ms bits que los que requiere elvalor. Para salvaguardar el signo de un nmero en complemento a 2 que se almacena en una variable de mayor tamao, serequiere hacer lo que se denomina extensin del signo. Esto consiste en rellenar los bits no usados de la variable con el valordel bit ms significativo del valor original. Se realiza de esta forma:

    Usando desplazamientos y mscaras, averiguamos el valor del bit 10 (o 13, segn el caso que estemos tratando) de desplaz.Este ser nuestro bit de relleno.

    Si el bit es positivo (0) no hacemos nada especial, simplemente dejamos desplazcomo est.

    Si el bit es negativo (1) hacemos: desplaz = desplaz | 0xC000;. Esto lo que hace es poner los bits 14 y 15 de desplaza 1. Sidesplazno es de 14 bits sino de 11, entonces los bits que tenemos que poner a 1 son desde el bit 11 al 15. Calcula qu valor esel que tendremos que usar en lugar de 0xC000.

    Este valor desplazes al fin, el que sumamos al valor actual depc, que recordemos, apunta siempre a la prxima instruccina leer de memoria. Antes de realizar la suma, hay que comprobar que el resultado final no excede el valor de TMEMORIA, yaque si es as, debe generarse una excepcin por destino de salto incorrecto(excepcin 4).

    Con esta informacin, ya puedes implementar las instrucciones de la clase 2 y 3, con lo que el simulador est completo.Puedes probarlo con cualquier programa de los suministrados, o bien escribiendo uno propio.