La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Conjunto de Instrucciones

Presentaciones similares


Presentación del tema: "Conjunto de Instrucciones"— Transcripción de la presentación:

0 Arquitectura del Conjunto de Instrucciones
Adaptado a partir de la presentación del Prof. D. Patterson’s, 2000 UCB

1 Conjunto de Instrucciones
Sirve para comandar el hardware del computador, es necesario que manejemos su estructura: Las palabras del lenguaje de máquina son llamadas instrucciones; El vocabulario forma el conjunto de instrucciones, que determina la interfaz hardware/software. Veremos el conjunto de instrucciones orientado a los programadores (lenguaje assembly) y a las máquina (lenguaje de máquina) Se mostrará también las relaciones entre un lenguaje de alto nivel (como C) y el assembly.

2 Conjunto de Instrucciones
Los lenguajes de máquina son bastante parecidos entre si. Aprendiendo bien uno queda fácil aprender otro. Esto ocurre porque: Todos son basados en los mismos principios (arquitectura de Von Neumann); Existe un conjunto de operaciones básicas que todas las máquinas deben suministrar; Los diseñadores tiene el mismo objetivo: encontrar un lenguaje que torne fácil la construcción del hardware y de los compiladores, maximizando el desempeño y minimizando los costos  SIMPLICIDAD

3 Implementación de Programas
Un Programa de Computador es, básicamente, una secuencia de comandos o instrucciones representando un algoritmo que debe ser ejecutado por la máquina. Normalmente los programadores usan Lenguajes de Programación de Alto Nível (LAN), como Pascal e C, C++, JAVA, etc. Estos lenguajes corresponden a un nivel de abstracción elevado. Los lenguajes de los procesadores como el WNEANDER o el MIPS corresponden a un nivel de abstracción bajo, y son denominados “Linguajes de Bajo Nível (LBN)” Por esta razón es necesario un proceso de traducción.

4 El problema de Traducir un programa
Los lenguajes LBNs son definidos por una serie de Mnemónicos, que son, básicamente, símbolos alfabéticos que representan un código binario Por ejemplo, en le caso del WNEANDER la instrucción de adicción es representada por ADD Sabemos que esta instrucción va sumar al acumulador el valor almacenado en una dirección especificada en el segundo byte da instrucción. Esto muestra que la instrucción ADD sigue un formato: el primer byte es el código correspondiente al Mnemónico de la instrucción El segundo byte corresponde a la dirección del segundo operando de la instrucción. El primer operando ya se encuentra en el acumulador

5 Lenguaje de Montaje del Lenguaje de Máquina
Entretanto, para que un programa sea entendido por la máquina, es necesario que sus instrucciones estén codificadas en la forma binaria, en la forma de 0s y 1s. En el WNEANDER esto queda claro, pues para usar la instrucción ADD debemos primero digitar su código de operación (OP-CODE) Esto es: ADD corresponde a 30H o sea El conjunto de instrucciones de una arquitectura (en la forma de Mnemónicos) corresponde al Lenguajes de Montaje de la arquitectura (Lenguaje ASSEMBLY) El conjunto de instrucciones de una arquitectura (en la forma binaria) corresponde al Lenguaje de Máquina

6 El problema de traducir un programa
Diferentes Niveles de Abstracción Lenguaje natural Lenguaje de alto nivel (C++) Lenguaje de bajo nivel (asembler) Lenguaje de máquina procesador

7 Traductores queda claro que tanto los programas implementados en LANs como en LBN requieren ser traducidos a lenguaje de máquina del procesador El proceso de traducción de un lenguaje de alto nivel (LAN) a lenguaje de máquina es realizado por compiladores o interpretadores El proceso de traducción de un lenguaje de montaje para lenguaje de máquina es realizado por traductores, denominados Montadores (o Assemblers).

8 Compiladores e Interpretadores
Compiladores son traductores que después de varias fases (análisis léxico, análisis sintáctico, análisis semántico, generación de código intermediario, optimización de código y generación de código de montaje) generan un programa ejecutable. En la verdad, este programa ejecutable deberá ser cargado en la memoria para ser ejecutado. Quine realiza esta tarea es un programa del sistema operacional (programa cargador o loader) Los Interpretadores no generan código ejecutable. Los interpretadores traducen cada instrucción del programa (en LAN o Assembly) y la ejecutan

9 Maneras como se realiza una traducción
Tenemos tres tipos de traductores: Montadores, Compiladores e Interpretadores montador ejecución Código fuente (leng. Montaje) Objeto compilador ejecución Código fuente (LAN) Objeto Interpretador ejecución Código fuente (LAN o Assembly)

10 El problema de Traducir un programa de una LAN para una LBN
Vamos suponer un programa en C que haga lo seguiente: Problema: Traducir el código en C al conjunto de instruciones del WNEANDER if (a == 0) a = a + b; else a = a - b;

11 Tradução feita para o WNEANDER
Programa Traduzido Código do programa LDA 81 NOT ADD 82 STA 83 LDA 80 9 A JZ 10 B ADD 81 D STA 84 F F HLT ADD 83 STA 84 14 F HLT Área de dados 80 10 81 20 82 1 83 E0 84 30 O operando a está na posição 80H O operando b está na posição 81H -b é calculado e armazenado em 83H O resultado final é armazenado em H

12 Conjunto de Instrucciones
El conjunto de instrucciones iniciales que estudiaremos será la del MIPS, utilizado por diversas empresas (NEC, Nintendo, Silicon Graphics, Sony, …) Se Utilizará un simulador de MIPS llamado SPIM, que tiene versiones para Unix, Windows y DOS. El SPIM puede ser bajado en la dirección URL:

13 Organización simplificada de un procesador
Registrador Memoria Señales de control Control ULA N Z clock Decodi ficador PC

14 Organización del MIPS R2000
Fig. A.18

15 ISA do MIPS (simplificado)
Categorias de Instrucciones: Load/Store Computación Jump y Desvio Punto Flotante Administración de Memoria Especiales Registros R0 - R31 PC HI LO 3 Formatos de Instrucción: todos con 32 bits OP rs rt rd sa funct OP rs rt inmediato OP Destino del jump

16 Componentes de un ISA Organización de la estructuras de almacenamiento programables registros memoria: flat, segmentada Modos de direccionamiento y de acceso a datos e instrucciones. Tipos de datos y estructuras de los datos Codificación y representación (próximo capítulo) Formatos de instrucciones. Conjunto de instrucciones (o código de operación) ULA, transferencia de control, tratamiento de excepciones.

17 Operaciones del Hardware
Todo computador debe ser capaz de realizar operaciones aritméticas. Instrucciones aritméticas en el MIPS tienen formato fijo, realizando solamente una operación y teniendo tres “variables” ej..: add a,b,c a = b + c ej: a = b + c + d + e Solamente una Instrucción por linea Comentarios add a, b, c # a = b + c add a, a, d # a = b + c + d add a, a, e # a = b + c + d + e

18 Operaciones del Hardware
Exigir que toda instrucción tenga exactamente tres operandos conlleva a la filosofía de mantener el hardware simple: hardware para número variable de parámetros es mas complejo que para número fijo. Principio #1 para diseño: Simplicidad favorece la regularidad

19 Ejemplo Cuál será código generado por un compilador C para el siguiente trecho de programa? a = b + c; d = a – e; add a, b, c #a = b + c sub d, a, e #d = a - e

20 Ejemplo 2 Cuál será código generado por un compilador C para el siguiente trecho de programa? f = (g + h) – (i + j); Solamente una operación es hecha por instrucción: necesidad de variables temporales... add t0, g, h #temporal t0 = g + h add t1, i, j #temporal t1 = i + j sub f, t0, t1 #f = (g + h) – (I + j)

21 Operandos y Registradores
Al contrario de los lenguajes de alto nivel, assembly no permite el uso de variables.  operandos en assembly son registradores: Número limitado de direcciones especiales construidos directamente en el hardware; Bloques básicos para construcción de computadores, pues son primitivas usadas en diseño de hardware que también son observadas por los programadores;

22 Registradores: beneficios
Registradores en el hardware, dentro del procesador  más rápidos que la memoria Registradores son de más fácil utilización por los compiladores: Es un espacio para almacenamiento temporal. pueden almacenar variables para reducir el tráfico de la memoria y mejorar la densidad de código (una vez que los registradores pueden ser especificados con menos bits que una dirección de memoria)

23 Operandos y Registradores
Registradores en el MIPS son de 32 bits; En el MIPS, bloques de 32 bits son llamados palabras; Número de registradores es limitado: MIPS  32 registradores, numerados desde 0 a 31 Principio #2 para diseño: pequeño es más rápido Un numero muy grande de registradores aumentaría el período del clock.

24 Operandos y Registradores
A pesar que podemos referirnos a los registradores a través de números, en MIPS existe una convención de utilizar nombres en la forma $xy Usaremos: $s0, $s1, $s2, … para registradores que corresponden a variables en C $t0, $t1, $t2, … para registradores temporales necesarios para compilar el programa en instrucciones MIPS

