Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
CAPÍTULO CAPÍTUL O 1 – PARTE PARTE II Instrucciones Introducción En un computador el componente encargado del control del mismo es el CPU. El CPU lo hace mediante la ejecución de un programa, el cual lee de la memoria (por tanto, el programa debe haberse grabado previamente previamente en la memoria). Una memoria está constituida por registros, y se ha visto que los registros son un conjunto de celdas de memorias, cada una de las cuales almacena un valor binario. En resumen, podríamos decir que en la l a memoria sólo pueden estar almacenados números. Si el CPU lee instrucciones de la memoria., entonces necesariamente estas instrucciones tienen que estar estar codificadas como números, números, pues es lo único que se podrá leer, y como la memoria se lee registro por registro, dichas instrucciones necesariamente ocuparán un número entero de registros. La codificación mencionada debe ser tal y como la espera el CPU. Dicha codificación ha sido creada por el equipo diseñador del CPU, y hay tantas codificaciones de instrucciones como procesadores y microcontroladores hay en el mercado. Sin embargo todas ellas tienen algo en común: se representan con números, que serán grabados en la memoria al formar parte de un programa. Así como las instrucciones están codificadas como números, también tiene que estarlo cualquier tipo de dato que se desee sea procesado por el computador. Un ejemplo es el código ASCII que permite representar como números de 7 u 8 bits las letras y signos de puntuación del alfabeto (todos estos denominados “caracteres”). Otro ejemplo lo son los números con signo (sino, ¿cómo representarían el signo menos?). En el presente capítulo se define a una instrucción, se describe cómo se codifican como números, y cómo se almacenan éstos en la memoria. Se verá que algunas instrucciones ocupan más espacio de memoria que otras, pero siempre la cantidad de bits que ocupan será un múltiplo de la longitud de palabra de los registros de la memoria. Finalmente se muestra cómo el CPU ejecuta una instrucción, y cómo es que logra ejecutarlas de manera secuencial. secuencial. Ejercicio: Indicar qué representa el siguiente número binario: 01100001 Si: a) Es un código ASCII b) Representa a un número sin sin signo c) Representa a un número decimal en formato BCD empaquetado. d) Representa a un número en formato de signo y magnitud.
Instrucción (instruction) Una instrucción es un conjunto de bits que le indican al CPU qué operación debe realizar, cómo acceder a los datos que se van a utilizar en la operación (operandos) y dónde almacenar los resultados.
Capítulo1Parte2 rev. 9
1
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Dependiendo del CPU, este conjunto de bits puede estar agrupado en bytes (como en el caso de los CPU´s de 8 bits como el del microcontrolador 68HC11 de Motorola) o en palabras (como en el caso del CPU del ATmega8 de la compañía Atmel en el que la mayoría de instrucciones son de una palabra de 16 bits, y algunas de dos palabras de 16 bits). En general toda instrucción consta de dos partes: código de operación y campo de referencia de operandos.
Código de operación (OpCode, Operation Code) Indica la operación a ejecutar, la longitud de la instrucción (cuántos bytes o palabras tiene la instrucción), y cómo interpretar lo campos de referencia de operandos (denominados modos de direccionamiento), si es que la instrucción los tiene. En el caso del 68HC11, las instrucciones tienen códigos de operación de uno o dos bytes, siendo la mayoría de un byte. En cambio, en el ATmega8, los códigos de operación son de 4 a 12 bits.
Campo de referencia de operando: En este campo está la información i nformación requerida por el CPU para acceder al dato, o datos a utilizar en la operación. Algunas instrucciones no tienen un campo de referencia de operando pues, por ejemplo, los operandos y el resultado están en registros internos del CPU. En el caso del ATmega8, en el que la memoria de programa está constituida por registros de 16 bits, este campo es de 4 a 12 bits en las instrucciones de una palabra de longitud, y de 16 bits en las de dos dos palabras de longitud. Los operandos pueden estar en registros del CPU, en la memoria, o en algún dispositivo de entrada/salida. ¿Por qué se requieren códigos de operación? El CPU es un circuito digital, y como tal lo único que reconoce son valores binarios. Para ser más exactos, lo que realmente realmente reconoce son son dos rangos de voltaje, que por facilidad les asignamos los números 0 y 1. Como se ha visto en secciones anteriores, el CPU espera encontrar las instrucciones en una memoria, y por lo tanto lo único que puede leer de la memoria es lo que le llega por las líneas de datos. En el caso del ATmega8, la memoria de programa tiene un bus de datos de 16 bits y por lo tanto sólo puede puede leer números de 16 bits. Como lo único que reconoce son valores binarios, las instrucciones tienen que representarse con números (patrones de bits). Y para poder distinguir una operación de otra, a cada una se le debe asignar un patrón de bits diferente. Pero no basta con distinguir las operaciones, sino también la manera como se accede al operando. Se verá en el próximo capítulo, que hay varias maneras diferentes de indicar al CPU cómo acceder al operando, y cada una de esas maneras se denomina “modo de direccionamiento”.
Capítulo1Parte2 rev. 9
2
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Formatos de instr ucciones Cada instrucción es representada por un patrón de bits. cada patrón consta de código de operación y campos de referencia a operandos. Al momento de diseñar el CPU, el diseñador tiene que definir cómo se representarán las instrucciones: - Cuántos bits para los códigos de operación y qué bits - Cuántos bits para referenciar a cada operando, y cuántos operandos. A cada manera diferente en que pueden representarse las instrucciones del CPU se le denomina formato de instrucción, y toda instrucción del CPU corresponderá a uno de dichos formatos. Por ejemplo, en el ATmega8, se tienen los siguientes formatos de instrucciones (sólo se muestran algunos de ellos). En gris oscuro se muestra el código de operación. 15
9
8
4 3
OpCode
15
Rd
9 OpCode
15
4
6
OpCode
31
9
5
0 Rd
8
4
A
Rr/Rd
25 24 OpCode (parte 1)
0 Rd
Rr
11 OpCode
3
Rr
9
15
OpCode
8 Rd
0
3
0 A
20
16
Rr/Rd
OpCode (parte 2)
Dirección dato
15
0
Fig. 1 Algunos formatos de instrucciones del ATmega8
No todas las instrucciones tienen códigos de operación de la misma cantidad de bits, y además puede apreciarse que el código de operación está separado en dos partes en el primer y último formato. En el primer formato, el código de operación es de 11 de bits, y el campo de referencia a operando de 5 bits. En el segundo formato el código de operación es de 7 bits y hay dos campos de referencia a operandos de 5bits (uno de los campos, Rd está constituido por dos partes, una de 1 bit y otra de 4 bits). En el tercero, el código de operación es de 7 bits, un campo de referencia de operando es de 3 bits (Rr) y el otro es de 6 bits (Rd). En el cuarto formato el código de operación es de 5 bits, y tiene dos campos de referencia de operando, uno de 5 bits, y el otro de 6 bits (campo A, que está constituido por dos partes). En el último formato la instrucción es de 32 bits, el código de operación es de 11 bits y la instrucción tiene dos campos de referencia a operandos: Rr/Rd de 5 bits y "Dirección dato" de 16 bits. En todos los casos, en los campos de referencia a operandos el bit más significativo es el de más a la derecha, y el menos significativo el de la izquierda.
Capítulo1Parte2 rev. 9
3
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Ejercicio: 1. ¿A cuál de los formatos anteriores corresponde cada una de las siguientes instrucción del microcontrolador ATmega8? cada carácter representa un bit. Un ‘0’ o ‘1’ corresponde a un bit del código de operación. Una misma letra corresponde al mismo campo de referencia de operando. a) 1011 1AAr r r r r AAAA b) 0000 11r d dddd r r r r c) 1111 00kk kkkk k101 d) 1001 010d dddd 0110 e) 0111 KKKK dddd KKKK
Nomenclatura de las operaciones de una instrucción Para representar en forma abreviada las operaciones que se efectúan con las instrucciones, se emplea la nomenclatura que se explica a continuación.
Representación de números: Bases numéricas Para diferenciar las bases numéricas se emplean prefijos, como se indica en la tabla. Ésta es la manera como tendrán que escribir los números en sus programas. Número a representar binario octal hexadecimal decimal
Base
Prefijo
Observaciones
Ejemplos
2 8 16
0b 0 $ 0x ninguno
es el dígito 0, no la letra “o” es el dígito 0
0b1100, es el número 12 010, es el número 8 $C 0xC son el número 12 27
10
dígito 0, como en lenguaje C no debe comenzar con cero
Por ejemplo, 0b1001, 0011, 0x9 y $9 representan al número 9.
Registros Los registros del CPU tienen un nombre con el cual se identifican. Es el fabricante del microcontrolador el que define los nombres para dichos registros, aunque algunos de ellos, por su función particular, tienen un nombre común, como PC, e IR (Ver sección: ejecución de instrucciones, para una explicación de la finalidad de estos registros). PC es el contador de programa IR es el registro de instrucciones SP es el puntero de pila (stack pointer) En el microcontrolador Atmega8, hay 32 registros de 8 bits denominados “de propósito general” (general purpose), con los nombres R0, R1, hasta R31. En el microcontrolador 68HC11 hay un par de registros que se denominan A y B (conocidos como acumuladores).
Capítulo1Parte2 rev. 9
4
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Numeración de bits en los registros Siempre la numeración de los bits en un registro comienza a partir de 0. Por ejemplo, un registro de 8 bits, tendrá los bits del 0 al 7, siendo el bit 0 el menos significativo y el bit 7 el más significativo.
Transferencia de datos Para indicar que el contenido de un registro se copia en otro registro se emplea el símbolo “←”. La flecha apunta al registro en el cual se copiará el dato. Ejemplo: “Copiar el contenido del registro R3 en el registro R7” Se representaría así: R7 ← R3 En general, equivale al símbolo de asignación de los lenguajes C y Pascal (en lenguaje C es “=”, en lenguaje Pascal es “:=”) Ejemplo: “Incrementar en una unidad el registro R9” Se representaría así: R9 ← R9+1 Ejemplo: “Copiar en el registro R14 el número $23” R14 ← $23
Transferencia de contenidos de una direcciones de memoria Cuando el registro cuyo dato se quiere transferir es un registro de memoria, se especifica la dirección del mismo dentro de paréntesis “( )”. cualquier expresión dentro de paréntesis representa una dirección de memoria. Ejemplo: Copiar en el registro R21 el contenido de la dirección 120 de la memoria de datos. Se representaría así: R21 ← (120) La dirección también podría estar almacenada en un registro. Ejemplo: “Copiar en el registro IR” el contenido de la dirección de memoria almacenada en registro PC. IR ← (PC) Interpretación: Si por ejemplo, el registro PC tuviese almacenado el valor $60, lo que se grabaría en el registro IR es el contenido de la dirección $60 de la memoria. En cambio, si el valor contenido en PC fuese $100, se grabaría en IR el contenido de la dirección $100 de la memoria. Ejemplo: Escribir en la dirección de memoria $60 el contenido del registro R31 Se representaría así: ($60) ← R31
Capítulo1Parte2 rev. 9
5
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Selección de un bit Para especificar un bit en particular de un registro, se coloca primero el nombre del registro seguido del número de bit entre paréntesis. Ejemplo: Para especificar el bit 4 del registro R31: Se representaría así: R31(4) Ejemplo: Poner a 1 el bit 3 del registro SREG. Se representaría así: SREG(3) ← 1
Copia de un rango de bits El rango de bits se especifica con el nombre del registro seguido del rango entre paréntesis. El rango se especifica con dos números separados con “..”. Ejemplo: Copiar los bits 0, 1 y 2 del registro de nombre R1, a los bits 5, 6 y 7 de otro registro de nombre R2. Se representaría así: R2(5..7) ← R1(0..2) Esto significa que el bit 0 de R1 se copia en el bit 5 de R2, el bit 1 de R1 se copia en el bit 6 de R2 y el bit 2 de R1 se copia en el bit 7 de R2.
Registros concatenados A veces hay instrucciones que hacen uso de dos registros para formar un número de mayor longitud, y lo utilizan así en las operaciones. Para representarlos se coloca primero el nombre del registro que representará a los bits más significativos, luego el carácter “:” y a continuación el nombre del registro que representará a los bits menos significativos. Ejemplo: R24 y R25 son registros de 8 bits. Representarlos como un registro de 16 bits donde el byte más significativo será el contenido de R25. Se representaría así: R25:R24. Ejemplo: Copiar $4756 en R25:R24 Se representaría así: R25:R24 ← $4756 Esto significa que en R25 se copiará el valor $47 y en R24 el valor $56. Ejemplo: Incrementar en una unidad el contenido de R25:R24. Se representaría así: R25:R24 ← R25:R24 + 1
Capítulo1Parte2 rev. 9
6
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Ejercicio: El ATmega8 cuenta con 32 registros de 8 bits de propósito general, llamados R0..R31. A continuación se muestran las operaciones y codificación de dos instrucciones y su formato, tal y como aparecen en el manual de instrucciones del microcontrolador ATmega8. a) ¿Qué representa la “d” en Rd? Operación: Rd ← Rr Codificación de la instrucción: 0010 11rd dddd rrrr b) ¿ Qué representa K en la operación? Operación: Rd K Codificación de la instrucción: 1110 KKKK dddd KKKK
Capítulo1Parte2 rev. 9
7
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Lenguajes y herramientas de desarrollo (ensamblador, compiladores cruzados) Lenguaje Máquina (machine language) Un lenguaje escrito es un conjunto de símbolos y reglas cuyo objetivo es lograr la comunicación entre dos o más personas que conocen dichas reglas y símbolos. En el caso de un CPU, se denomina lenguaje máquina al conjunto de instrucciones que reconoce el CPU. En este caso, haciendo analogía con un lenguaje escrito, los símbolos serían los valores leídos de la memoria (números binarios) y las reglas: los formatos de las instrucciones, y que las instrucciones son leídas en secuencia. Es decir, en la instrucción misma ya están de manera implícita las reglas, por la definición de instrucción dada anteriormente. Las instrucciones en este lenguaje, están codificadas como números. Dado que cada fabricante diseña sus CPU´s de forma diferente, en general los lenguajes máquina para CPU´s diferentes serán diferentes. Código Máquin a (machi ne code) Es el conjunto de instrucciones (en lenguaje máquina) que conforman un programa.
Código máquina de una instrucción Es la representación binaria, o en general numérica, de una instrucción, es decir, la instrucción tal y como está almacenada en la memoria del computador. Ejemplo: Se muestra una porción de la tabla de instrucciones del ATmega8. nemonic Operands
ADC
Rd,Rr
ADD
Rd,Rr
Description
Add with Carry Add without Carry
Operation
Rd
←
Rd + Rr + C
Rd ← Rd + Rr
Flags
Cycles
Machine Coding
Z,C,N,V,H,S
1
0001 11rd dddd rrrr
Z,C,N,V,H,S
1
0000 11rd dddd rrrr
Notes
La columna de nombre “machine coding” muestra la codificación máquina de cada instrucción. la columna “operation” muestra la operación que efectúa la instrucción, con la nomenclatura mostrada anteriormente. En este par de instrucciones se representan a los registros R0 a R31 con 5 bits. El código máquina de la instrucción que efectúe la operación: R22 000011 1101100001
R22 + R17 sería:
←
Pues el registro R17 se representa con el número binario 10001 y el registro R22 con el número binario 10110. Se ha resaltado en negrita los bits que representan a R17 Lenguaje de ensamblaje (Assembly language) Debido a la dificultad que desde los inicios de las computadoras tuvieron los programadores para desarrollar programas directamente en lenguaje máquina, éstos comenzaron a ponerles Capítulo1Parte2 rev. 9
8
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
nombres cortos a las instrucciones del computador, que reflejaran la operación que efectuaba la instrucción. Estos nombres cortos eran abreviaturas en inglés (pues eran de habla inglesa los programadores), y cada programador creaba sus propios nombres nemotécnicos y sus propias reglas de cómo indicar los datos en cada instrucción. Los programadores escribían sus programas en papel usando estas abreviaturas o ayudas nemotécnicas, y luego los traducían manualmente al lenguaje máquina, es decir, los convertían a números que escribían en papel. Eran estos números los que luego introducían en la memoria del computador. De esa manera les era más fácil visualizar un programa, revisarlo, y depurarlo. No pasó mucho tiempo hasta que se decidió crear un lenguaje que unificara esos nemotécnicos y la manera de representar en papel los datos de las instrucciones, de manera que los programadores no tuviesen necesidad de inventar sus propias abreviaturas, y al mismo tiempo permitir que otros pudiesen leer los programas escritos por alguien. A este lenguaje se le llamó “lenguaje de ensamblaje”. Al mismo tiempo se creó un programa que se encargara de traducir el programa escrito en lenguaje de ensamblaje a lenguaje máquina. A este programa se le llamó “ensamblador”. El lenguaje de ensamblaje es un lenguaje que representa las instrucciones en lenguaje máquina del CPU de una manera simbólica, que se supone es más fácil de manejar por parte de un programador (lo cual es cierto, pero si sabe inglés). Siempre es el fabricante del microprocesador o microcontrolador el que define el lenguaje de ensamblaje, a excepción de las directivas, que pueden variar, y cuya definición se da en esta parte. Por eso, hay tantos lenguajes de ensamblaje como CPU’s hay en el mercado (sea como parte de un microcontrolador o microprocesador). Sus principales características son : •
•
• •
Existe una correspondencia biunívoca (para la mayor parte de las instrucciones) entre una instrucción escrita en lenguaje de ensamblaje y una instrucción en lenguaje máquina. Es decir, una instrucción en lenguaje de ensamblaje representa a una única instrucción en lenguaje máquina. Al igual que en los lenguajes de alto nivel (como PASCAL o C) los programas están formados por líneas de texto (líneas de instrucción). En una línea de texto se representa una única instrucción del CPU. Cada línea de instrucción está formada por uno o más de los siguientes campos: • campo de etiqueta (label field) • campo de nemónico (mnemonic field) • campo de operandos (operand field) • campo de comentarios (comment field)
Antes de explicar el contenido de estos campos, hay que definir dos términos: Etiqueta (label): Es una secuencia de caracteres (símbolo) al cual se le asocia un número.
Cuando ésta está en el campo de etiqueta, representa la dirección de inicio (número asociado a la etiqueta) de la instrucción que está en dicha línea, en caso de haber una instrucción en ésta.
Capítulo1Parte2 rev. 9
9
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Nemónico (mnemonic): es una palabra que representa la operación que realiza una
instrucción del CPU. Es el fabricante del microcontrolador el que define los nemónicos para las instrucciones del CPU. El campo de etiqueta está al comienzo de una línea de texto y en ella va una etiqueta. En el campo de nemónico , que sigue al campo de etiquetas, se escriben los nemónicos de las instrucciones. En el campo de operandos , que va luego del campo de nemónicos, se escriben los operandos, que son los valores utilizados por la instrucción del CPU. Se utilizan ciertas reglas para indicar el modo de direccionamiento involucrado. En el campo de comentarios puede haber cualquier texto que permita entender la función del programa, tanto por parte del programador como de cualquier otra persona que lea el programa. Los comentarios deben ser breves e indicar lo que hace cada porción de programa en relación con el algoritmo implementado. Es una mala práctica de programación colocar como comentario lo que el CPU hace en una instrucción, pues eso lo indica claramente el nemónico y operandos de la instrucción. Además de lo antes mencionado, para facilitar la programación, y en algunos casos para poder especificar sin ambigüedades un programa, este lenguaje cuenta con una serie de palabras (símbolos) llamados “directivas” (directives), las cuales no representan instrucciones del CPU, y que permiten especificar cosas como : dirección de inicio de un programa, si se desea generar un listado del programa, definir tablas de datos, etc. Los lenguajes de ensamblaje son diferentes para CPU´s diferentes pues, en general, tendrán registros a los que los fabricantes les ponen nombres diferentes y nemónicos diferentes. Incluso para un mismo CPU, pueden haber lenguajes de ensamblaje diferentes, pero lo serán sólo en las directivas, mas no en los nemónicos. En la primera figura se muestra un programa escrito en lenguaje de ensamblaje del ATmega8, y en la siguiente figura se muestra, para comparación, un programa escrito en lenguaje de ensamblaje del 68HC11. En ambas se indican sus diferentes partes. Como se puede apreciar, casi todo es diferente. Ese es un inconveniente de la programación en lenguaje de ensamblaje: hay que aprender uno por cada familia de microcontroladores que se desee utilizar.
Capítulo1Parte2 rev. 9
10
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
EJEMPLO DE PROGRAMA comentarios ; PROGRAMA QUE COPIA UN BLOQUE DE 30 DATOS DE 8 BITS ; DE LA DIRECCION $60 A LA DIRECCIÓN $100 ; EL PROGRAMA COMIENZA EN LA DIRECCIÓN $0000 directivas
.INCLUDE "m8def.inc"
.CSEG
nemonico
etiquetas
INICIO: LDI LDI LDI LDI LDI SIGUE: LD ST DEC BRNE FIN: JMP
.ORG 0 R17, 30 R29, 1 R28, 0 R27, 0 R26, $60 R16, X+ Y+, R16 R17 SIGUE FIN
; R17 se usa como contador ; R29 R28 son registro Y ; Se hace Y=$100, inicio del destino ; R27 R26 son registro X ; Se hace X = $60 inicio de datos ; se lee el dato y se incrementa X ; se copia el dato y se incrementa Y ; Si no se copiaron todos, seguir copiando ; Si.
comentario operandos
EJEMPLO DE PROGRAMA comentarios
directivas
nemonico
* * * * * *
PROGRAMA QUE COPIA UN BLOQUE DE 30 DATOS DE 8 BITS DE DIRECCION $CD00 A LA DIRECCION $D000 EL PROGRAMA COMIENZA EN DIRECION $C000 ESTE PROGRAMA CORRIGE EL ERROR DE EJM1A.ASM OPT
HC11
ORG
$C000
INICIO LDX
etiquetas
directiva
Capítulo1Parte2 rev. 9
#$CD00
LDY #$D000 LDAB #30 SIGUE LDAA 0,X STAA 0,Y INX INY DECB BNE SIGUE FIN END
* EL AS68 REQUIERE ESTA LINEA!
operando
; X = puntero a bloque fuente ; Y = puntero a bloque destino ; B = contador
comentario
; X apunta a siguiente dato fuente ; Y con nueva direccion destino ; se copiaron todos los datos?
11
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Compilador (compiler) Es un programa que recibe como entrada un archivo que tiene un programa escrito en un lenguaje, y genera como resultado un archivo con el mismo programa pero escrito en otro lenguaje. Ensamblador (assembler) Es un compilador (programa) que acepta como entrada un archivo que tiene un programa escrito en lenguaje de ensamblaje, y genera como salida un archivo con el código máquina del programa. Ensamblador cr uzado (cros s-assembler) Es un ensamblador que se ejecuta en un computador basado en cierto microprocesador o microcontrolador, y genera código máquina para un microprocesador o microcontrolador diferente al del computador. También se denomina así a los ensambladores que se ejecutan en un computador basado en cierto microprocesador y generan código para computadoras de diferente arquitectura pero basadas en el mismo microprocesador. Por ejemplo, el AS68 es un ensamblador cruzado, que se ejecuta en un computador compatible IBM, pero genera código máquina para el microcontrolador 68HC11. El AVR Assembler 2.0 de Atmel, es también un ensamblador cruzado; se ejecuta en un computador compatible IBM, pero genera código máquina para microcontroladores de la familia AVR, como el ATmega8, ATmega32, AT90S8535, etc. Compilador cru zado de C (C cro ss-comp iler) Es un compilador de lenguaje C que se ejecuta en un computador, y genera código máquina para un computador diferente. La diferencia puede ser en el tipo de procesador, microcontrolador o microprocesador que emplee la computadora, o de contar con el mismo procesador, en la arquitectura del computador. Por ejemplo, el Ht-6811 es un compilador cruzado de C. Es un programa que se ejecuta en una computadora personal (IBM compatible) y genera código máquina para cualquier computador basado en el 68HC11. El programa "CodeVision AVR C Compiler" es un entorno de desarrollo para la familia de microcontroladores AVR8 de Atmel, y cuenta con un compilador cruzado de C para dicha familia de microcontroladores (existe una versión reducida, gratuita de dicho programa). La gran diferencia entre un compilador cruzado y otro que no lo es, estriba en que el primero genera código independientemente de la arquitectura del computador en el que se ejecutará dicho código. Los compiladores usados en las computadoras personales (por ejemplo Borland C, ó DevC++, ó Visual CPP) son compiladores que generan archivos que se ejecutan sobre un sistema operativo determinado, por ejemplo DOS o Windows XP, y los programas ejecutables que generan no pueden ser utilizados sobre cualquier otro sistema operativo que no sea compatible con los mencionados.
Capítulo1Parte2 rev. 9
12
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Tipos de instrucciones, ejecución de instrucciones Tipos de Instrucciones El microcontrolador ATmega8 cuenta con los siguiente tipos de instrucciones •
•
•
•
•
•
•
Instrucciones de transferencia de datos : Permiten copiar el contenido de un registro
del CPU a otro registro (del CPU, de memoria de datos, de memoria de programa, o de una interface de entrada/salida) o viceversa. Instrucciones aritméticas : Permiten efectuar operaciones de suma, resta y multiplicación con los registros del CPU. Instrucciones lógicas : Para efectuar operaciones lógicas bit a bit (O, O exclusivo, Y, complemento a 1). Instrucciones de rotación y desplazamiento : Para cambiar de posición los bits de un registro del CPU (por ejemplo, desplazarlos un bit a la derecha, a la izquierda) Instrucciones de Entrada/Salida (E/S) : Para poder manejar los registros de Entrada/Salida del microcontrolador. La mayoría de dichos registros son para el manejo de las interfases de entrada salida con que cuenta el microcontrolador. Instrucciones de manejo de bits : Permiten analizar el estado de un bit en particular de un registro del CPU, o ponerlo a 1 ó a 0. Instrucciones de control de flujo de programa : Estas instrucciones permiten que el programa no siga la orden normal de ejecución de instrucciones que es secuencial. Hay dos tipos de instrucciones: • instrucciones de salto : Permiten al CPU continuar la ejecución del programa a partir de la dirección indicada en el campo de referencia de operando de la instrucción de salto. Estas instrucciones permiten implementar las estructuras condicionales de los lenguajes de alto nivel (if-else, while, repeat, for, etc.) • Instrucciones de llamada y retorno de subrutinas : Permiten al CPU ejecutar un bloque de instrucciones (subrutina) y luego retomar la ejecución del programa a partir del punto donde se quedó. Estas instrucciones permiten implementar las funciones de los lenguajes de alto nivel. Instrucciones de control : Estas instrucciones permiten controlar algunas • características del microcontrolador. Por ejemplo, hacer que entre a un modo de ahorro de energía.
Pasos en la ejecución de una ins trucci ón En general, se suelen distinguir dos fases en la ejecución de una instrucción: ♦ Búsqueda del código de operación, también llamado ciclo de captación, o Ciclo fetch ( opcode fetch) ♦ Decodificación/ejecución La primera fase consiste en la lectura del código de operación y su grabación en un registro especial, denominado comúnmente registro de instrucciones (IR, instruction register). La segunda consiste en la lectura y procesamiento de las demás palabras de la instrucción (si las hubiera), lectura de datos, procesamiento de éstos, y grabación del resultado.
Capítulo1Parte2 rev. 9
13
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
El CPU siempre comienza la ejecución de una instrucción con la búsqueda del código de operación, luego realiza la decodificación y ejecución de ésta. A continuación, efectúa un nuevo ciclo de búsqueda de código de operación, repitiéndose el ciclo.
INICIO
Capturar siguiente instrucción
Ejecutar Instrucción
PARADA
Fig. 1 Ejecución de instrucciones
Ejecución de instrucciones El CPU para poder ejecutar las instrucciones de manera secuencial tiene que saber en todo momento en qué registro de la memoria está la siguiente instrucción a ejecutar. Para ello cuenta con un registro especial denominado contador de programa (program counter) y que suele tener el nombre abreviado PC, el cual tiene almacenada la dirección del registro de la memoria de programa que contiene la siguiente instrucción a ejecutar. Cada vez que el CPU capta una instrucción, incrementa dicho contador, de manera que al finalizar la ejecución de la instrucción actual, capte la siguiente instrucción de la dirección de memoria inmediata superior. Para poder ejecutar una instrucción primero tiene que leerla de la memoria de programa y almacenarla temporalmente dentro del CPU para decodificarla, para lo cual internamente cuenta con un registro denominado registro de instrucciones (instruction register) y que suele tener el nombre IR. Además de estos registros, tiene los registros de propósito general (general purpose registers), cuyos contenidos son utilizados como operandos en la mayoría de instrucciones con que cuenta el CPU. Antiguamente los CPU’s contaban con uno o dos de estos registros, a los cuales se les denominaba “acumuladores”. En la figura se muestra un diagrama simplificado del microcontrolador Atmega8, en el que, por simplicidad, no se muestran las interfaces de entrada/salida.
Capítulo1Parte2 rev. 9
14
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
En la figura se muestra que: • El microcontrolador cuenta con 1KB de memoria RAM estática, 8KB de memoria de programa, en un arreglo de 4Kx16, y 512 bytes de memoria EEPROM. • El microcontrolador cuenta con 32 registros de propósito general, y se puede seleccionar el contenido de uno o dos de ellos para efectuar operaciones con el ALU. • Las salidas del contador de programa, PC, están conectadas a las líneas de direcciones de la memoria de programa. • Algunas salidas del registro de instrucciones IR, pueden conectarse a las líneas de direcciones de la memoria de datos. • Es posible utilizar las salidas de dos registros de propósito general como direcciones de la memoria de datos. • Las líneas de control, que son salidas del decodificador de instrucciones, son las que permiten: o leer o escribir en la memoria SRAM o leer la memoria de programa o grabar un valor en uno de los registros de propósito general, o en el registro IR o seleccionar la operación matématica en el ALU, y el registro en el que se grabará el resultado de la operación o seleccionar si un par de registros de propósito general se utilizará para seleccionar el registro de la memoria SRAM, o si se utilizarán los bits del registro IR. Estas características determinan que: • El valor a grabar en el registro IR, quede determinado por el contenido del contador de programa. Pues el contenido del registro PC indica la dirección de memoria que se leerá, y por tanto, la instrucción que leerá. Capítulo1Parte2 rev. 9
15
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú •
•
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Si se va a leer un registro de la memoria de datos, la dirección está determinada por un grupo de bits del registro IR, o por un par de registros de propósito general. Las señales de control que van a las líneas de control de las memorias, registros y el ALU son generadas por el decodificador de instrucciones.
A continuación se muestra un ejemplo de programa, grabado en la memoria Flash a partir de la dirección $000, que efectúa la suma de los contenidos de los registros R0, R1 y R2 almacenando el resultado en R16. Se muestra, al lado izquierdo, la operación que efectúa cada instrucción. El programa consta de cuatro instrucciones, cada una ocupando un registro de la memoria Flash. Los demás registros de la memoria Flash no han sido grabados y por tanto están en blanco. 1 Oper aci ón
di r ecci ón $000 $001 $003 $004 $005
R16 ← R0 R16 ← R16 +R1 R16 ← R16 + R2 PC ← PC-1
...
$FFF
Memor i a Fl ash $2D00 $0D01 $0D02 $CFFF $FFFF ...
$FFFF
Cómo ejecuta el microcontrolador el programa Como se indicó en la sección anterior, la ejecución de cada instrucción consta de dos etapas: captación y decodificación/ejecución. Ciclo de captación:
Se efectúa la lectura de la instrucción, cuya dirección está indicada por el contenido del contador de programa, y se incrementa el contador de programa, para que apunte a la siguiente instrucción a ejecutar. 1. IR ← (PC) 2. PC ← PC+1 Ciclo de ejecución:
En el ciclo de ejecución efectúa las operaciones mostradas en la figura de arriba para cada una de las instrucciones. Visto en secuencia, el CPU efectúa las operaciones indicadas en la siguiente tabla, en la que se muestra en la segunda columna la operación que se efectúa, y en las dos columnas siguientes los nuevos valores que se graban en el contador de programa PC, y en el registro de instrucciones IR. Inicialmente el contador de programa tiene el valor $000.
1
Se dice que una memoria Flash está en blanco cuando ha sido borrada eléctricamente o es nueva y no se le ha grabado nada aún. Una memoria Flash en blanco tiene almacenado en todas sus celdas de memoria el valor 1. Por tanto, una memoria Flash de 16 bits si está en blanco tendrá almacenado en todos sus registros el valor $FFFF. Esto también se aplica a las memorias EPROM y EEPROM. Capítulo1Parte2 rev. 9
16
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú Paso 1 2 3 4 5 6 7 8 9 10
IR ← (PC) PC ← PC+1 R16 ← R0 IR ← (PC) PC ← PC+1 R16 ← R16 + R1 IR ← (PC) PC ← PC+1 R16 ← R16 + R2 IR ← (PC) PC ← PC+1 PC ← PC -1 IR ← (PC) PC ← PC+1 PC ← PC -1 ...
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
PC
IR
Descripción
0 1
$2D00
ciclo fetch
$0D01
ejecución primera instrucción ciclo fetch
$0D02
ejecución segunda instrucción ciclo fetch
$CFFF
ejecución tercera instrucción ciclo fetch
$CFFF
ejecución cuarta instrucción ciclo fetch
2 3 4 3 4 3
ejecución cuarta instrucción ...
Puede observarse que: • El ciclo fetch siempre es el mismo, independiente de la instrucción a ejecutar. • A pesar de ser el mismo, se lee la instrucción que está en la dirección siguiente de memoria, pues el contador de programa PC se incrementó. • Una vez ejecutadas las primeras tres instrucciones, el CPU se queda ejecutando repetidamente, y por siempre, la cuarta instrucción. Ello debido a la particularidad de dicha instrucción: observar que decrementa en una unidad el contenido del contador de programa, y con ello, vuelve a tener la dirección de la cuarta instrucción. La última instrucción es un ejemplo de instrucción de salto, y ha permitido que el CPU no ejecute la instrucción que está a continuación (dirección $005).
Capítulo1Parte2 rev. 9
17
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Computador hipotético Para mostrar la secuencia que sigue un CPU para ejecutar las instrucciones, se va a considerar un computador hipotético con arquitectura Harvard, el cual consta de un CPU hipotético de 8 bits que puede direccionar 512 registros de memoria de datos (RAM) y 1024 registros de memoria de programa. Las instrucciones son de 12 bits, y por tanto, los registros de la memoria de programa también son de 12 bits. Cuenta con los siguientes registros: • PC Contador de programa de 10 bits • IR Registro de instrucciones de 12 bits • R0 acumulador de 8 bits • R1 acumulador de 8 bits • MAR Registro de almacenamiento temporal de 9 bits el cual almacena la dirección del registro de la memoria de datos que se quiere acceder. En la figura se muestra un diagrama simplificado de este computador hipotético con los registros mencionados, la memoria de programa y la memoria de datos.
En la figura se intenta mostrar lo siguiente: • Las salidas del contador de programa, PC, van conectadas a las líneas de direcciones de la memoria de programa. • Las salidas del registro MAR van conectadas a las líneas de direcciones de la memoria SRAM (memoria de datos). • Las líneas de datos de la memoria de programa van conectadas a las entradas del registro IR. • Algunas salidas del registro IR van conectadas a las entradas del registro MAR. • Sólo se han conetado los registros R0 y R1 al ALU. • Las líneas de control, que son salidas del decodificador de instrucciones, son las que permiten: leer o escribir en la memoria SRAM, leer la memoria de programa, grabar
Capítulo1Parte2 rev. 9
18
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
•
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
un valor en los registros R0, R1, MAR, seleccionar la operación matématica en el ALU. No se muestra la señal de reloj, pero ésta llega a todos los registros, pues el CPU es un circuito síncrono.
Estas características determinan que: • El valor a grabar en el registro IR, quede determinado por el contenido del contador de programa. Pues el contenido del registro PC indica la dirección de memoria que se leerá, y por tanto, la instrucción que leerá. • Si se va a leer un registro de la memoria de datos, dicho registro será el que tenga una dirección numéricamente igual al contenido del registro MAR. • Que ciertos bits del registro IR puedan grabarse en el registro MAR permite implementar instrucciones que lean o escriban en la memoria de datos. • En este CPU hipotético sólo se pueden efectuar operaciones aritméticas con los contenidos de los registros R0 y R1. Por tanto, para efectuar cualquier operación matemática, necesariamente deben copiarse antes los valores en estos registros. • Las señales de control que van a las líneas de control de las memorias, registros y el ALU son generadas por el decodificador de instrucciones, Consideremos además que este CPU hipotético reconoce tres instrucciones, cuya operación y codificación en binario se muestra en la tabla, donde se ha resaltado en negrita el código de operación de cada instrucción. Instrucción
Nombre abreviado Copiar en un acumulador COPA el contenido de un registro de la memoria de datos
Operación
Descripción de operandos
Codificación binaria
Ri ← (K)
K: dirección del registro de la memoria de datos a leer (9 bits) Ri: uno de los registros R0 ó R1
10i
Sumar contenido de R0 y R1 y almacenar resultado en R0 Copiar en un registro de la memoria de datos el contenido de un acumulador
SUMA
R0 ← R0+R1
COPM
(K) ← Ri
k kkkk kkkk
i=0, registro R0 i=1 registro R1 k..k: la dirección 0100 0000 0000
K: dirección del registro de la memoria de datos a leer (9 bits) Ri: uno de los registros R0 ó R1
11i
k kkkk kkkk
i=0, registro R0 i=1 registro R1 k..k: la dirección
Por ejemplo, si se quiere copiar el contenido de la dirección $21 (0b000100001) en el registro R1, debe emplearse la primera instrucción codificada en binario así: 1010 0010 0001
Pasos en la ejecución de cada instrucción: Usando la nomenclatura previamente vista, y del diagrama simplificado, se muestra la secuencia de pasos que ejecutaría el CPU internamente, para ejecutar cada instrucción. Cada paso, por simplicidad, asumiremos que toma un ciclo de reloj.
Capítulo1Parte2 rev. 9
19
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
Ciclo de captación: El ciclo de captación consiste en la lectura de la instrucción, y el incremento del contador de programa, para que apunte a la próxima instrucción a ejecutar. Este ciclo es el mismo para cualquier instrucción.
1. IR ← (PC) 2. PC ← PC +1 Ciclo de ejecución de la instrucción: La ejecución es diferente para cada instrucción. Se muestran la secuencia para cada instrucción. Instrucción: COPA, con registro R0
1. MAR ← IR[0..8] 2. R0 ← (MAR) Instrucción COPA, con registro R1
1. MAR ← IR[0..8] 2. R1 ← (MAR) Instrucción: SUMA
1. R0 ← R0 + R1 Instrucción COPM, con R0
1. MAR ← IR[0..8] 2. (MAR) ← R0 Instrucción COPM, con R1
1. MAR ← IR[0..8] 2. (MAR) ← R0
Ejemplo Se quiere hacer un programa para el computador hipotético que sume dos números de 8 bits contenidos en las direcciones $37 y $38 de la memoria de datos. El resultado debe almacenarce en la dirección $40. El programa debe comenzar en la dirección $000. Una solución, utilizando las instrucciones de la tabla es: 1. Copiar en R0 el contenido de la dirección $37 2. Copiar en R1 el contenido de la dirección $38 3. Sumar R0 y R1 y guardar resultado en R0 Capítulo1Parte2 rev. 9
20
21/03/2006
Curso: Sistemas Digitales Especialidad: Ing. Electrónica Pontificia Universidad Católica del Perú
Profesor: Ing. Hugo Pratt Área de circuitos y sistemas
4. Copiar R0 en dirección $40. Utilizando la representación abreviada: 1. R0 ← ($37) 2. R1 ← ($38) 3. R0 ← R0 + R1 4. ($40) ← R0 Como el programa debe comenzar en la dirección $000, la primera instrucción debe grabarse en la dirección $000 de la memoria de programa, la segunda en la dirección 1, y así sucesivamente. En la tabla se muestran las instrucciones Operación R0 ← ($37) R1 ← ($38) R0 ← R0 + R1 ($40) ← R0
Capítulo1Parte2 rev. 9
dirección de memoria de programa $000 $001 $002 $003
contenido de la memoria (binario) 1000 0011 0111 1010 0011 1000 0100 0000 0000 1100 1000 0000
21
21/03/2006