Home MundoTec Software Código fuente Tutorial / pdf Minijuegos
Cerrar

Tutorial Microcontroladores

Tutorial Microcontroladores.







Microcontroladores

Operación de la CPU

En esta sección discutiremos primero la operación detallada de las instrucciones de la CPU y luego explicaremos cómo la CPU ejecutaría el programa de ejemplo. Trataremos de hacer una detallada descripción de típicas instrucciones de la CPU para pensar cómo lo hace una CPU. Podemos entonces recorrer el programa de ejemplo usando una técnica de adiestramiento llamada “jugando a la computadora”en la que pretenderemos ser una computadora interpretando y ejecutando las instrucciones de un programa.

Operación detallada de las Instrucciones de la CPU

Antes de ver cómo la CPU ejecuta los programas, nos ayudaría conocer (en detalle) cómo la CPU divide una instrucción en operaciones fundamentales y realiza estas pequeñas etapas para llevar a cabo una determinada instrucción. Como veremos, muchos pequeños pasos se ejecutan rápidamente y con suma precisión dentro de cada instrucción, pero nada de estas pequeñas etapas es demasiado complicada.

El circuito de lógica dentro de la CPU parecería ríspido para un ingeniero habituado a trabajar con lógica TTL o bien con lógica de relevadores. Lo que hace del MCU y su CPU otras formas de lógica digital es la densidad del encapsulado. Las técnicas de muy alta escala de integración (VLSI) hacen posible colocar el equivalente de miles de circuitos integrados TTL en una simple pastilla de silicio. Ordenando las compuertas de lógica para formar una CPU, podemos obtener un ejecutor de instrucciones de propósito general capaz de actuar como una caja negra universal. Colocando diferentes combinaciones de instrucciones podría virtualmente realizar cualquier función definible.

Una típica instrucción toma de dos a cinco períodos del reloj interno del procesador. Aunque normalmente no es importante saber con exactitud qué sucede durante cada uno de estos períodos de ejecución, será de ayuda recorrer algunas instrucciones en detalle para entender cómo trabaja internamente la CPU.

Almacenamiento del Acumulador (Modo de Direccionamiento Directo)

Echemos un vistazo a la instrucción STA en el apéndice A. En la tabla de la parte inferior de la página, veremos que $B7 es la versión en modo de direccionamiento directo (DIR) de la instrucción almacenamiento del acumulador. Además veremos que la instrucción requiere dos bytes, el primero para especificar el código de operación ($B7) y el segundo para especificar la dirección directa donde será almacenado el acumulador. (Los dos bytes se presentan como “B7 dd”en la columna de código de máquina de la tabla).

Discutiremos el modo de direccionamiento directo más detalladamente en otro capítulo, pero la breve descripción siguiente nos ayudará a entender cómo la CPU ejecuta esta instrucción. En el modo de direccionamiento directo, la CPU asume que la dirección está en el rango de $0000 a $00FF; en consecuencia, no es necesario incluir los dos dígitos de más peso de la dirección del operando en la instrucción (pues es siempre $00).

La tabla de la parte inferior de la página correspondiente a STA nos muestra que la versión de STA en modo de direccionamiento directo toma cuatro períodos de la CPU para su ejecución. Durante el primer ciclo, la CPU vuelca el contenido del contador de programa sobre el bus interno de direcciones y lee el código de operación $B7, que identifica a la instrucción como la versión en modo de direccionamiento directo de la instrucción STA y avanza a la PC hasta la próxima posición de memoria. Durante el segundo ciclo, la CPU vuelca el contenido de la PC sobre el bus interno de direcciones y lee el byte de menos peso de la dirección directa ($00 por ejemplo). La CPU usa el tercer ciclo de esta instrucción STA para armar en su interior la dirección completa donde se almacenará el acumulador, ya que avanza al PC hasta la próxima posición de memoria (la dirección del código de operación de la próxima instrucción).

En este ejemplo, la CPU une el valor asumido $00 (por ser de modo de direccionamiento directo) con el $00 que fue leído durante el segundo ciclo la instrucción para obtener la dirección completa $0000. durante el cuarto ciclo de esta instrucción la CPU vuelca la dirección construida sobre el bus interno de direcciones, además vuelca el contenido del acumulador sobre el bus interno de datos y acciona la señal de escribir. Esto es, la CPU escribe el contenido del acumulador en la posición de memoria $0000 durante el cuarto ciclo de la instrucción STA.