25 Ejemplo Cuál será código generado por un compilador C para el siguiente trecho de programa? f = (g + h) – (i + j) Las variables f, g, h, i, j pueden ser mapeadas en los registradores $s0, $s1, $s2, $s3 e $s4, respectivamente. add $t0, $s1, $s2 #temporal t0 = g + h add $t1, $s3, $s4 #temporal t1 = i + j sub $s0, $t0, $t1 #f = (g + h) – (I + j)

26 Operandos y Registradores
Estructuras de datos pueden ser bastante complejas, con un número de elementos muy grande para poder ser almacenados en los registradores Estructuras de datos, como vectores, son almacenadas en la memoria Operaciones aritméticas en MIPS solo pueden ser hechas cuando los operandos están en registradores MIPS debe suministrar instrucciones para transferir datos entre la memoria y los registradores Para acceder una palabra en la memoria, la instrucción debe suministrar una dirección de la memoria

27 Memoria La Memoria es solamente un gran vector unidimensional, con la dirección actuando como índice en el vector, comenzando en 0. 3 2 1 100 10 101 Procesador Datos Direcciones Memoria

28 Transfiriendo datos de la memoria
La instrucción de transferencia de datos de la memoria para el registrador es llamada load. Formato: Dirección de la memoria accedida es dada por la suma de la constante (llamada “offset”) con el contenido del registrador base En MIPS, el nombre de la instrucción es: lw (load word) lw registrador destino, constante (registrador base)

29 Ejemplo g = h + *a; lw $t0, 0($s3) #temporal t0 = *a
Suponga que tenemos un apuntador a para un entero que está en la memoria, con la dirección de memoria dado en el registrador $s3 (o sea, el apuntador a está en $s3). Suponga además que el compilador asoció las variables g y h a los registradores $s1 y $s2. Cuál es el código para el siguiente trecho en C? Primero tenemos que tomar el operando que está en la memoria y transferirlo a un registrador: g = h + *a; lw $t0, 0($s3) #temporal t0 = *a add $s1, $s2, $t0 #g = h + *a

30 Resumen de la traducción
g = h + *a; lw $t0, 0($s3) #temporal t0 = *a add $s1, $s2, $t0 #g = h + *a

31 Como un vector aparece en la memoria
Vector A = [0,0,0,0,15], con 5 posiciones, comenzando en la dirección de memoria Esta dirección es llamada de dirección base del vector. Así, 102 es la dirección de A[0],103 y de A[1], ...,106 y de A[4]. Datos Direcciones Dirección base de A

32 Ejemplo Suponga que el vector A tiene 100 posiciones, y que el compilador asoció las variables g y h a los registradores $s1 y $s2. Tenemos además que la dirección base del vector A es dado en $s Cuál es el código para: Primero tenemos que ubicar el operando que está en la memoria y transferirlo a un registrador: g = h + A[8] ? lw $t0, 8($s3) #temporal t0 = A[8] add $s1, $s2, $t0 #g = h + A[8]

33 Resumen de la Traducción
g = h + A[8] lw $t0, 8($s3) #temporal t0 = A[8] add $s1, $s2, $t0 #g = h + A[8]

34 Comentario sobre la traducción anterior
La traducción anterior no toma en cuenta el hecho de como el MIPS direciona las palabras de la memoria Esto será tratado posteriormente....

35 Transferencia de la memoria
Ya que los bytes (8 bits) son útiles en muchos programas, la mayor parte de las arquitecturas permiten acceder bytes; Por lo tanto, la dirección de una palabra es la dirección de uno de los 4 bytes dentro de la palabra Así, direcciones de palabras consecutivas difieren en 4 12 8 4 100 10 101 1 direcciones Datos Procesador Memoria

36 Cómo un vector aparece en la memoria (2)
Cada posición del vector (de enteros) es una palabra, y por lo tanto ocupa 4 bytes Vector A = [0,0,0,0,15], con 5 posiciones, comenzando en la dirección de memoria 408. Así, 408 es la dirección de A[0], 412 la de A[1], 416 la de A[2], 420 la de A[3] y 424 la de A[4]. Datos Dirección base de A Ddirecciones

37 Ejemplo Suponga que el vector A tiene 100 posiciones, y que el compilador asoció la variable h al registrador $s2. Tenemos además que la dirección base del vector A es dada en $s3. Cuál es el código para: La novena posición del vector A, A[8], está en el offset 8 x 4 = 32 La décima-tercera posición del vector A, A[12], está en offset 12 x 4 = 48 A[12] = h + A[8] ? lw $t0, 32($s3) #temporal t0 = A[8] add $t0, $s2, $t0 #temporal t0 = h + A[8] sw $t0, 48($s3) #carga A[12] en $t0!!!!

38 Resumen de la traducción (real en el MIPS)
A[12] = h + A[8] lw $t0, 32($s3) #temporal t0 = A[8] add $t0, $s2, $t0 #temporal t0 = h + A[8]

39 Transferiendo datos para la memoria
La instrucción de transferencia de datos de un registrador para la memoria es llamada store. Formato: Dirección de memoria accedida es dada por la suma de la constante (llamada de offset) con el contenido del registrador base En MIPS, el nombre de la instrucción es: sw (store word) sw registrador funte, constante (registrador base)

40 Dirección absoluta de la posición 3 (i = 3) del vector
Para obtener la dirección absoluta requerimos: Variable i ( i = 3) ($s4) desplazamiento(offset) offset = 4*i dirección = $s2 + 4*3 Registrador base eje. $s2

41 Ejemplo: y si el índice fuera una variable?
Suponga que el vector A tiene 100 posiciones, y que el compilador asoció las variables g, h y i a los registradores $s1, $s2 e $s4. Tenemos además que la dirección base del vector A es dado en $s3. Cual es el código para: Requerimos primero que calcular la dirección de A[i]. Antes de sumar i a la dirección base de A, debemos multiplicar i por 4. Vamos hacer esto por ahora de la siguiente forma: g = h + A[i] ? add $t1, $s4, $s4 # $t1 = 2 * i add $t1, $t1, $t1 # $t1 = 4 * i

42 Ejemplo: y si el índice fuera una variable?
Para coger A[i], sumamos $t1 con la dirección base de A, dada en $s3: Ahora podemos cargar A[i] para un registrador temporal, y realizar la suma, que será almacenada en g: add $t1, $t1, $s3 # $t1 = dirección de A[i] lw $t0, 0($t1) #temporal $t0 = A[i] add $s1, $s2, $t0 #g = h + A[i]

43 Resumen de la Traducción
g = h + A[i] add $t1, $s4, $s4 # $t1 = 2 * i add $t1, $t1, $t1 # $t1 = 4 * i add $t1, $t1, $s3 # $t1 = dirección de A[i] lw $t0, 0($t1) #temporal $t0 = A[i] add $s1, $s2, $t0 #g = h + A[i]

44 Ejercicio Tenemos además que la dirección base del vector A está dado en $s2, y que las variables i y g son dadas en $s0 y $s1, respectivamente . Cual sería el código para: A[i+g] = g + A[i] – A[0]?

45 Solución A[i+g] = g + A[i] – A[0]? i,g,A = $s0, $s1,$s2
add $t0, $s0, $s0 # $t0 = 2*i add $t0, $t0, $t0 # $t0 = 4*i add $t0, $t0, $s2 # $t0 = dirección de A[i] lw $t1, 0($t0) # $t1 = A[i] add $t1, $s1, $t1 # $t1 = g + A[i] lw $t0, 0($s2) # $t0 = A[0] sub $t1, $t1, $t0 # $t1 = g + A[i] – A[0] add $t0, $s0, $s1 # $t0 = i + g add $t0, $t0, $t0 # $t0 = 2 * (i + g) add $t0, $t0, $t0 # $t0 = 4 * (i + g) add $t0, $t0, $s2 # $t0 = dirección de A[i + g] sw $t1, 0($t0) # A[i + g] = g + A[i] – A[0]

46 Utilizando los registradores
Muchos programas tiene más variables de que el número de registradores que tiene una máquina. El compilador intenta mantener las variables más usadas en los registradores y coloca el resto en la memoria, utilizando loads y stores para mover los datos entre la memoria y los registradores: Los compiladores tiene que utilizar los registradores de forma eficiente.

47 Un comentario sobre la memoria: alineamiento
MIPS requiere que todas las palabras comiencen en direcciones que son múltiplos de 4 bytes LLamamos esto de alineamiento: objetos tiene que tener direcciones que sean múltiplos de sus tamaños. Alineado No alineado

48 Otro comentario: Byte order
Procesadores puoden numerar bytes dentro de una palabra, de tal forma que el byte con el menor número es el más a la izquierda o el más a la derecha. Esto es llamado de byte order. Ej: .byte 0, 1, 2, 3 Big endian: IBM 360/370, Motorola 68k, MIPS, Sparc, HP PA Little Endian: Intel 80x86, MIPS, DEC Vax, DEC Alpha big endian little endian

