Descargar

Programación en lenguaje ensamblador

Enviado por Pablo Turmero


    edu.red 1 Programación a nivel de máquina Lenguaje Ensamblador Introducción: Para dar ordenes al hardware una computadora, debes hablar su idioma. Las palabras de un lenguaje de máquina se llaman instrucciones y su vocabulario se llama conjunto de instrucciones de la arquitectura (ISA). En este capitulo se aprenderá el diseño y uso de un conjunto de instrucciones de una máquina real, en la forma escrita por las personas y en la forma que la maquina “entiende”.

    edu.red 2 El modelo de ejecución Estado Visible por el programador: PC: Contador de programadirección de la próxima instrucción Banco de Registros: -Fuertemente usado por los datos de programa. Códigos de condición -Almacena información de estado de las operaciones realizadas recientemente. Memoria: -Arreglo accesible por bytes Código, datos de usuario, datos de S.O. -Pila (Stack): memoria utilizada para soportar procedimientos

    edu.red 3 Convirtiendo código C a código objeto Código: archivos de texto Compila con el comando: -gcc p1.c, p2.c -o p.exe Optimizaciones: – O -O0: -O1: -O2: Enlace (Link) -Enlaza programas p1.o, p2.o con librerías estáticas. Salida (-o p.exe) -Pone el programa binario en el archivo p.exe .

    edu.red Características del lenguaje ensamblador SubTipos de datos reducido: Datos de enteros de 1, 2 ó 4 bytes Valores de datos Direcciones (apuntadores sin tipo) Datos de Punto Flotante 4, 8 ó 16 bytes No agrega tipos como arreglos o estructuras Asigna bytes en direcciones contiguas de memoria ¡El programador tiene el control total de la máquina! 4

    edu.red 5 Características del lenguaje ensamblador SubOperaciones primarias: Realiza funciones aritméticas sobre valores almacenados en registros o sobre valores almacenados en memoria. ADD, SUB, MUL, etc. Transfiere datos entre registros y memoria Carga datos de memoria a registros (LOAD) Almacena datos de registros en Memoria (STORE) Transfiere el control del programa Saltos incondicionales hacia/desde procedimientos Saltos condicionales

    edu.red Conjunto de instrucciones de la arquitectura Cuando se diseñaron los primeros procesadores, una manera de diseño consistía en agregar mas y mas instrucciones a los CPU’s para elaborar tareas complicadas Por ejemplo, la arquitectura de una VAX tiene instrucciones inclusive para multiplicar polinomios Por otro lado, la filosofía de las computadoras RISC (Cocke IBM, Patterson, Hennessy, 1980’s-Reduced Instruction Set Computing) que tienen un Conjunto Reducido de Instrucciones para Cálculo tienen las siguientes características: Mantiene el conjunto de instrucciones pequeño y sencillo, de manera que se hace fácil el diseño de hardware rápido Se le deja al software realizar operaciones complicadas por medio de la composición de instrucciones simples

    edu.red Arquitectura del MIPS El procesador MIPS fue una de las primeras arquitecturas que estaban disponibles comercialmente ¿Por qué estudiar el MIPS en vez del procesador Intel x86? MIPS es simple y elegante. No es necesario entrar con tanto detalle con instrucciones que posiblemente ni siquiera se utilicen nunca MIPS es ampliamente utilizado en dispositivos embebidos, los x86son poco utilizados en sistemas embebidos, y existen más computadoras embebidas

    edu.red Registros (1/4) A diferencias de los lenguajes de alto nivel como C o Java, el lenguaje ensamblador no utiliza variables ¿Por qué no? Esto hace que el hardware sea simple Los operadores ensamblados son registros Hay un número limitado de localidades especiales que son construidas directamente en hardware Las operaciones sólo se pueden realizar en estos registros Beneficios: Debido a que los registros se encuentran directamente en hardware, son muy rápidos

    edu.red Registros (2/4) Desventajas: Debido a que los registros se encuentran en hardware, hay un número predeterminado de ellos Hay una solución: El código del MIPS debe ser cuidadosamente programado para un uso eficiente de registros Existen 32 registros en el MIPS ¿Por qué 32? Mientras más pequeño más rápido A su vez, cada registro del MIPS tiene un ancho de 32 bits Grupos de 32 bits es llamado palabra en el MIPS

    edu.red Registros (3/4) Los registros son numerados del 0 al 31 Cada registro puede ser referido por su número o por su nombre Por ejemplo, referencias numéricas: $0, $1, $2, …, $30, $31

    edu.red Registros (4/4) Por conveniencia, cada registro tiene un nombre para hacerlo fácil de codificar y recordar Por ahora para nosotros: $16 A $ 23 equivalen a los registros $s0 a $s7 ( y que corresponde a variables en C) $8 A $15 equivalen a $t0 a $t7 (que corresponden a variables temporales) Posteriormente veremos los nombres de los otros registros En general, se utilizan nombres para que el código sea más entendible

    edu.red Variables en C y Java vs. registros En C (y la mayoría de los lenguajes de alto nivel) las variables se declaran al principio y se les asigna un tipo Ejemplo: int fahr, celsius; char a, b, c, d e; Cada variable puede SÓLO representar un valor del tipo con el que fue declarado (no se puede mezclar y empatar las variables int y char) En lenguaje ensamblador, los registros no tienen tipo; el tipo de operación determina como el contenido de los registros es tratado

    edu.red Comentarios sobre lenguaje ensamblador Otra forma de hacer que el código ensamblador sea más entendible es utilizar comentarios El símbolo de gato (hash) # es utilizado por MIPS para realizar comentarios Cualquier expresión después de # hasta el fin de esa línea es un comentarios y será ignorado Esto es igual que si se utilizará en C99 el símbolo // Nota: Diferencias respecto a C C también tiene el formato /* … */ para realizar comentarios De forma que se pueden incluir varias líneas

    edu.red Instrucciones en ensamblador En lenguaje ensamblador cualquier expresión (llamada instrucción), ejecuta exactamente un comando de una lista corta de éstos. A diferencia de C (y la mayoría de los lenguajes de alto nivel), cada línea de código ensamblado contiene al menos 1 instrucción Las instrucciones están relacionadas con las operaciones (=, +, -, ?, /) en C o en Java Veamos ahora algunos ejemplos para MIPS

    edu.red Suma y resta en el MIPS (1/4) Sintaxis de las instrucciones: 1 2, 3, 4 Donde: nombre de la operación operando donde se obtiene el resultado (“destino”) 1er operando de la operación (“fuente 1”) 2do operando de la operación (fuente 2”) La sintaxis es rígida: i.e. 1 operador, 3 operandos ¿Por qué? Mantiene al hardware simple debido a la regularidad

    edu.red Suma y resta en el MIPS (2/4) Suma en ensamblador Ejemplo: add $s0, $s1, $s2 (en MIPS) Equivale a: a = b + c (en C) Donde los registros del MIPS $s0, $s1 y $s2 están asociados a C con las variables a, b y c respectivamente Resta en ensamblador Ejemplo: sub $s3, $s4, $s5 (en MIPS) Equivale a: d = e – f ( en C) Donde los registros del MIPS $s3, $s4 y $s5 están asociados a C con las variables d, e y f respectivamente

    edu.red Suma y resta en el MIPS (3/4) ¿Cómo se implementa la siguiente instrucción de C a MIPS? a = b +c + d – e; La instrucción se divide en múltiples instrucciones add $t0, $s1, $s2 # temp = b + c add $t0, $t0, $s3 # temp = temp + d add $s0, $st0, $s4 # a = temp – e Hay que notar que una sóla línea en C puede dividirse en varias instrucciones en MIPS Además, todo aquello después del # en cada línea es ignorado

    edu.red Suma y resta en el MIPS (4/4) ¿Cómo se implementa la siguiente instrucción? f = (g + h) – (i + j); Se utilizan registros intermedios add $t0, $s1, $s2 # temp = g + h add $t1, $s3, $s4 # temp = i + j sub $s0, $t0, $t1 # f = (g + h) – (i + j)

    edu.red Registro cero Un valor inmediato particular, el número cero (0), aparece en MIPS constantemente De manera que se ha definido un registro cero ($0 o $zero) y que siempre tiene el valor 0; e.g. add $s0, $s1, $zero (en MIPS) f = g (en C) Donde los registros del MIPS $s0 y $s1 están asociados a C con las variables f y g De acuerdo con la definición anterior, la instrucción: add $zero, $zero, $0 No realizaría nada

    edu.red Valores inmediatos (1/3) Los valores inmediatos son constantes numéricas Aparecen constantemente en el código para los MIPS, de manera que son instrucciones especiales Suma inmediata: addi $s0, $s1, 10 (en MIPS) f = g + 10; (en C) Donde los registros del MIPS $s0 y $s1 están asociados a C con las variables f y g La sintaxis es similar a la instrucción add, excepto que el último argumento es un número en vez de un registro

    edu.red Valores inmediatos (2/3) No existe una instrucción de resta inmediata en MIPS: ¿Por qué? Existe un límite en el número de operaciones que pueden ser implementadas físicamente con el propósito de mantener un conjunto de instrucciones mínimo, además se ahorra en área de silicio Si la instrucción puede ser descompuesta e implementada por otras operaciones que ya existen, entonces este tipo de instrucción (posiblemente subi) no se incluye addi ., ., -X = subi ., ., X ? de manera que no existe subi

    edu.red Valores inmediatos (3/3) addi $s0, $s1, -10 (en MIPS) f = g – 10; (en C) Donde los registros del MIPS $s0 y $s1 están asociados a C con las variables f y g

    edu.red Trivia Los tipos están asociados con declaration en C (normalmente), pero están asociados con instrucciones (operadores) en MIPS Debido a que hay solamente 8 registros locales ($s0-$s7) y 8 registros variables temporales ($t0-$t7), no podemos escribir en MIPS expresiones de lenguaje C que contengan más de 16 variables Si p (almacenado en $s0) fuera un apuntador a un arreglo de enteros (ints), entonces p++; pudiera ser implementado con la instrucción en MIPS: addi $s0, $s0, 1

    edu.red Resumen En el lenguaje ensamblador en MIPS: Los registros reemplazan a las variables en C Se tiene una instrucción (simple operación) por línea Simple es mejor Más pequeño es más rápido Instrucciones nuevas vistas: add, addi, sub Nuevos registros Variables en C: $s0 – $s7 Variables temporales: $t0 – $t7 Cero: $0 ó $zero

    edu.red MIPS: lectura y almacenamiento, decisión

    edu.red Ensamble de operandos: Memoria Las variables en lenguaje C se mapean hacía registros; ¿Qué sucederá con estructuras de datos grandes como los arreglos? En 1 de los 5 componentes principales de la computadora en este caso la memoria, contiene tales estructuras de datos Sin embargo en el caso de los MIPS las instrucciones aritméticas sólo operan sobre registros, nunca directamente sobre la memoria Las instrucciones de transferencia de datos se realiza entre registros y memoria: De memoria a registros De registros a memoria

    edu.red Anatomía: los 5 componentes de cualquier computadora PC Procesador Computadora Control (“cerebro”) Pagtrón de datos Registros Memoria Despositivos Entrada Salida (Gp:) Carga (desde) (Gp:) Almacenamiento (hacía)

    edu.red Los registros se encuentran en el camino de datos del procesador; si los operandos se encuentran en memoria, se deben de transferir los datos para que el procesador opere sobre ellos, y entonces se vuelve a realizar la transferencia de nuevo a memoria A continuación se presentan las instrucciones para transferencia de datos

    edu.red Transferencia de datos: memoria a registros (1/4) Para transferir palabras a datos se necesita especificar dos cosas: Registros: se especifican por medio de ($0-$31) o con un nombre simbólico Dirección de memoria: es más difícil de indicar Hay que pensar en la memoria como un arreglo de una sóla dimensión, de manera que se pueda direccionar de manera sencilla por medio de un apuntador a una dirección de memoria En otras ocasiones, se debe de ser capaz de realizar un desplazamiento (offset) a partir de este apuntador Recordar: “leer (cargar) desde la memoria”

    edu.red Transferencia de datos: memoria a registros (2/4) Para especificar a una dirección de memoria para copiar datos; se especifican dos valores: Un registro que contenga un apuntador a memoria Una desplazamiento (en bytes) La dirección de memoria deseada es la suma de estos dos valores Ejemplo: 8($t0) Especifica la dirección de memoria a la que se apunta a partir de valor en $t0, más 8 bytes

    edu.red Transferencia de datos: memoria a registros (3/4) Sintaxis para la instrucción de lectura 1 2, 3(4) Donde Es el nombre de la operación Registro que recibirá el valor Corrimiento numérico en bytes Registro que contiene el apuntador a memoria Nombre de la instrucción para el MIPS: lw (significa “load word” (carga de palabra), de manera que se cargan 32 bits o una palabra a la vez)

    edu.red Transferencia de datos: memoria a registros (4/4) Ejemplo: lw $t0, 12($s0) Esta instrucción tomará el apuntador en $s0, se le sumarán los 12 bytes, y se cargará el valor el valor de la localidad de memoria a la que se apunta hacía el registro $t0 Notas: $s0 Es llamado registro base El valor 12 será llamado corrimiento El corrimiento se utiliza generalmente para accesar elementos del arreglo o de la estructura: el registro base apunta al comienzo del arreglo o de la estructura (hay que notar el corrimiento debe de ser una constante conocida al momento de que se ensambla el programa) Flujo de Datos

    edu.red Transferencia de datos: registro a memoria (1/2) También se desea almacenar desde un registro hacía una localidad de memoria La sintaxis de la instrucción de escritura (almacenamiento) es idéntica a la de lectura Nombre de la instrucción para el MIPS: sw (que significa “store word” (almacenar palabra), de manera que 32 bits o una palabra se almacena a a la vez

    edu.red Transferencia de datos: registro a memoria (2/2) Ejemplo: sw $t0, 12($s0) Esta instrucción tomará el apuntador en $s0, le sumará 12 desplazamientos (bytes), y almacenará el valor del registro $t0 hacía la dirección de memoria Hay que recordar: “Almacenar haciá la memoria” Flujo de Datos

    edu.red Apuntadores vs. valores Concepto clave: un registro puede tener cualquier valor de 32 bits. Ese valor puede ser (con signo) int, un unsigned int, un apuntador (a dirección de memoria), entre otros Si se escribe add $t2, $t1, $t0 entonces $t0 y $t1 lo mejor será que tengan valores a sumar Si se escribe lw $t2, 0($t0) entonces $t0 deberá tener un apuntador No hay que confundir los conceptos

    edu.red Direccionamiento: bytes vs. palabra Cada palabra en memoria tiene una dirección, que es similar a un índice en un arreglo: memoria[0], memoria[1], memoria[2], … Llamada la dirección de la palabra Las computadoras necesitan un acceso de 8 bits (bytes) así como a palabras (4 bytes por palabra) Actualmente la dirección de memoria de las máquinas como bytes (i.e., “direccionamiento por bytes”) es de 32 bits (4 bytes) direcciones por palabra diferida por 4 memoria[0], memoria[4], memoria[8], …

    edu.red Compilación con memoria ¿Qué valor de corrimiento en lw se debe de tener para seleccionar A[5] en C? El corrimiento será 4?5 = 20 para seleccionar A[5]: byte vs. Palabra Compilar a mano utilizando los registros: g = h + A[5]; g: $s1, h: $s2, $s3: Dirección base de A 1ra. Transferencia de memoria al registro: lw $t0, 20($s3) # $t0 obtiene A[5] Suma 20 a $s3 para seleccionar A[5], y colocar en $t0 A continuación añadirlo a h y colocarlo en g add $s1, $s2, $t0 # $s1 = h + A[5]

    edu.red Notas sobre la memoria Error: Al olvidar que una palabra secuencial direcciona en máquina con un direccionamiento de 1 byte no difiere de 1 Muchos programadores de lenguaje ensamblador han trabajado sobre errores hechos bajo el supuesto que la dirección de la siguiente palabra puede encontrarse incrementando la dirección de un registro en 1 byte en vez del tamaño de palabra en bytes Por lo tanto, hay que recordar que tanto para lw y sw la suma de la dirección base y el corrimiento debe de ser múltiplo de 4 (para que quede alineado con la palabra)

    edu.red Más notas sobre memoria: alineamiento MIPS requiere que todas las palabras comiencen en un byte de dirección que sea múltiplo de 4 bytes Llamado alineamiento: los datos deben caer en una dirección que sea múltiplo de su tamaño (Gp:) 0 1 2 3 (Gp:) Alineado (Gp:) No Alineado 0, 4, 8, or Chex Último dígito hex. de la dir. es: 1, 5, 9, or Dhex 2, 6, A, or Ehex 3, 7, B, or Fhex

    edu.red ESTA PRESENTACIÓN CONTIENE MAS DIAPOSITIVAS DISPONIBLES EN LA VERSIÓN DE DESCARGA