3. Instrucciones: lenguaje de la máquina Fundamentos de Computadores Ingeniería de Telecomunicación Raúl Durán Díaz Departamento de Automática Escuela Politécnica Superior Curso académico 2009 2010 Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 1 / 50 Contenidos 1 2 3 4 Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 2 / 50
Introducción Para manejar la máquina, hablamos su lenguaje. Las palabras son instrucciones. El vocabulario es el repertorio de instrucciones. Las instrucciones deben ser lo más sencillas que sea posible, pero... deben permitir cualquier operación, es decir, el repertorio debe ser completo. En la práctica, los repertorios de instrucciones de todas las máquinas se parecen. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 3 / 50 Concepto de programa almacenado La idea clave de von Neumann es representar las instrucciones mediante códigos numéricos, susceptibles de ser almacenados en memoria como cualquier otro tipo de dato. Nosotros no manejamos directamente los códigos numéricos, sino un mnemónico asociado a cada instrucción. Al conjunto de todos los mnemónicos lo llamamos lenguaje máquina. Existe un formato de instrucción, que nos permitirá traducir los códigos numéricos a lenguaje máquina y viceversa. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 4 / 50
Arquitectura MIPS Tipo RISC (reduced intruction set computer): esto significa mínimo número de instrucciones, todas muy simples. Dotado con 32 registros de propósito general y el contador de programa, todos ellos de 32 bits. Observación Limitar el número de registros es bueno para poder conseguir una elevada velocidad de operación en el hardware. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 5 / 50 Arquitectura MIPS Esta arquitectura es del tipo carga-almacenamiento: Sólo permite operaciones con valores en los registros. Interactúa con la memoria por medio de únicamente un par de instrucciones de carga (lectura de memoria a registro) y almacenamiento (escritura de registro a memoria). La memoria es como un gran vector, direccionable byte a byte. Lo normal es acceder en direcciones múltiplos del tamaño accedido. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 6 / 50
Excursus: acceso a memoria big endian El byte 0 está en la posición más alta. Usado en IBM 370, Sun SPARC, HP-PARISC, etc. 31 24 23 16 15 8 7 0 8 9 10 11 4 5 6 7 0 1 2 3 Direcciones altas Direcciones bajas Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 7 / 50 Excursus: acceso a memoria little endian El byte 0 está en la posición más baja. Usado en x86, Digital VAX, Digital Alpha, Digital Unix, etc. 31 24 23 16 15 8 7 0 11 10 9 8 7 6 5 4 3 2 1 0 Direcciones altas Direcciones bajas Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 8 / 50
Arquitectura MIPS: registros Los registros se nombran $0, $1,...,$31. Son casi de propósito general, excepto: el registro 1, llamado $at, reservado al ensamblador; los registros 26 27, llamados $k0 y $k1, reservados al kernel; los registros 28 31, reservados a ciertos punteros. El resto tiene un uso convenido, pero arbitrario. Al final, todos tienen un sinónimo. Veamos el siguiente cuadro. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 9 / 50 Nombres de los registros en MIPS Nombre Número Uso $zero 0 constante 0 $v0 $v1 2 3 resultados, evaluación de expresiones $a0 $a3 4 7 argumentos $t0 $t7 8 15 temporales $s0 $s7 16 23 preservados en llamadas $t8 $t9 24 25 temporales $gp 28 puntero global $sp 29 puntero de pila $fp 30 puntero de cuadro $ra 31 dirección de retorno Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 10 / 50
Instrucciones para operaciones aritméticas Cómo ensamblamos un código como éste? Ejemplo en C int i, j, f, g, h; f = (g + h) - (i + j); Podemos asignar las variables a registros y usar la instrucciones de suma y resta enteras: Lo mismo, ensamblado add $t0, $s3, $s4 add $t1, $s0, $s1 sub $s2, $t0, $t1 en donde las instrucciones de suma y resta significan: Regs[x] = Regs[y] ± Regs[z] Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 11 / 50 Instrucciones de acceso a memoria Ejemplo en C int g, h, A[100]; g = h + A[8]; Lo mismo, ensamblado lw $t0, 32($s2) add $s0, $t0, $s1 Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 12 / 50
Instrucciones de acceso a memoria Ejemplo en C int h, A[100]; A[4] = h + A[8]; A[4] += 5; Lo mismo, ensamblado lw $t0, 32($s1) add $t0, $t0, $s0 sw $t0, 16($s1) ; se puede eliminar addi $t0, $t0, 5 sw $t0, 16($s1) Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 13 / 50 Instrucciones de acceso a memoria Ejemplo en C int i, g, h, A[100]; g = h + A[i]; Lo mismo, ensamblado add $t0, $s0, $s0 add $t0, $t0, $t0 add $t0, $t0, $s3 lw $t1, 0($t0) add $s1, $s2, $t1 Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 14 / 50
Observaciones respecto a lo visto En un programa hay más variables que registros... pónganse en registros las variables más usadas. El direccionamiento tipo base + desplazamiento es útil para direccionar vectores y campos de estructuras. Los operandos de todas las instrucciones están siempre en registros. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 15 / 50 Instrucciones de desplazamiento lógico y aritmético Operación en C en ensamblador Shift left << sll $s1,$s2,d Shift right >> srl $s1,$s2,d AND bit a bit & and $s1,$s2,$s3 OR bit a bit or $s1,$s2,$s3 Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 16 / 50
Resumen de instrucciones básicas Instrucción Función add $r3, $r2, $r1 $r3 $r1 + $r2 sub $r3, $r2, $r1 $r3 $r1 - $r2 addi $r2, $r1, n $r2 $r1 + n lw $r2, n($r1) $r2 M[$r1 + n] sw $r1, n($r2) M[$r2 + n] $r1 sll $r1, $r2, d $r1 $r2 << d srl $r1, $r2, d $r1 $r2 >> d and $r1, $r2, $r3 $r1 $r2 & $r3 or $r1, $r2, $r3 $r1 $r2 $r3 Atención: El número n puede ser positivo o negativo. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 17 / 50 Tomando decisiones La gran potencia de la programación es la toma dinámica de decisiones: para ello introducimos los saltos condicionales. La idea es que la ejecución del código salte a una zona u otra en función del resultado de la comparación de dos registros. Las instrucciones básicas son beq $r1, $r2, Etiq1 ; Ir a Etiq1 si $r1 = $r2 bne $r1, $r2, Etiq2 ; Ir a Etiq2 si $r1 $r2 También existe el salto incondicional j Etiqueta ; salta a Etiqueta incondicionalmente. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 18 / 50
Ensamblamos una sentencia if-then-else Ejemplo en C int i, j, f, g, h; if (i == j) f = g + h; else f = g - h; Lo mismo, ensamblado bne $s0, $s1, Else add $s2, $s3, $s4 j Fin Else: sub $s2, $s3, $s4 Fin: Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 19 / 50 Ensamblamos un bucle Ejemplo en C int i, j, k, A[100]; while (A[i] == k) i = i + j; Lo mismo, ensamblado Bucle: add $t0, $s0, $s0 add $t0, $t0, $t0 add $t0, $t0, $s3 lw $t1, 0($t0) bne $t1, $s2, Fin add $s0, $s0, $s1 j Bucle Fin: Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 20 / 50
Más instrucciones de control de flujo Para comparar un menor que tenemos: slt $r3, $r1, $r2 $r3 recibe un 1 si $r1 < $r2 y un 0 en caso contrario. Tenemos también slti $r2, $r1, n $r2 recibe un 1 si $r1 < n y un 0 en caso contrario. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 21 / 50 Y otra instrucción de salto Tenemos una instrucción que nos permite saltar a una dirección variable, que esté contenida en un registro: jr $r1 La instrucción siguiente a ésta será la que resida en la dirección que está contenida en el registro $r1. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 22 / 50
Resumen de instrucciones de control de flujo Instrucción Función beq $r1, $r2, etiq ($r1 == $r2)? $PC $PC+etiq : bne $r1, $r2, etiq ($r1!= $r2)? $PC $PC+etiq : slt $r1, $r2, $r3 ($r2 < $r3)? $r1 1 : $r1 0 slti $r1, $r2, n ($r2 < n)? $r1 1 : $r1 0 j etiq $PC etiq jr $r1 $PC $r1 jal etiq $ra $PC+4; $PC etiq Atención: Como antes, el número n puede ser positivo o negativo. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 23 / 50 Las instrucciones se representan binariamente, usando bytes. En MIPS, todas las instrucciones tienen 4 bytes. Los 32 bits se reparten en campos, algunos de los cuales son fijos. De esta forma, la interpretación de la instrucción es más sencilla y uniforme. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 24 / 50
Para las instrucciones tipo R (varios registros involucrados): op code RS RT RD SHAMT FUNC 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits Significado de los campos op code: código de operación básica RS: registro fuente 1 RT: registro fuente 2 RD: registro destino SHAMT: shift amount FUNC: código de función concreta Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 25 / 50 Para las instrucciones tipo I (valores inmediatos involucrados): op code RS RT dirección 6 bits 5 bits 5 bits 16 bits Significado de los campos op code: código de operación básica RS: registro fuente RT: registro destino dirección: número de 16 bits (±32767) Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 26 / 50
Para las instrucciones tipo J (transferencia de control): op code dirección de salto 6 bits 26 bits op code: dirección de salto: Significado de los campos código de operación básica dirección de la siguiente instrucción a ejecutar Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 27 / 50 básicas Tipo Opcode RS RT RD SHAMT FUNC dir add R 0 reg reg reg 0 32 n/a sub R 0 reg reg reg 0 34 n/a addi I 8 reg reg n/a n/a n/a inm lw I 35 reg reg n/a n/a n/a dir sw I 43 reg reg n/a n/a n/a dir j J 2 n/a n/a n/a n/a n/a n/a Traducir el lenguaje ensamblador a código máquina es el papel del as (o programa ensamblador). Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 28 / 50
de control Tipo Opcode RS RT RD SHAMT FUNC dir beq I 4 reg reg n/a n/a n/a dir bne I 5 reg reg n/a n/a n/a dir slt R 0 reg reg reg 0 42 n/a jr R 0 reg 0 0 0 8 n/a jal J 3 n/a n/a n/a n/a n/a n/a Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 29 / 50 lógicas Tipo Opcode RS RT RD SHAMT FUNC dir sll R 0 0 reg reg d 0 n/a srl R 0 0 reg reg d 2 n/a sra R 0 0 reg reg d 3 n/a and R 0 reg reg reg 0 36 n/a or R 0 reg reg reg 0 37 n/a Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 30 / 50
Resumen de modos de direccionamiento 1 Registro: los operandos están en registros. 2 Inmediato: El operando es una constante contenida en la propia instrucción. 3 Indexado, (base más desplazamiento): Un operando está en memoria. La dirección es la suma del contenido de un registro y de un valor inmediato. 4 Relativo a $PC: La dirección del operando es la suma del registro $PC más una constante contenida en la instrucción. 5 Directo: La dirección de salto está (casi) contenida en la instrucción. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 31 / 50 o procedimientos Las subrutinas o procedimientos estructuran el código: se les pasan valores (argumentos) y devuelven resultados. Permiten el reuso del software. Aíslan unas piezas del código de otras, facilitando el mantenimiento. Es un sirviente al que se le dan unos datos (los argumentos ) y nos devuelve un resultado ( valor de retorno ). Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 32 / 50
o procedimientos Para ejecutar correctamente una subrutina, los pasos son: Actor Principal: Principal: Subrutina: Subrutina: Subrutina: Subrutina: Acción coloca argumentos en un lugar accesible a la subrutina. transfiere el control. reserva espacio para su ejecución. ejecuta su función. coloca el resultado en un lugar accesible al principal. devuelve el control al punto de partida. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 33 / 50 Más registros... Para el intercambio de datos se utilizan ciertos registros convenidos: Nombre Uso $a0 $a3 para pasar argumentos $v0 $v1 para devolver los resultados $ra para la dirección de retorno Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 34 / 50
... y una nueva instrucción Una instrucción especialmente pensada nos permite saltar al comienzo de la subrutina al tiempo que se guarda la dirección de retorno en el registro $ra. jal Procedimiento El nombre jal significa jump-and-link. El sentido es que conservamos en $ra la dirección a la que se debe retornar. La dirección de la instrucción que se ha de ejecutar se guarda en el registro de instrucción, o $PC. Por tanto la dirección que se ha de guardar en $ra es $PC+4. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 35 / 50 Resumen de llamada a la subrutina Los pasos para la llamada serán: 1 El principal coloca en $a0 $a3 los argumentos necesarios para la ejecución de la subrutina. 2 Ésta realiza los cálculos y devuelve el/los resultado(s) en $v0 $v1. 3 Devuelve el control con un simple jr $ra. Y si no bastan con los registros de que se dispone? Ahora lo vemos. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 36 / 50
Un nuevo registro y la pila Es muy probable que una subrutina necesite más registros que los $a0 $a3 y $v0 $v1. Antes de poder usar otros registros, éstos se deben archivar. Para ello, se dedica un trozo de memoria, suficientemente grande, como repositorio temporal. Este repositorio se llama pila (en inglés, stack). Se usa un registro, $sp, para saber en donde comienza el espacio libre. Cada vez que se almacena o se extrae algo, se ajusta. Por razones históricas, crece hacia las direcciones bajas de memoria. Las operaciones de almacenamiento y extracción se llaman push y pop, respectivamente. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 37 / 50 Ensamblando una subrutina Subrutina en C int sub1(int g, int h, int i, int j) { int f; f = (g + h) - (i + j); } return f; Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 38 / 50
Ensamblando una subrutina Subrutina en ensamblador sub1: subi $sp, $sp, 12 sw $t0, 8($sp) sw $t1, 4($sp) sw $s0, 0($sp) add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1... Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 39 / 50 Ensamblando una subrutina Subrutina en ensamblador... add $v0, $s0, $zero lw $s0, 0($sp) lw $t1, 4($sp) lw $t0, 8($sp) addi $sp, $sp, 12 jr $ra Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 40 / 50
Convenios sobre el uso de registros Convenimos en que los registros $t0 $t9 son temporales y no hace falta guardarlos antes de usarlos. En cambio, los registros $s0 $s7 sí deben ser salvados antes de ser usados. En la subrutina anterior nos ahorramos dos pushes. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 41 / 50 Y si la subrutina llama a otra? Si una subrutina llama a otra, probablemente necesita usar también los registros $a0 $a3, y guardar en $ra la dirección de retorno. Hay un conflicto en el uso de los registros. La solución es guardarlos en la pila antes de modificarlos, restaurando su valor al final. Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 42 / 50
Subrutina recursiva Subrutina en C int fact(int n) { if (n == 1) return 1; else return n*fact(n - 1); } Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 43 / 50 Subrutina recursiva Subrutina ensamblada (I) fact: subi $sp, $sp, 8 sw $ra, 4($sp) sw $a0, 0($sp) subi $t0, $a0, 1 bne $t0, $zero, F1 addi $v0, $zero, 1 addi $sp, $sp, 8 jr $ra... Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 44 / 50
Subrutina recursiva Subrutina ensamblada (II)... F1: subi $a0, $a0, 1 jal fact lw $a0, 0($sp) lw $ra, 4($sp) addi $sp, $sp, 8 mul $v0, $v0, $a0 jr $ra Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 45 / 50 Estado de los registros en llamadas a subrutinas Por convenio, el comportamiento es así: Preservados $s0 $s7 $sp $ra Memoria encima de $sp No preservados $t0 $t9 $a0 $a3 $v0 $v1 Memoria debajo de $sp Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 46 / 50
Ciclo de programación Programa C Código ensamblado Código máquina Ejecutable Programa cargado Compilador Ensamblador Linker Cargador Figura: Procesos y resultados del ciclo de programación Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 47 / 50 Estructura del programa cargado $sp 7fff fffc Pila $gp 1000 8000 1000 0000 Datos dinámicos Datos estáticos pc 0040 0000 0 Código (texto) Reservado Figura: Zonas de memoria, una vez cargado el programa Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 48 / 50
Estructura de un fichero objeto Cabecera fichero objeto Segmento de código Segmento de datos Información de realojo Tabla de símbolos Información de depuración Figura: Partes de un fichero objeto, con extensión.o Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 49 / 50 Lenguajes de programación de alto nivel COBOL, PL/I FORTRAN PASCAL, C ADA Java, C++, SmallTalk... Raúl Durán Díaz 3. Instrucciones: lenguaje de la máquina 50 / 50