49 Representando Instrucciones en un Computador
Números son armacenados en el hardware en base 2, o binária. Instrucciones se pueden representar como números. En la verdad, cada pedazo de la instrucción es un número, y el posicionamento de un lado a otro es los que forma la instrcción. Existe una convención en el MIPS para asociar nombres de registradores a sus números: $s0, $s1, …, $s7  16, 17, …, 23 $t0, $t1, …, $t7  8, 9, …, 15

50 Representando Instrucciones en un Computador
Lenguaje de máquina para la instrucción: Cada segmento es se llama campo. El primero y el último, juntos, informan que la instrucción es una adición. El segundo dice cual es el primer registrador fuente (17 = $s1) y el tercero, el segundo registrador fuente (18 = $s2). El cuarto campo es el registrador destino (8 = $t0). El quinto campo no es usado en esta instrucción, y por esto tiene valor cero. add $t0, $s1, $s2

51 Representando Instrucciones en un Computador
También podemos representar los números en binario: Para distinguir del lenguaje Assembly, llamamos esta representación numérica del lenguaje de máquina, y la secuencia de tales instrucciones de código de máquina Llamamos esta estructura de campos del formato de la instrucción. Tales instrucciones en MIPS poseen 32 bits (“simplicidad favorece regularidad”). 6 bits bits bits 5 bits bits bits

52 Campos del MIPS op rs rt rd shamt funct
Daremos nombres a los campos para simplificar la discusión: op: operación básica de la instrucción (opcode); rs: primer registrador fuente; rt: segundo registrador fuente; rd: registrador destino, recibe el resultado de la operación shamt: cantidad de shift (se verá posteriormente) funct: función; selecciona el tipo específico de la operación dada en el campo op, tambiém llamada de código de la función. op rs rt rd shamt funct 6 bits bits bits 5 bits bits bits

53 Campos MIPS Un problema sucede cuando una instrucción necesita de campos más largos que los mostrados en este ejemplo. Ex.: La instrucción lw requiere especificar dos registradores y una constante. Si la constante fuera a ser representada en el campo de uno de los registradores, su valor se limitará máximo hasta 32 (2^5). Obviamente, este valor es muy pequeño para ser útil. Así, tenemos un conflicto entre el deseo de que todas las instrucciones tengan el mismo tamaño y el deseo de que tengamos un solo formato de instrucciones.

54 Campos MIPS Principio #3 para diseño: buenos diseños demandan buenos compromisos. El Compromiso escogido por los diseñadores del MIPS: mantener todas las instrucciones con el mismo tamaño  diferentes tipos de instrucción puedem tener diferentes formatos de instrucción. El formato mostrado anteriormente es el llamado de tipo-R (de registrador) o formato-R Un segundo formato es el usado por las instrucciones de transferencia de datos: tipo-I o formato-I

55 Campos MIPS Formato tipo-I: op rs rt dirección
La dirección de 16 bits significa que una instrucción lw puede cargar cualquier palabra dentro de una región de 2^15 o bytes (2^13 o 8192 palabras) en relación a la dirección en el registrador base rs. op rs rt dirección 6 bits bits bits bits

56 Campos MIPS op rs rt dirección
Ej: lw $t0, 32($s3) #temporal $t0 = A[8] En este ejemplo, rs recibe 19 ($s3), rt recibe 8 ($t0) y el campo dirección recibe el valor 32. Op en este caso es 35 (lw). En una instrucción de load, el campo rt determina el registrador destino!! A pesar que e hardware queda más complejo se utilizan diferentes formatos de instrucción, podemos reducir este aumento de complejidad manteniendo cierta similaridad entre los formatos (ej.: 3 primeros campos en los formatos tipo-R y tipo-I son los mismos; el largo del último campo tipo-I es igual a la suma de los 3 últimos tipo-R). op rs rt dirección

57 Campos MIPS El primer campo determina el tipo del formato.
Pregunta: por que no utilizar solamente un campo de 12 bits para los campos op y funct en las instrucciones tipo-R??

58 Codificación de algunas instrucciones estudiadas
Formato op rs rt rd shamt funct Direcc. add R reg 32 no sub 34 lw I 35 direc. sw 43 $s0, $s1, …, $s7  16, 17, …, 23 $t0, $t1, …, $t7  8, 9, …, 15

59 Ejemplo de una compilación manual
Suponga que $t1 tiene la direción base de A y que $s2 corresponda a h, traduzca la seguiente linea en C a código de máquina MIPS: A[300] = h + A[300]; Primeiro, temos que el código een assembly correspondiente es: Cuál es el código de máquina de estas 3 instrucciones? lw $t0,1200($t1) # $t0 = A[300] add $t0, $s2, $t0 # $t0 = h + A[300] sw $t0, 1200($t1) # A[300] = h + A[300]

60 Ejemplo de una compilación manual
lw $t0,1200($t1) add $t0, $s2, $t0 sw $t0, 1200($t1) op rs rt rd direcc / shamt func 35 9 8 1200 18 32 43 op rs rt rd direcci / shamt func 100011 01001 01000 000000 10010 00000 100000 101011

61 Idea general: concepto de programa almacenado
Computadores modernos son construidos basados en dos principios fundamentales: Las Instrucciones pueden ser representadas como números Los Programas pueden ser almacenados en memória para ser ledos o escritos de la misma forma que los números El Concepto de programa almacenado,es fundamental en Computación!!!

62 Instruciones para toma de decisiones (control de flujo)
Lo que distingue un computador de una calculadora simple es la habilidad de tomar decisiones. Con base en la entrada y en los resultados computados, diferentes instrucciones son ejecutadas. En lenguajes de alto nivel, una de las formas de tomar las decisiones es a través de las instrucciones if y goto. En MIPS, tenemos dos instrucciones que actúan de manera similar las instrucciones que combinan if con goto: beq registr1, registr2, L1 #branch if equal bne registr1, registr2, L1 #branch if not equal rótulo (label)

63 Instrucciones de decisión en MIPS
en C, esto sería equivalente a: beq registr1, registr2, L1 Semántica: “Desvie si (valores en los registradores son) iguales” if (registr1== registr2) goto L1

64 Instrucciones de decisión en MIPS(II)
en C, esto sería equivalente a: Estas instrucciones se llaman de desvío condicional. bne registr1, registr2, L1 Semántica: “desvie si (los valores en los registradores) no son iguales” if (registr1!=registr2) goto L1

65 Ejemplo Si las variables f, g, h, i, j corresponden a los registradores $s0 a $s4, cual es el código compilado para el seguiente programa en C? Como las instrucciones son armacenadas en la memoria, ellas tiene direcciones también!! if (i == j) goto L1; f = g + h; L1: f = f – i; beq $s3, $s4, L1 # va para L1 si $s3 == $s4 add $s0, $s1, $s2 # f = g + h (se i != j) L1: sub $s0, $s0, $s3 # f = f – i (se i == j)

66 Instrucciones para toma de decisiones
El montador (assembler) hace que el compilador o el programador en lenguaje assembly no tenga que estar calculando direcciones para los desvíos (branches) al permitir el uso de labels. Compiladores crean desvíos y rótulos sen que el programador de lenguaje de alto nivel los tenga que especificar. Esta es una de las razones de por que es más rápido programar en lenguajes de alto nivel.

67 Desvío incondicional en MIPS
MIPS tiene un desvío incondicional: llamada de instrucción de salto (jump): salte al rótulo especificado, (incondicionalmente!) En C, esto sería equivalente a: goto label Podemos pensar que esto es equivalente a: Ya que la condición siempre es satisfecha Existe un formato de instrucción para desvío (tipo-J o formato-J), como se verá adelante. j rótulo beq $0,$0,rótulo

68 Ejemplo: código para if
Si las variables f, g, h, i, j corresponden a los registradores $s0 a $s4, cuál es el código compilado para el siguiente trecho en C? Queremos implementar el siguiente flujo: if (i == j) f = g + h; else f = g – h; Fin i == j? f=g+h f=g-h (falso) i != j (verdadero) i == j

69 Ejemplo: código para if
Primero debemos saber si i es igual a j: Si i == j, sumamos g con h y almacenamos en f Requerimos ahora ir para el fin del if. Para esto utilizamos un desvío incondicional ( j, de jump ): Tratamos ahora el caso en que i != j bne $s3, $s4, else # vá para else si i != j add $s0, $s1, $s2 # f = g + h (se i == j) j Fim # vá para Fim Else: sub $s0, $s1, $s2 # f = g – h (se i != j) Fin:

70 Resumen de la traducción de if then else
if (i == j) f = g + h; else f = g – h; bne $s3, $s4, Else # vá para else si i != j add $s0, $s1, $s2 # f = g + h (se i == j) j Fin # vá para Fin Else: sub $s0, $s1, $s2 # f = g – h (si i != j) Fin:

71 Loops Decisiones son importantes para escoger entre dos alternativas, y para iterar una computación (loop). Usamos las mismas instrucciones assembly para las dos situaciones. Todo depende de donde colocamos el rótulo para el cual saltaremos.

72 Ejemplo de loop Loop: g = g + A[i]; if ( (i = i + j) != h ) goto Loop;
Si las variable g, h, i, j corresponden a los registradores $s1 a $s4, y la dirección base del vector A (de 100 elementos) está en $s5, compile el siguiente trecho dado C. Loop: g = g + A[i]; if ( (i = i + j) != h ) goto Loop; Loop: add $t1, $s3, $s3 # $t1 = 2 * i add $t1, $t1, $t1 # $t1 = 4 * i add $t1, $t1, $s5 # $t1 = direcc. de A[i] lw $t0, 0($t1) # $t0 = A[i] add $s1, $s1, $t0 # g = g + A[i] add $s3, $s3, $s4 # i = i + j bne $s3, $s2, Loop # Loop se (i != h)

73 Compilando un lazo do tipo while
Los programadores normalmente no utilizan instrucciones goto (su uso es considerado una mal práctica de programación !!!). Asim, el compilador tiene que traducir los loops tradicionales en lenguaje MIPS. Ejemplo en C: Si i, j, e k corresponden a los registradores $s3, $s4 e $s5, y la dirección base del vector save está en el registrador $s6, cuál es le código assembly MIPS correspondiente? while (save[j] == k) i = i + j;

74 Compilando un lazo do tipo while
Tenemos inicialmente que cargar save[i] a un registrador temporal: Ahora realizamos el test del loop, si save[i] != k Debemos ahora regresar al while en el inicio del loop Loop: add $t1, $s3, $s3 # $t1 = 2 * i add $t1, $t1, $t1 # $t1 = 4 * i add $t1, $t1, $s6 # $t1 = direccion de save[i] lw $t0, 0($t1) # $t0 = save[i] bne $t0, $s5, Fin # vá para Fim se save[i] != k add $s3, $s3, $s4 # i = i + j j Loop # va para Loop Fin:

75 Resumen de la traducción de while
while (save[j] == k) i = i + j; Loop: add $t1, $s3, $s3 # $t1 = 2 * i add $t1, $t1, $t1 # $t1 = 4 * i add $t1, $t1, $s6 # $t1 = direccion de save[i] lw $t0, 0($t1) # $t0 = save[i] bne $t0, $s5, Fin # va par Fim si save[i] != k add $s3, $s3, $s4 # i = i + j j Loop # va para Loop Fin:

76 Comparando dos registradores
Los tests de igualdad o desiguald son probablemente los más populares, pero hay veces que queremos testar si una variable es menor que otra Por ejemplo, un for puede querer testar si un índice es menor de cero. En MIPS, tenemos una instrucción que compara los valores de dos registradores, e atribuye 1 a un tercer registrador si el primero registrador es menor que el segundo, y 0 en caso contrario:  Si $s3 < $s4, $t0 recibe 1, caso contrario, recibe 0 slt (set on less than) slt $t0, $s3, $s4

77 Compilando un lazo del tipo while
Compiladores MIPS utilizam las instrucciones slt, beq, bne, y el valor fijo cero para criar todas las relaciones de comparación: igual, diferente, menor que, menor o igual a, mayor que, mayor o igual a. El registrador $cero (registrador 0) tiene su valor fijado en cero.

78 Ejemplo: desvío si menor que
Cuál el código para testar, si la variable a, mapeada en el registrador $s0, es menor que la variable b (registrador $s1), y desviar para el rótulo Menor si la condición fuera satisfecha? Primero usamos a instrucción slt y un registrador temporal: Registrador $t0 es 1 si a < b. Por lo tanto, testamos si $t0 no es 0: slt $t0, $s0, $s1 # $t0 = (a < b)? bne $t0, cero, Menor #vá para Menor si $t0!=0 #o sea, si (a < b)

79 traducción del if (a < b) then... else
if (i < j) f = g + h; else f = g – h; slt $t0, $s0, $s1 # $t0 = (a < b)? beq $t0, cero, Else # va para else si a >= b add $s0, $s1, $s2 # f = g + h (se i == j) j Fin # vá para Fin Else: sub $s0, $s1, $s2 # f = g – h (se i != j) Fin:

80 Por que no utilizar una instrucción solo “desvie si es menor que”?
MIPS no tiene instrucciones como “desvie si menor que” porque son muy complicadas: aumentarían el período del clock o serian necesarios más ciclos de clock por instrucción (además de exigir la necesidad de más hardware). Las dos instrucciones slt y bne son más rápidas y más útiles, pues también sirven para otros propósitos.

81 j Rótulo # desvio para el rótulo
otro tipo de desvío incondicional Hasta ahora vimos una instrucción de desvío incondicional, a través de la instrucción En esta instrucción, tenemos que especificar un rótulo, o sea una dirección fija, para la cual el Program Counter será desviado. En diversas situaciones, puede ser interesante que desviemos para una dirección variable, almacenada en un registrador. Por lo tanto, existe la instrucción jr: j Rótulo # desvio para el rótulo jr registrador #desvio para dirección #contenida en el registrador

82 Instrucción switch El linguaje C define la instrucción switch, que permite que el programador seleccione una alternativa entre varias, dependiendo de un valor único. Cómo compilar el siguinte trecho de código en C? switch (k) { case 0: f = i + j; break; case 1: f = g + h; break; case 2: f = g – h; break; case 3: f = i – j; break; }

83 Instrucción switch Una forma de realizar esto es tratar el comando switch como una secuencia de instrucciones if: if ( (k >= 0) && (k <= 3)) { if (k == 0) f = i + j; else if (k == 1) f = g + h; else if (k == 2) f = g - h; else }

84 Instrucción switch De esta forma, si tenemos n casos posible, tendremos, en media, que verificar n/2 casos contra k para encontrar el caso deseado. Cómo podemos implementar el comando switch de manera más eficiente? En algunos casos, podemos utilizar una tabla de direcciones, de tal forma que al acceder la tabla en la posición correspondiente a k, TabEnd[k], obtengamos la dirección del label deseado. De esta manera, podemos tomar la decisión en tiempo constante.

85 Instrucción switch Mejorando la instrucción switch: switch (k) {
Vamos suponer que las variables f, g, h, i, j, k están en los registradores $s0 a $s5, y que $t2 contiene el valor 4. switch (k) { case 0: f = i + j; break; case 1: f = g + h; break; case 2: f = g – h; break; case 3: f = i – j; break; }

86 Comando switch Utilizaremos la variable k como índice en la tabla de direcciones, y desviamos de acuerdo con el valor cargado; Primero, tenemos que verificar si 0 <= k <= 3: Vamos utilizar k para indexar; por esto tenemos que multiplicar k por 4. slt $t3, $s5, $cero #verifica si k<0 bne $t3, $cero, Fin #si k<0, se va para Fin slt $t3, $s5, $t2 #verifica si k<4 beq $t3, $cero, Fin #si k>=4 va para Fin

87 Instrucción switch add $t1, $s5, $s5 # t1 = 2 * k
Suponga que el vector de direcciones TabEnd, cuya dirección está en $t4, pose cuatro posiciones, con las direcciones correspondientes a los labels L0, L1, L2 y L3: Ahora saltamos para la dirección presente en $t0: add $t1, $s5, $s5 # t1 = 2 * k add $t1, $t1, $t1 # t1 = 4 * k add $t1, $t1, $t4 # t1 = direccion de TabEnd[k] lw $t0, 0($t1) # t0 = TabEnd[k] jr $t0

88 Instrucción switch Por fin tratamos los casos del switch:
L0: add $s0, $s3, $s4 # f = i+j j Fin L1: add $s0, $s1, $s2 # f = g + h L2: sub $s0, $s1, $s2 # f = g – h j Fin L3: sub $s0, $s3, $s4 # f = i – j (no requiere saltar # para el Fin, ya que la próxima # instrucción es Fin) Fin:

89 Resumen: instrucciones estudiadas hasta ahora

90 Instrucciones para soportar llamada procedimentos o subrutinas
Procedimientos o subrutinas son utilizadas por los programadores para: Facilitar la compresión y mantenimiento del código; Posibilitar el reaprovechamiento de código. El código de un procedimiento queda “aislado”, siendo la interfaz con el código restante, la establecidad por los argumentos de entrada y por los resultados de salida.

91 Instrucciones para soportar llamada procedimentos o subrutinas
En la ejecución de un procedimiento, un programa debe seguir los siguientes pasos: Colocar los argumentos (parámetros) en un lugar donde el procedimiento puede accederlos; Transferir el control al procedimiento; Ejecutar la tarea deseada (del procedimiento). Colocar el resultado de la ejecución en un lugar en el cual el código que llamó el procedimiento pueda accederlo; Retornar el control para el lugar de origen.

92 Instrucciones de soporte a procedimentos
Cuál es el lugar más rápido donde se pueden almacenar datos en un computador? Registrador. Se deben utilizar registradores siempre que sea posible El Software para MIPS utiliza los siguientes registradores para llamada de procedimientos: $a0 - $a3: cuatro registradores que son utilizados para pasar parámetros para los procedimientos; $v0 - $v1: dos registradores que son utilizados para retornar valores calculados por los procedimientos (resultados) $ra: registrador utilizado para retornar al ponto de origen (ra = return address).

93 Instrucciones para soportar llamada procedimientos o subrutinas
Prepara argumentos para el procedimento $a0-$a3 Realiza desvio para el procedimento $ra; desvio Ejecución del procedimento Continuación del programa Valores de retorno del procedimento $v0-$v1 Retorno para la continuación del programa jr $ra

94 Ejemplo de procedimento
... suma(a,b);... /* a:$s0; b:$s1 */ } int suma(int x, int y) { /* x:$a0; y:$a1 */ return x+y; } Direccción 1000 add $a0,$s0,$zero # x = a 1004 add $a1,$s1,$zero # y = b addi $ra,$zero,1016 # $ra = j suma # desvio para suma 2000 suma: add $v0,$a0,$a jr $ra #regre. p/ origen, #a la direicc 1016 C M I P S