Mientras el acumulador está siendo almacenado, los bits N y Z del registro de código de condición son modificados de acuerdo al dato almacenado. La fórmula de lógica booleana para estos bits está en la mitad de la página de la instrucción STA. El bit Z irá a uno lógico si el valor almacenado es $00; sino, el bit Z irá a cero lógico. El bit N irá a uno lógico si el bit más significativo del valor almacenado es uno; sino el bit N irá a cero lógico.

Carga del Acumulador (Modo de Direccionamiento Inmediato)

Echemos un vistazo a la instrucción LDA en el apéndice A. En la tabla de la parte inferior de la página, veremos que $A6 es la versión en modo de direccionamiento inmediato (IMM) de la instrucción carga del acumulador. Además veremos que la instrucción requiere dos bytes, el primero para especificar el código de operación ($A6) y el segundo para especificar el dato inmediato con que será cargado el acumulador. (Los dos bytes se presentan como “A6 ii”en la columna de código de máquina de la tabla).

La tabla de la parte inferior de la página correspondiente a LDA nos muestra que la versión de LDA en modo de direccionamiento inmediato toma dos períodos de la CPU para su ejecución. Durante el primer ciclo, la CPU vuelca el contenido del contador de programa sobre el bus interno de direcciones y lee el código de operación $A6, que identifica a la instrucción como la versión en modo de direccionamiento inmediato de la instrucción LDA y avanza a la PC hasta la próxima posición de memoria (la dirección del operando inmediato ii).

Durante el segundo ciclo, la CPU vuelca el contenido del PC sobre el bus interno de direcciones, lee el byte del dato inmediato y lo carga en el acumulador, y luego avanza la PC hasta la próxima posición de memoria (la dirección del código de operación de la próxima instrucción).

Mientras el acumulador está siendo cargado, los bits N y Z del registro de código de condición son modificados de acuerdo al dato almacenado. La fórmula de lógica booleana para estos bits está en la mitad de la página de la instrucción LDA. El bit Z irá a uno lógico si el valor cargado es $00; sino el bit Z irá a cero lógico. El bit N irá a uno lógico si el bit más significativo del valor almacenado es uno; sino el bit N irá a cero lógico.

El bit N (negativo) puede servir para detectar el signo de números signados según el convenio de complemento a dos. En este convenio el bit más significativo es usado como un bit de signo, un uno indica un valor negativo y un cero uno positivo. El bit N puede además usarse sólo como indicador del estado del bit de más peso de una magnitud binaria.

Bifurcación Condicional

Las instrucciones de bifurcación condicional permiten a la CPU elegir uno de dos posibles caminos a seguir por el programa, dependiendo del estado de un bit en particular de la memoria o bien de varios bits del CCR. Si la condición evaluada por la instrucción de bifurcación es verdadera, el programa efectúa la bifurcación a la posición de memoria especificada. Si la condición evaluada es falsa, la CPU continúa con la instrucción siguiente a la instrucción de bifurcación. Los bloques de decisión en un diagrama de flujo corresponden a instrucciones de bifurcación condicional en un programa.

La mayoría de las instrucciones de bifurcación contienen dos bytes, uno para el código de operación y otro para un byte de desplazamiento relativo. Las instrucciones bifurcar si el bit es cero (BRCLR) y bifurcar si el bit es uno (BRSET) requieren tres bytes: el código de operación, un byte de una dirección directa de un byte (para especificar la posición de memoria a evaluar) y el byte de desplazamiento relativo.

El byte correspondiente al desplazamiento relativo es interpretado por la CPU como un número signado en convenio de complemente a dos. Si la condición de bifurcación evaluada es verdad, este desplazamiento con signo se suma a la PC y la CPU lee su próxima instrucción desde la nueva dirección calculada. Si la condición de bifurcación evaluada es falsa, la CPU continúa con la instrucción siguiente a la de bifurcación.

Llamado a Subrutinas y Retornos

Las instrucciones salto (JSR) y bifurcación (BSR) a subrutina automatizan el proceso permitiendo salir del flujo lineal normal de un programa, ejecutar un grupo de instrucciones y luego retornar al punto desde donde se saliera del flujo normal del programa. El grupo de instrucciones externas al programa normal se denomina subrutina. Una instrucción JSR o BSR se usa para ir del programa en curso a una subrutina. Una instrucción retorno de subrutina (RTS) se usa para completar una subrutina, para retornar al programa desde el que fuera llamada la subrutina.

El listado 4-2 presenta líneas del listado de un programa de ejemplo generado por un ensamblador que usaremos para demostrar cómo la CPU ejecuta un llamado a subrutina. Asumimos que el puntero a la pila (SP) apunta a la dirección $00FF cuando la CPU encuentra la instrucción JSR en la posición de memoria $0302. Este listado se describe con más detalle en el capítulo 6.