95 Instucción jal (jump and link)
El MIPS tiene una instrucción de salto solo para procedimientos; ella causa un desvío para la dirección, y al mismo tiempo guarda la dirección de la próxima instrucción en $ra: jal (jump and link). jal label #desvio para el procedimento que tiene #dirección marcado por label

96 Procedimientos son muy comunes: “Haga el caso común el más rápido”
jal (jump and link) Link, en este caso, quiere decir que es utilizado, el registrador $ra, para guardar una referencia a la instrucción que sigue a la instrucción jal, o sea, la instrucción jal es equivalente al siguiente código: Por qué existe a instrucción jal?? $ra = PC + 4 j Rótulo Procedimientos son muy comunes: “Haga el caso común el más rápido”

97 Ejemplo de procedimento (revisado)
... suma(a,b);... /* a:$s0; b:$s1 */ } int suma(int x, int y) { /* x:$a0; y:$a1 */ return x+y; } dirección 1000 add $a0,$s0,$zero # x = a 1004 add $a1,$s1,$zero # y = b jal suma #prepara $ra y #jump p/ proc suma 2000 suma: add $v0,$a0,$a jr $ra # regre p/ origen, # a la direcc 1012 C M I P S

98 i = sub(i,j); /* sub(a, b) {return a-b;} */
Ejercicio Cuál es le código en assembly del MIPS equivalente al siguiente instrucción en C, estando i en $s0 y j en $s1? i = sub(i,j); /* sub(a, b) {return a-b;} */ ... add $a0, $s0, $zero #a0 = i add $a1, $s1, $zero #a1 = j jal sub #Llama la fun. sub add $s0, $v0, $zero # i = sub(i,j) sub: sub $v0, $a0, $a1 # $v0 = a – b jr $ra # retorne p/ origen

99 Usando más registradores
Suponga que un procedimiento requiere más registradores de que los 4 registradores de argumentos y 2 de retorno. El código que llama este procedimiento puede estar utilizando diversos registradores, de tal forma que el procedimiento no puede utilizar los registradores de cualquier forma, ya que valores importantes se podrían perder. Así, Cualquier registrador que el procedimiento utilice y que pueda ser de interés del código “que efectua el llamado” debe tener su valor restaurado al valor anterior a la ejecucción del procedimento.

100 Usando más registradores
Cómo llevar a cabo esto? Se realiza el Proceso conocido como register spilling: Consiste en el uso de una pila, una estructura de datos do tipo LIFO (last-in first-out); Se tiene un apuntador para el tope de la pila; Este apuntador es ajustado en una palabra cada vez que un registrador es colocado en la pila (operación conocida por push), o retirado de la pila (operación conocida por pop). En el MIPS, un registrador es utilizado solamente para indicar el tope de la pila: sp (stack pointer)

101 Usando más registradores
Por razones históricas, la pila “crece” de la mayor dirección a la menor dirección: Para colocar un valor en la pila (push), debemos decrementar $sp en una palabra y mover el valor deseado para la posición de memoria apuntada por $sp; Para retirar un valor de la pila (pop), debemos leer este valor de la posición de memoria apuntado por $sp, y entonces incrementar $sp en una palabra.

102 Alocando memória en C Dirección ¥ Espacio para que los Pila
procedimentos almacenen información $sp stack pointer Espacio explicitamente creado malloc: apuntadores en C Heap Variábles declaradas una vez para todo programa Estático Código Programa

103 Ejemplo: ejemplo_proc
Suponga que tenemos el seguiente código: Vamos generar el código correspondiente en assembly MIPS. int ejemplo_proc (int g, int j, int i, int h) { int f; f = (g+h) – (i+j); return f; }

104 Ejemplo: ejemplo_proc
Los argumentos g, h ,i e j corresponden a los registradores $a0, $a1, $a2 y $a3, y f corresponde a $s0. Primero colocamos el rótulo del procedimiento: ejemplo_proc: Debemos entonces almacenar los registradores que serán utilizados por el procedimiento. Como estaremos utilizando los registradores $t0, $t1 e $s0, vamos a colocarlos en la pila: subi $sp, $sp, 12 #crea espacio para 3 itens mas en la pila sw $t1, 8(sp) #empila $t1 sw $t2, 4(sp) #empila $t2 sw $s0, 0(sp) #empila $s0

105 Ejemplo: ejemplo_proc
Como quedó la pila? $sp Valores empilados antes de la función Pila antes de la función Valores empilados antes de la función $sp $s0 $t2 $t1 Pila durante ejecución de la función

106 Ejemplo: ejemplo_proc
Las próximas instrucciones corresponden al cuerpo del procedimiento: El resultado debe ser almacenado en el registrador $v0: add $v0, $s0, $zero # retorna f en $v0 add $t0, $a0, $a1 # $t0 = g + h add $t1, $a2, $a3 # $t1 = i + j sub $s0, $t0, $t1 # f = $t0 = (g+h) – (i+j)

107 Ejemplo: ejemplo_proc
Antes de salir del procedimiento, debemos restaurar los valores de $t0, $t1 y $s0, retirándolos de la pila: Regresamos entonces para la instrucción siguiente al punto en que la función ejemplo_proc fue llamada: lw $s0, 0($sp) # desempila $s0 lw $t0, 4($sp) # desempila $t0 lw $t1, 8 ($sp) # desempila $t1 addi $sp, $sp, 12 # retira 3 itens de la pila jr $ra # retorna a la subrutina que llamo # este procedimento

108 Instrucciones de soporte a procedimentos
En el ejemplo anterior, utilizamos registradores temporales y asumimos que los valores de ellos deberían ser guardados y restaurados. Para evitar que los registradores que no son utilizados sean empilados y desempilados, MIPS ofrece dos clases de registradores: $t0-$t9: 10 registradores temporales que no son preservados por la función que es llamada. $s0-$s7: 8 registradores que tienen sus valores preservados en el proceso de llamada de procedimiento. De esta forma, si estos registradores fueran utilizados por el procedimiento, se debe almacenar sus valores empilandolos en el inicio del procedimiento y desempilandolos en el final.

109 Instrucciones de soporte a procedimentos
Esta simple convención permite que nos se pierda tanto tiempo empilando y desempilando registradores En el ejemplo, tendríamos que preservar solamente el valor de $s0. que hacer entonces si tenemos un código que utiliza registradores temporales y va llamar una función?? Pueden aparecer problemas cuando hacemos que funciones chamen otras funciones (por ejemplo, funciones recursivas)??

110 Procedimentos anidados
Suponga que el programa principal llama la función A con el argumento 3, al colocar 3 en $a0 y utiliza la instrucción jal A. Suponga además que la función A llama la función B con argumento 7, al colocar 7 en $a0 y utiliza la instrucción jal B. Una vez que A todavía no terminó de ejecutarse tendremos un conflicto en el uso del registrador $a0. Un problema también aparece para el registrador $ra, que ahora contiene el valor para el retorno de B. Se no tenemos cuidado, podríamos no ser capaces ni de regresar al programa principal!!! Cómo resolver este problema?

111 Procedimentos anidados: convención sobre registradores
Una solución es empilar todos los registradores que requieren ser preservados. Para esto, tenemos que establecer una convención entre la subrutina que llama a la función y la subrutina llamada, para establecer cuales registradores serán preservados, y por quien ? Definiciones: llamadora: función que realiza la llamada, utilizando jal; Llamada: función siendo llamada. Podemos pensar en estas convenciones como un “contrato” entre la llamadora y la llamada;

112 Por que utilizar convenciones para llamadas de procedimentos?
Si tanto la sub-rutina llamadora como la llamada obedecieran la convención, tendremos los siguientes beneficios: Personas que nunca conversaran pueden escribir funciones que funcionan juntas; Funciones que llaman otras funciones – como las recursivas – funcionan correctamente. Atención!! Llamadora o llamada no representa una propiedad de la función, pero si el papel que la función ejerce en una llamada de procedimiento específica. Así, una función puede ejercer el papel de llamadora y de llamada, solo que en diferentes llamadas de procedimiento.

113 Derechos de la Llamadora y de la Llamada
Derechos de la Llamada: Utilizar libremente los registradores v, a, y t; Asumir que los argumentos son pasados corretcamente. Registradores que deben ser preservados por la Llamadora: Dirección de retorno $ra Argumentos $a0, $a1, $a2, $a3 Valores de retorno $v0, $v1 Registradores temporales $t0 - $t9 Derechos de la Llamadora Utilizar los registradores s, sin que ellos sean alterados por la Llamada Asumir que los valores de retorno y la pila están correctos Registradores que deben ser preservados por la Llamada: Registradores $s $s0 - $s7

114 Ejemplo: suma_recursiva
Suponga que tenemos el siguiente código, que calcula la suma n + (n-1) + … de forma recursiva: Vamos generar el código correspondiente en assembly MIPS. int suma_recursiva (int n) { if (n < 1) return 0; else return n + suma_recursiva(n-1) }

115 Ejemplo: suma_recursiva
El parámetro n corresponde al registrador $a0. Debemos inicialmente colocar un rótulo para la función, y salvar la dirección de retorno, almacenada en $ra, o parámetro $a0: En la primera vez que suma_recursiva es llamada, el valor de $ra que es almacenado corresponde a una dirección que está en la sub-rutina que llama esta función. Suma_recursiva: subi $sp, $sp, 8 # prepara la pila para recibir 2 # valores sw $ra, 4($sp) # empila $ra sw $a0, 0($sp) # empila $a0

116 Ejemplo: suma_recursiva
Vamos ahora a compilar o cuerpo de la función. Inicialmente, verificamos si n < 1: Si n <1, la función debe retornar el valor 0. No podemos olvidarnos de restaurar la pila. Por qué no cargamos los valores de $a0 y $ra antes de ajustar $sp?? slti $t0, $a0, 1 # testa si n < 1 beq $t0, $zero, L # si n>=1, va para L1 add $v0, $zero, $zero # valor de retorno es0 add $sp, $sp, 8 # remueve 2 itens de la pila jr $ra # retorne para depues de jal

117 Ejemplo: suma_recursiva
Si n >=1, decrementamos n y llamamos nuevamente la función suma_recursiva con el nuevo valor de n. Cuando la suma para (n-1) es calculada, el programa vuelve a ejecutar en la próxima instrucción. Restauramos la dirección de retorno y el argumento anterior, e incrementamos el apuntador de tope de la pila: L1: subi $a0, $a0, 1 # argumento pasa a ser (n-1) jal suma_recursiva # calcula la suma para (n-1) lw $a0, 0($sp) # restaura el valor de n lw $ra, 4($sp) # restaura la dirección de retorno addi $sp, $sp, 8 # retira 2 itens de la pila.

118 Ejemplo: suma_recursiva jr $ra # retorne para el “llamador”
Ahora el registrador $v0 recibe la suma de argumento antiguo $a0 con el valor actual en $v0 (suma_recursiva para n-1): Por último, regresamos a la instrucción siguiente a la que llamó el procedimiento: add $v0, $a0, $v0 # retorne n + suma_recursiva(n-1) jr $ra # retorne para el “llamador”

119 Ejemplo: suma_recursiva jr $ra # retorne para el “llamador”
Ahora el registrador $v0 recibe la suma de argumento antiguo $a0 con el valor actual en $v0 (suma_recursiva para n-1): Por último, regresamos a la instrucción siguiente a la que llamó el procedimiento: add $v0, $a0, $v0 # retorne n + suma_recursiva(n-1) jr $ra # retorne para el “llamador”

120 Trabajando con caracteres y strings
La mayor parte de los computadores hoy utiliza bytes para representar caracteres, casi siempre utilizan la codificación ASCII (American Standard Code for Information Interchange). La tabla de ASCII, debe ser utilizada como fuente de consulta. Instrucciones de transferencia de palabras (lw, sw) son suficientes para transferir bytes también. En caso, bytes individuales podrían ser leidos o escritos, a través del uso de máscaras, con las instrucciones and y or lógicos.

121 Trabajando con caracteres y strings
Ya que gran parte de los programas utilizan texto, MIPS definió instrucciones específicas para mover bytes. Lectura de bytes: load byte (lb): le un byte de la memoria, colocándolo en los 8 bits mas a la derecha de n registrador Ej: lb $t0, 0($sp) # el byte que está en el tope de la pila

122 Trabajando con caracteres y strings
Escritura de bytes: store byte (sb): escribe en la memoria el byte que está en los 8 bits más a la derecha de un registrador Ej: sb $t0, 0($sp) # escribe byte en el tope de la pila

123 Trabajando con caracteres y strings
Caracteres son normalmente combinados en strings o cadenas de caracteres, que poseen un número variable de caracteres. Existen 3 opciones para representar un string: La primera posición del string es reservado para almacenar el ancho de la cadena; Ej: “casa” = 4 ´c´ ´a´ ´s´ ´a´ = Cuál e el tamaño máximo del string si cada posición ocupa un byte?

124 Trabajando con caracteres y strings
El string es almacenada en una estructura, en la que una varible dice el ancho de la cadena y otra trae los caracteres que componen la cadena; Ej: “casa” = {4, ´c´ ´a´ ´s´ ´a´} = {4, } La última posición de una cadena es indicada por un caracter especial. Ej: “casa” = ´c´ ´a´ ´s´ ´a´ 0 = Esta es la representación utilizada por el lenguaje C, siendo el marcador de final de string el valor 0.

125 Ejemplo: string_copy Suponga que tenemos el siguiente código:
void strcpy(char x[], char y[]) { int i; i = 0; while ((x[i] = y[i]) != 0) i = i + 1; } Vamos generar el código correspondiente een assembly MIPS…..

126 Ejemplo: string copy Las direcciones base de x y de y están en $a0 y $a1, entretanto que i está en $s0. Requerimos entonces el valor de $s0: strcpy: addi $sp, $sp, -4 #espacio para 1 ítem en la pila sw $s0, 0($sp) # salva $s0 Inicializamos i con 0: add $s0, $zero, $zero # i = 0 + 0

127 Ejemplo: string copy Podemos hacer un lazo entonces; La dirección de y[i] es formada adicionando i con la dirección base de y: L1: add $t1, $a1, $s0 # $t1 = dirección de y[i] Por que no multiplicamos i por 4?? y es un vector de bytes, y no de palabras!!! Ahora cargamos el caracter y[i]: lb $t2, 0($t1) # $t2 = y[i]

128 Ejemplo: string copy Preparamos ahora la dirección de x[i] en $t3, y almacenamos y[i]: add $t3, $a0, $s0 # $t3 = direccíon de x[i] sb $t2, 0($t3) # x[i] = y[i] Si el caracter y[i] fuera 0, salimos del loop: beq $t2, $zero, L2 # se y[i] == 0, desvie para L2 Si no, incremente i e iteramos nuevamente: addi $s0, $s0, 1 # $s0 = $s0 + 1 j L1 # desvie para L1

129 Ejemplo: string copy Restauramos $s0, ajustamos $sp y retornamos:
L2: # fin del string lw $s0, 0($sp) # restaura $s0 addi $sp, $sp, 4 # retira un item de la pila jr $ra # retorna para el llamador Podríamos haber alocado el registrador $t0 para i, y en este caso no tendríamos que empilar y desempilar $s0. Percibimos que es mejor utilizar primero los registradores $t que $s en funciones que no llaman otra función.

130 Patrón Unicode Se está tornando cada vez mas común otro tipo de codificación para caracteres, el patrón Unicode. Java utiliza este patrón. Este patrón, de poder representar todos los caracteres latinos, puede representar símbolos de letras orientales, entre otros. Un caracter pasa a ocupar 16 bits. Cuantos símbolos se pueden representar? MIPS incluye instrucciones para trabajar con 16 bits, pero no estudiaremos. Tienen que consultarlas en el manual o en libro.

131 Visión General Arquitectura del Conjunto de Instrucciones (utilizando ISA del MIPS como ejemplo) Operandos y direccionamiento (Sec. 3.3, 3.8) Organización de los registradores Transferencia de memoria y direccionamiento Formato de instrucciones Operaciones Lógico-aritméticas Toma de decisiones e desvíos Jumps para procedimientos

132 Arquitectura de registradores
Pila (procesador Forth): una dirección: add tope  tope + próximo Acumulador (1 registrador - acc): 1 dirección: add A acc  acc + mem[A] 1+x direción: addx A acc  acc + mem[A+x] Registradores de propósito general (GPR): 2 direcciones: add A,B EA(A)  EA(A) + EA(B) 3 direcciones: add A,B,C EA(A)  EA(B) + EA(C) Load/Store: 3 address: add Ra,Rb,Rc Ra  Rb + Rc load Ra,Rb Ra  mem[Rb] store Ra,Rb mem[Rb]  Ra Invented index register Reverse polish stack = HP calculator GPR = last 20 years L/S variant = last 10 years