Microcontroladores

Listado 4-2 – Ejemplo de llamado a Sub – Rutina.

Haremos referencia a la figura 4-3 durante la siguiente discusión. Partiremos nuestra explicación con la CPU ejecutando la instrucción “LDA #$02”en la dirección $0300. el lado izquierdo de la figura muestra el flujo normal del programa compuesto por TOP LDA #$ 02, JSR SUBBY y STA $EO (en ese orden) ubicados en posiciones de memoria consecutivas. En el lado derecho nos presenta las instrucciones de la subrutina SUBBY DECA, BNE SUBBY y RTS.

Microcontroladores

Fig. 4-3 – Secuencia de llamado de una Sub-rutina.

El número de ciclos de reloj de la CPU (entre corchetes) se usará como referencia en la siguiente explicación de esta figura.

[1] La CPU lee el código de operación $A6 de la posición de memoria $0300 (LDA inmediato).

[2] La CPU lee el dato inmediato $02 de la posición de memoria $0301 y lo carga en el acumulador.

[3] La CPU lee el código de operación $CD de la posición de memoria $0302 (JSR extendido)

[4] La CPU lee el byte más significativo de la dirección extendida $04 de la posición de memoria $0303.

[5] La CPU lee el byte menos significativo de la dirección extendida $00 de la posición de memoria $0304.
[6] La CPU arma la dirección completa de la subrutina ($0400).

[7] La CPU escribe $05 en la posición de memoria $00FF y decrementa el SP a $00FE. En otras palabras diremos que “hemos ingresado en la pila el byte menos significativo de la dirección de retorno”.

[8] La CPU escribe $03 en la posición de memoria $00FE y decrementa el SP a $00FD. En otras palabras diremos que “hemos ingresado en la pila el byte más significativo de la dirección de retorno”. La dirección de retorno salvada en la pila es $0305, que es la de la instrucción siguiente al JSR.

[9] La CPU lee el código de operación $4A de la posición de memoria $0400 (DECA). Esta es la primera instrucción de la subrutina invocada.

[10] La CPU usa su unidad aritmético lógica (ALU) para restar uno al contenido del acumulador.

[11] El resultado de la ALU (A – 1) se escribe nuevamente en el acumulador.

[12] La CPU lee el código de operación $26 de la posición de memoria $0401 (BNE relativo).

[13] La CPU lee el byte de desplazamiento relativo $FD de la posición de memoria $0402.

[14] Con la instrucción LDA #$02 en [1], el acumulador se cargó con el valor 2; con la instrucción DECA en [9], el acumulador se decrementó a 1 (que es distinto de cero). De este modo, en [14], la condición de bifurcación fue verdad y el complemento a dos del desplazamiento ($FD o –3) se suma al valor contenido por la PC ($0403 en este momento) para obtener el valor $0400.

[15] a [19] Son la repetición de los ciclos [9] a [13] excepto que al ejecutar la instrucción DECA en [15] en esta pasada, el acumulador era de $01 a $00.

[20] Como ahora el acumulador es “igual a cero”la condición de bifurcación de BNE

[19] es falsa y no se efectúa la bifurcación.

[21] La CPU lee el código de operación $81 de la posición de memoria $0403 (RTS).

[22] La CPU incrementa el SP a $00FE.

[23] La CPU lee $03 de la posición de memoria $00FE. En otras palabras diremos que “hemos retirado de la pila el byte más significativo de la dirección de retorno”.

[24] La CPU incrementa el SP a $00FF.

[25] La CPU lee $05 de la posición de memoria $00FF. En otras palabras diremos que “hemos retirado de la pila el byte menos significativo de la dirección de retorno”.

[26] la CPU arma la dirección de retorno completa recuperada de la pila ($0305) y con ella carga la PC.

[27] La CPU lee el código de operación $B7 de la posición de memoria $0305 (STA directo).

[28] la CPU lee el byte menos significativo de la dirección directa $E0 de la posición de memoria $0306.

[29] y [30] La instrucción STA directo toma en total cuatro ciclos. En los últimos dos ciclos de la instrucción, la CPU arma la dirección completa en la que se almacenará el acumulador uniendo $00 (valor asumido para la mitad más significativa de la dirección para el modo de direccionamiento directo) con $E0 leído en [28]. El contenido del acumulador ($00 en este momento) es almacenado entonces en la dirección reconstruida ($00E0).