133 La organización de registradores afecta la programación
Código para C = A + B para 4 organizaciones de registradores.: Pilla Acumulador Registrador Registrador (reg-mem) (load-store) Push A Load A Load R1,A Load R1,A Push B Add B Add R1,B Load R2,B Add Store C Store C, R1 Add R3,R1,R2 Pop C Store C,R3 => La Organización de registradores es un atributo del ISA! Comparación: Bytes por instrucción? Número de instrucciones? Ciclos por instrucción? Desde 1975 casi todas las máquinas utilizam GPRs.

134 Other Kinds of Operands (Sec. 3.8)
Immediate: numerical constants Often appear in code, so there are special instructions for them Add Immediate: addi $s0,$s1,10 (in MIPS) f = g + 10 (in C) where $s0,$s1 are associated with f,g Syntax similar to add instruction, except that last argument is a number instead of a register One particular immediate, the number zero (0), appears very often in code; so we define register zero ($0 or $zero) to always 0 This is defined in hardware, so an instruction like addi $0,$0,5 will not do anything

135 Outline Instruction set architecture (using MIPS ISA as an example)
Operands and addressing Register organization Memory transfer and addressing Instruction format Operations Arithmetic and logical Decision making and branches Jumps for procedures

136 Addressing: Byte versus Word
Every word in memory has an address, similar to an index in an array Early computers numbered words like C numbers elements of an array: Memory[0], Memory[1], Memory[2], … Called the “address” of a word Computers needed to access 8-bit bytes as well as words (4 bytes/word) Today, machines address memory as bytes, hence word addresses differ by 4 Memory[0], Memory[4], Memory[8], … This is also why lw and sw use bytes in offset

137 MIPS Data Transfer Instructions
Instruction Comment SW 500(R4), R3 Store word SH 502(R2), R3 Store half SB 41(R3), R2 Store byte LW R1, 30(R2) Load word LH R1, 40(R3) Load halfword LHU R1, 40(R3) Load halfword unsigned LB R1, 40(R3) Load byte LBU R1, 40(R3) Load byte unsigned LUI R1, 40 Load Upper Immediate (16 bits shifted left by 16) What does it mean?

138 Load Byte Unsigned lbu $t2, 0($t0) $t0 $t1 $t2 F7 F0 12 … F7 F7 FFFFFF
(Make noise) Back row! You in the (describe clothing)! I do a load byte from t0 to t1. What do I get in t1? F7? Is there anything you would like to add to your statement? So your final answer is F7? (Alarm.wav) FFFFFF F7 Sign-extended lb $t1, 0($t0) lbu $t2, 0($t0) 000000 F7 Zero-extended

139 Addressing Modes Addressing mode Example Meaning
Register Add R4,R3 R4  R4+R3 Immediate Add R4,#3 R4  R4+3 Displacement Add R4,100(R1) R4  R4+Mem[100+R1] Register indirect Add R4,(R1) R4  R4+Mem[R1] Indexed / Base Add R3,(R1+R2) R3  R3+Mem[R1+R2] Direct / Absolute Add R1,(1001) R1  R1+Mem[1001] Memory indirect Add R1  R1+Mem[Mem[R3]] Auto-increment Add R1,(R2)+ R1  R1+Mem[R2] R2  R2+d Auto-decrement Add R1,-(R2) R2  R2-d R1  R1+Mem[R2] Scaled Add R1,100(R2)[R3] R1  R1+ Mem[100+R2+R3*d]

140 Outline Instruction set architecture (using MIPS ISA as an example)
Operands and addressing Register organization Memory transfer and addressing Instruction format (Sec. 3.4) Operations Arithmetic and logical Decision making and branches Jumps for procedures

141 I-Format Instructions
Define the following “fields”: opcode: uniquely specifies an I-format instruction rs: specifies the only register operand rt: specifies register which will receive result of computation (target register) addi, slti, slitu, immediate is sign-extended to 32 bits, and treated as a signed integer 16 bits  can be used to represent immediate up to 216 different values Key Concept: Only one field is inconsistent with R-format. Most importantly, opcode is still in same location 6 5 16 opcode rs rt immediate

142 I-Format Example MIPS Instruction: addi $21,$22,-50 opcode = 8 (look up in table) rs = 22 (register containing operand) rt = 21 (target register) immediate = -50 (by default, this is decimal) decimal representation: 8 22 21 -50 binary representation: 001000 10110 10101

143 I-Format Problem What if immediate is too big to fit in immediate field? Load Upper Immediate: lui register, immediate puts 16-bit immediate in upper half (high order half) of the specified register, and sets lower half to 0s addi $t0,$t0, 0xABABCDCD becomes: lui $at, 0xABAB ori $at, $at, 0xCDCD add $t0,$t0,$at 0000 … 0000 LUI R1 R1

144 Outline Instruction set architecture (using MIPS ISA as an example)
Operands and addressing Register organization Memory transfer and addressing Instruction format Operations Arithmetic and logical Decision making and branches Jumps for procedures

145 MIPS Arithmetic Instructions
Instruction Example Meaning Comments add add $1,$2,$3 $1 = $2 + $3 3 operands; exception possible subtract sub $1,$2,$3 $1 = $2 ?$3 3 operands; exception possible add immediate addi $1,$2,100 $1 = $ constant; exception possible add unsigned addu $1,$2,$3 $1 = $2 + $3 3 operands; no exceptions subtract unsigned subu $1,$2,$3 $1 = $2 ?$3 3 operands; no exceptions add imm. unsign. addiu $1,$2,10 $1 = $ constant; no exceptions multiply mult $2,$3 Hi, Lo = $2 x $3 64-bit signed product mul. unsigned multu$2,$3 Hi, Lo = $2 x $3 64-bit unsigned product divide div $2,$3 Lo = $2 / $3, Lo = quotient, Hi = remainder Hi = $2 mod $3 divide unsigned divu $2,$3 Lo = $2 / $3, Unsigned quotient & remainder Move from Hi mfhi $1 $1 = Hi Used to get copy of Hi Move from Lo mflo $1 $1 = Lo Used to get copy of Lo

146 Bitwise Operations Up until now, we’ve done arithmetic (add, sub, addi ) and memory access (lw and sw) All of these instructions view contents of register as a single quantity (such as a signed or unsigned integer) New Perspective: View contents of register as 32 bits rather than as a single 32-bit number Since registers are composed of 32 bits, we may want to access individual bits rather than the whole. Introduce two new classes of instructions: Logical Operators Shift Instructions

147 Logical Operators Logical instruction syntax: Instruction names:
1 2,3,4 where 1) operation name 2) register that will receive value 3) first operand (register) 4) second operand (register) or immediate (numerical constant) Instruction names: and, or: expect the third argument to be a register andi, ori: expect the third argument to be immediate MIPS Logical Operators are all bitwise, meaning that bit 0 of the output is produced by the respective bit 0’s of the inputs, bit 1 by the bit 1’s, etc.

148 Uses for Logical Operators
AND operator can be used to set certain portions of a bitstring to 0s, while leaving the rest alone => mask Example: The result of anding these two is: In MIPS assembly: andi $t0,$t0,0xFFF Similarly, OR operator can be used to force certain bits of a string to 1s For example, if $t0 contains 0x , then after ori $t0, $t0, 0xFFFF $t0 contains 0x1234FFFF (e.g. the high-order 16 bits are untouched, while the low-order 16 bits are set to 1s) Mask:

149 Shift Instructions (1/3)
Move (shift) all the bits in a word to the left or right by a number of bits, filling the emptied bits with 0s. Example: shift right by 8 bits Example: shift left by 8 bits

150 Shift Instructions (2/3)
Shift Instruction Syntax: 1 2,3,4 where 1) operation name 2) register that will receive value 3) first operand (register) 4) second operand (register) MIPS has three shift instructions: sll (shift left logical): shifts left, fills empties with 0s srl (shift right logical): shifts right, fills empties with 0s sra (shift right arithmetic): shifts right, fills empties by sign extending

151 Shift Instructions (3/3)
Example: shift right arith by 8 bits

152 Uses for Shift Instructions (1/2)
Suppose we want to get byte 1 (bit 15 to bit 8) of a word in $t0. We can use: sll $t0,$t0,16 srl $t0,$t0,24

153 Uses for Shift Instructions (2/2)
Shift for multiplication: in binary Multiplying by 4 is same as shifting left by 2: 112 x 1002 = 11002 10102 x 1002 = Multiplying by 2n is same as shifting left by n Since shifting is so much faster than multiplication (you can imagine how complicated multiplication is), a good compiler usually notices when C code multiplies by a power of 2 and compiles it to a shift instruction: a *= 8; (in C) would compile to: sll $s0,$s0,3 (in MIPS)

154 MIPS Logical Instructions
Instruction Example Meaning Comment and and $1,$2,$3 $1 = $2 & $3 3 reg. operands; Logical AND or or $1,$2,$3 $1 = $2 | $3 3 reg. operands; Logical OR xor xor $1,$2,$3 $1 = $2 ?$3 3 reg. operands; Logical XOR nor nor $1,$2,$3 $1 = ~($2 |$3) 3 reg. operands; Logical NOR and immediate andi $1,$2,10 $1 = $2 & 10 Logical AND reg, zero exten. or immediate ori $1,$2,10 $1 = $2 | 10 Logical OR reg, zero exten. xor immediate xori $1, $2,10 $1 = ~$2 &~10 Logical XOR reg, constant shift left logical sll $1,$2,10 $1 = $2 << 10 Shift left by constant shift right logical srl $1,$2,10 $1 = $2 >> 10 Shift right by constant shift right arithm. sra $1,$2,10 $1 = $2 >> 10 Shift right (sign extend) shift left logical sllv $1,$2,$3 $1 = $2 << $3 Shift left by variable shift right logical srlv $1,$2, $3 $1 = $2 >> $3 Shift right by variable shift right arithm. srav $1,$2, $3 $1 = $2 >> $3 Shift right arith. by variable

155 Outline Instruction set architecture (using MIPS ISA as an example)
Operands and addressing Register organization Memory transfer and addressing Instruction format Operations Arithmetic and logical Decision making and branches (Sec. 3.5) Jumps for procedures

156 Immediate in Inequalities
There is also an immediate version of slt to test against constants: slti if (g >= 1) goto Loop Loop: slti $t0,$s0,1 # $t0 = 1 if $s0<1 (g<1) beq $t0,$0,Loop # goto Loop if $t0==0 Unsigned inequality: sltu, sltiu $s0 = FFFF FFFAhex, $s1 = 0000 FFFAhex slt $t0, $s0, $s1 => $t0 = ? sltu $t1, $s0, $s1 => $t1 = ? C M I P S

157 Branches: Instruction Format
Use I-format: opcode specifies beq v. bne Rs and Rt specify registers to compare What can immediate specify? Immediate is only 16 bits, but PC is 32-bit => immediate cannot specify entire address Loops are generally small: < 50 instructions Though we want to branch to anywhere in memory, a single branch only need to change PC by a small amount We can use PC-relative addressing 16-bit immediate as a signed two’s complement integer to be added to the PC if branch taken Now we can branch +/- 215 bytes from the PC opcode rs rt immediate

158 Branches: Instruction Format
Note: Instructions are word aligned (byte address is always a multiple of 4, i.e., it ends with 00 in binary) So the number of bytes to add to the PC will always be a multiple of 4 So specify the immediate in words (<= confusing?) Now, we can branch +/- 215 words from the PC (or +/- 217 bytes), so we can handle loops 4 times as large Final Calculation: If branch not taken: PC = PC + 4 If branch taken: PC = (PC+4) + (immediate*4) Immediate field specifies the number of words to jump, which is simply the number of instructions to jump. Immediate field can be positive or negative. Due to hardware, add immediate to (PC+4), not to PC

159 Branch Example MIPS Code: Branch is I-Format:
Loop: beq $9,$0,End add $8,$8,$ addi $9,$9, j Loop End: Branch is I-Format: opcode = 4 (look up in table) rs = 9 (first operand) rt = 0 (second operand) immediate = ??? Number of instructions to add to (or subtract from) the PC, starting at the instruction following the branch => immediate = 3

160 Branch Example 4 9 3 000100 01001 00000 0000000000000011 MIPS Code:
Loop: beq $9,$0,End addi $8,$8,$ addi $9,$9, j Loop End: decimal representation: binary representation: 4 9 3 000100 01001 00000

161 Branch Instructions: Summary
Compare and Branch: BEQ rs, rt, offset if R[rs] == R[rt] then PC-relative BNE rs, rt, offset != Compare to zero and Branch: BLEZ rs, offset if R[rs] <= 0 then PC-relative BGTZ rs, offset > BLTT rs, offset < BGEZ rs, offset >= BLTZAL rs, offset if R[rs] < 0 then branch and link BGEZAL rs, offset >= Almost all comparisons are against zero!

162 J-Format Instructions (1/3)
For branches, we assumed that we won’t want to branch too far, so we can specify change in PC. For general jumps (j and jal), we may jump to anywhere in memory. Ideally, we could specify a 32-bit memory address to jump to. Unfortunately, we can’t fit both a 6-bit opcode and a 32-bit address into a single 32-bit word, so we compromise.

163 J-Format Instructions (2/3)
Define “fields” of the following number of bits each: As usual, each field has a name: Key concepts: Keep opcode field identical to R-format and I-format for consistency Combine other fields to make room for target address Optimization: Note that, just like with branches, jumps will only jump to word aligned addresses, so last two bits are always 00 (in binary) => specify 28 bits of the 32-bit bit address 6 bits 26 bits opcode target address

164 J-Format Instructions (3/3)
Where do we get the other 4 bits? By definition, take the 4 highest order bits from the PC Technically, this means that we cannot jump to anywhere in memory, but it’s adequate …% of the time, since programs aren’t that long If we absolutely need to specify a 32-bit address, we can always put it in a register and use the jr instruction Summary: New PC = PC[31..28] || target address (26 bits) || 00 Note: II means concatenation 4 bits || 26 bits || 2 bits = 32-bit address Understand where each part came from!

165 MIPS Jump, Branch, Compare
Instruction Example Meaning branch on equal beq $1,$2,25 if ($1 == $2) go to PC Equal test; PC relative branch branch on not eq. bne $1,$2,25 if ($1!= $2) go to PC Not equal test; PC relative set on less than slt $1,$2,$3 if ($2 < $3) $1=1; else $1=0 Compare less than; 2’s comp. set less than imm. slti $1,$2,100 if ($2 < 100) $1=1; else $1=0 Compare < constant; 2’s comp. set less than uns. sltu $1,$2,$3 if ($2 < $3) $1=1; else $1=0 Compare less than; natural numbers set l. t. imm. uns. sltiu $1,$2,100 if ($2 < 100) $1=1; else $1=0 Compare < constant; 2’s comp. jump j go to bit+4-bit of PC jump register jr $31 go to $31 For switch, procedure return jump and link jal $31 = PC + 4; go to For procedure call

166 Outline Instruction set architecture (using MIPS ISA as an example)
Operands and addressing Register organization Memory transfer and addressing Instruction format Operations Arithmetic and logical Decision making and branches Jumps for procedures (Sec. 3.6)

167 Miscellaneous MIPS Instructions
break A breakpoint trap occurs, transfers control to exception handler syscall A system trap occurs, transfers control to exception handler coprocessor inst. Support for floating point TLB instructions Support for virtual memory restore from exception Restores previous interrupt mask & kernel/user mode bits into status register load word left/right Supports misaligned word loads store word left/right Supports misaligned word stores

168 Summary: Typical Operations
Data Movement load (from memory) store (to memory) memory-to-memory move register-to-register move input (from I/O device) output (to I/O device) push, pop (to/from stack) Arithmetic integer (binary + decimal) or FP add, subtract, multiply, divide Shift shift left/right, rotate left/right Logical not, and, or, set, clear Control (jump/branch) unconditional, conditional Subroutine linkage call, return Interrupt trap, return Synchronization test & set (atomic r-m-w) String search, translate

169 Top 10 80x86 Instructions Help to identify common cases!
Rank Instruction % of Total load % 2 conditional branch % 3 compare % 4 store % 5 add % 6 and % 7 sub % 8 move register-register % 9 call % return % Total % Help to identify common cases! Simple instructions dominate instruction frequency

170 Summary: MIPS ISA (1/2) 32-bit fixed format instructions (3 formats)
32 32-bit GPR (R0 = zero), 32 FP registers, (and HI LO) partitioned by software convention 3-address, reg-reg arithmetic instructions Memory is byte-addressable with a single addressing mode: base+displacement 16-bit immediate plus LUI Decision making with conditional branches: beq, bne Often compare against zero or two registers for = To help decisions with inequalities, use: “Set on Less Than”called slt, slti, sltu, sltui Jump and link puts return address PC+4 into link register (R31) Branches and Jumps were optimized to address to words, for greater branch distance

171 Summary: MIPS ISA (2/2) opcode rs rt rd funct shamt immediate R I
Immediates are extended as follows: logical immediate: zero-extended to 32 bits arithmetic immediate: sign-extended to 32 bits Data loaded by lb and lh are similarly extended: lbu, lhu are zero extended; lb, lh are sign extended Simplifying MIPS: Define instructions to be same size as data (one word), so they can use same memory Stored Program Concept: Both data and actual code (instructions) are stored in the same memory Instructions formats are kept as similar as possible opcode rs rt rd funct shamt immediate R I target address J


Descargar ppt "Conjunto de Instrucciones"

Presentaciones similares


Anuncios Google