Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Cap3.2 Mips Como Estandar Isa

Descargar como pptx, pdf o txt
Descargar como pptx, pdf o txt
Está en la página 1de 95

INF60500 - Arquitectura de

computadores
Depto. de Informática y Computación
Segundo semestre 2019

Apuntes: Leonardo Bravo & Jorge Vergara


Profesor: Jaime Rodríguez B.
Conjunto de Instrucciones

● ISA: “Instruction Set Architecture”


● El repertorio de instrucciones de un computador
● Diferentes computadores tienen diferentes conjuntos de instrucciones
○ Pero con muchos aspectos en común
● Los primeros computadores tenían conjuntos de instrucciones muy simples
○ Implementación simplificada
● Muchos computadores modernos también tienen conjunto de instrucciones simples
El Conjunto de Instrucciones MIPS

● Utilizados como ejemplos a través del curso


● MIPS de Stanford comercializado por MIPS Technologies (www.mips.com)
● Compartido largamente por mercado de núcleos incrustados
○ Aplicaciones en electrónica de consumo, equipos de redes/almacenamiento,
cámaras, impresoras, …
● Típico de muchos ISAs modernos
○ Ver MIPS Reference Data, y Apéndices B y E del libro de referencia de
Patterson & Hennessy
Operaciones Aritméticas

● Suma y resta, tres operandos


○ Dos fuentes y un destino
add a, b, c # a obtiene b + c
● Todas las operaciones aritméticas tienen esta forma
● Principio de Diseño 1: La simplicidad favorece la regularidad
○ La regularidad hace la implementación mas simple
○ La simplicidad permite altas performance a menor costo
Ejemplo de Aritmética

● Código C:

f = (g + h) - (i + j);
● Código MIPS compilado:

add t0, g, h # temp t0 = g + h


add t1, i, j # temp t1 = i + j
sub f, t0, t1 # f = t0 - t1
Operandos de Registros

● Instrucciones aritméticas utilizan operandos de registros


● MIPS tiene un archivo de registros de 32 × 32-bit
○ Utilizado para datos de acceso frecuente
○ Enumerados de 0 a 31
○ 32-bit de datos se llaman palabra (“word”)
● Nombres en Assembler
○ $t0, $t1, …, $t9 para valores temporales
○ $s0, $s1, …, $s7 para variables guardadas
● Principio de Diseño 2: El diseño más pequeño es más rápido
○ c.f. memoria principal: millones de posiciones
Ejemplo Operandos de Registros

● Código C:

f = (g + h) - (i + j);
○ f, …, j in $s0, …, $s4
● Código MIPS compilado :

add $t0, $s1, $s2


add $t1, $s3, $s4
sub $s0, $t0, $t1
Operandos de Memoria
● Memoria principal utilizada para combinar datos
○ Arreglos, estructuras, datos dinámicos
● Para realizar operaciones aritméticas
○ Cargar valores de memoria a registros
○ Guardar resultados de registros a memoria
● La memoria es direccionada por byte
○ Cada dirección identifica un byte de 8-bit
● Las palabras están alineadas en memoria
○ Las direcciones deben ser múltiplos de 4
● MIPS es “Big-Endian”
○ Byte más significativo en la dirección menor de la palabra
○ c.f. “Little-Endian”: byte menos significativo en la dirección menor de la palabra
“Big-Endian”/”Little-Endian”

Ultimo byte
Primer byte Bytes
Endian (dirección más Notas
(dirección más baja) intermedio
alta)

Similar a como se
big más significativo ... menos significativo escriben números
en un papel

Orden del cálculo


little menos significativo ... más significativo
aritmético
Ejemplo 1: Operandos de Memoria

● Código C:

g = h + A[8];
○ g en $s1, h en $s2, dirección base de A en $s3
● Código MIPS compilado:
○ Índice 8 requiere offset de 32
■ 4 bytes por palabra

lw $t0, 32($s3) # load word


add $s1, $s2, $t0
offset registro base
Ejemplo 2: Operandos de Memoria

● Código :

A[12] = h + A[8];
○ h en $s2, dirección base de A en $s3
● Código MIPS compilado :

○ Índice 8 requiere offset de 32

○ Índice 12 requiere offset de 48

lw $t0, 32($s3) # load word


add $t0, $s2, $t0
sw $t0, 48($s3) # store word
Registros vs. Memoria

● Registros son más rápidos de accesar que las memorias

● Operación en datos de memoria requiere cargar (“loads”) y guardar (“stores”)

○ Más instrucciones a ser ejecutadas

● El compilador debe utilizar los registros para las variables tanto como sea posible

○ Solamente utilizar la memoria con variables de uso menos frecuente

○ Es importante la optimización del uso de los registros!


Operadores Inmediatos

● Dato constante especificado en una instrucción

addi $s3, $s3, 4


● No hay instrucción de resta inmediata

○ Utilizar una constante negativa

addi $s2, $s1, -1


● Principio de Diseño 3: Hacer que los casos frecuentes sean rápidos

○ Son frecuentes las constantes pequeñas

○ Operandos inmediatos evitan las instrucciones de carga


La Constante Cero

● El registro 0 ($zero) de MIPS es la constante 0

○ No se puede escribir en él
● Útil para operaciones frecuentes

○ p.e., mover entre registros

add $t2, $s1, $zero


Enteros Binarios Sin Signo

● Dado un número de n-bit

 Rango: 0 a +2n – 1
 Ejemplo:
 0000 0000 0000 0000 0000 0000 0000 10112

= 0 + … + 1×23 + 0×22 +1×21 +1×20


= 0 + … + 8 + 0 + 2 + 1 = 1110
 Utilizando 32 bits
 0 a +4.294.967.295
Enteros Con Signo Complemento de 2

● Dado un número de n-bit

 Rango: –2n – 1 to +2n – 1 – 1


 Ejemplo:
 1111 1111 1111 1111 1111 1111 1111 11002

= –1×231 + 1×230 + … + 1×22 +0×21 +0×20


= –2,147,483,648 + 2,147,483,644 = –410
 Utilizando 32 bits
 –2,147,483,648 a +2,147,483,647
Enteros Con Signo Complemento de 2

● Bit 31 es bit de signo


○ 1 para números negativos
○ 0 para números no-negativos
● –(–2n – 1) no puede ser representado
● Números no-negativos tienen la misma representación de los números sin signo y
complemento de 2
● Algunos números específicos:
○ 0: 0000 0000 … 0000
○ –1: 1111 1111 … 1111
○ El más negativo: 1000 0000 … 0000
○ El más positivo: 0111 1111 … 1111
Negación Con Signo

● Complementar y agregar 1

○ Complementar significa 1 → 0, 0 → 1

• Ejemplo: negar +2

• +2 = 0000 0000 … 00102

• –2 = 1111 1111 … 11012 + 1

= 1111 1111 … 11102


Extensión del Signo
● Representar un número utilizando mas bits

○ Preserva el valor numérico

● En el set de instrucciones de MIPS

○ addi: extiende el valor inmediato

○ lb, lh: extiende byte/halfword cargado

○ beq, bne: extiende el desplazamiento

● Replica el bit de signo a la izquierda

○ c.f. valores sin signo: extiende con 0s

● Ejemplos: 8-bit a 16-bit

○ +2: 0000 0010 => 0000 0000 0000 0010

○ –2: 1111 1110 => 1111 1111 1111 1110


Representación de Instrucciones
● Las instrucciones son codificadas en binario

○ Llamadas código de máquina (“machine code”)

● Instrucciones de MIPS

○ Codificadas como palabras de instrucciones de 32-bit

○ Un pequeño numero de formatos codifica el código de operación (“opcode”),


número del registro, …

○ Regularidad!

● Numero de los Registros

○ $t0 – $t7 son los registros 8 – 15

○ $t8 – $t9 son los registros 24 – 25

○ $s0 – $s7 son los registros 16 – 23


Instrucciones Formato R de MIPS
op rs rt rd shamt funct
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits

● Campos de la Instrucción

○ op: código de operación (opcode)

○ rs: número registro primera fuente

○ rt: número registro segunda fuente

○ rd: número registro destino

○ shamt: cantidad desplazamiento (00000 por ahora)

○ funct: código de la función (extiende el opcode)


Ejemplo Formato R
op rs rt rd shamt funct
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits

add $t0, $s1, $s2

special $s1 $s2 $t0 0 add

0 17 18 8 0 32

000000 10001 10010 01000 00000 100000

000000100011001001000000001000002 = 0232402016
Hexadecimal

● Base 16
○ Representación compacta de un conjunto de bits
○ 4 bits por dígito hexadecimal
0 0000 4 0100 8 1000 c 1100
1 0001 5 0101 9 1001 d 1101
2 0010 6 0110 a 1010 e 1110
3 0011 7 0111 b 1011 f 1111
• Ejemplo: eca8 6420
• 1110 1100 1010 1000 0110 0100 0010 0000
Instrucciones Formato I de MIPS
op rs rt constante o dirección
6 bits 5 bits 5 bits 16 bits

● Instrucciones de aritmética inmediata y de “load/store”


○ rt: numero del registro de destino o fuente
○ Constante: –215 to +215 – 1
○ Dirección: offset agregado a la dirección base en rs
● Principio de Diseño 4: Buenos diseños requieren buenos compromisos
○ Diferentes formatos complican la decodificación, pero permiten uniformidad en
las instrucciones de 32-bit
○ Mantener los formatos tan similares como sea posible
Computadores de Programas Almacenados
El cuadro global
● Instrucciones representadas en binario,
como datos
● Instrucciones y datos almacenados en
memoria
● Programas pueden operar en programas
○ e.g., compiladores, “linkers”, …
● Compatibilidad binaria permite a los
programas compilados funcionar en
diferentes computadores
○ ISAs estandarizados
Operaciones Lógicas
● Instrucciones para manipulación a nivel de bit

Operación C Java/Python MIPS


Shift left << << sll
Shift right >> >> srl
Bitwise AND & & and,andi
Bitwise OR | | or,ori
Bitwise NOT ~ ~ nor

Ø Utilizado para extraer e insertar grupos de bits en una palabra


Operaciones de Desplazamiento (“Shift”)

op rs rt rd shamt funct
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits

● shamt: cuantas posiciones a desplazar


● Desplazamiento lógico a la izquierda

○ Desplazar a la izquierda y llenar con 0 bits

○ sll por i bits multiplica por 2i


● Desplazamiento lógico a la derecha

○ Desplazar a la derecha y llenar 0 bits

○ srl por i bits divide por 2i (sin signo solamente)


Operaciones AND

● Utilizado para enmascarar bits en una palabra


○ Selecciona algunos bits, y pone otros en 0
and $t0, $t1, $t2

$t2 0000 0000 0000 0000 0000 1101 1100 0000

$t1 0000 0000 0000 0000 0011 1100 0000 0000

$t0 0000 0000 0000 0000 0000 1100 0000 0000


Operaciones OR

● Utilizado para incluir bits en una palabra


○ Poner algunos bits en 1, dejar otros sin cambiar
or $t0, $t1, $t2

$t2 0000 0000 0000 0000 0000 1101 1100 0000

$t1 0000 0000 0000 0000 0011 1100 0000 0000

$t0 0000 0000 0000 0000 0011 1101 1100 0000


Operaciones NOT

● Utilizado para invertir bits en una palabra


○ Cambia 0 a 1, y 1 a 0
● MIPS tiene instrucción NOR de 3 operandos
○ a NOR b == NOT ( a OR b )
nor $t0, $t1, $zero
Registro 0: siempre se
lee como cero

$t1 0000 0000 0000 0000 0011 1100 0000 0000

$t0 1111 1111 1111 1111 1100 0011 1111 1111


Operaciones Condicionales

● Salto a una instrucción rotulada si una condición es verdadera


○ De lo contrario, continua secuencialmente
● beq rs, rt, L1
○ si (rs == rt) salte a instrucción rotulada L1;
● bne rs, rt, L1
○ si (rs != rt) salte a instrucción rotulada L1;
● j L1
○ salto incondicional a instrucción rotulada L1
Compilación de Declaración If

● Código C:
if (i==j) f = g+h;
else f = g-h;
○ f, g, … en $s0, $s1, …
● Código MIPS compilado:
bne $s3, $s4, Else
add $s0, $s1, $s2
j Exit
Else: sub $s0, $s1, $s2
El Assembler calcula las direcciones
Exit: …
Compilación de Declaración Loop

● Código C:
while (save[i] == k) i += 1;
○ i en $s3, k en $s5, dirección a guardar en $s6
● Código MIPS compilado:
Loop: sll $t1, $s3, 2
add $t1, $t1, $s6
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit: …
Bloques Básicos

 Un bloque básico es una secuencia de instrucciones:


 sin saltos condicionales internos (excepto al final)
 sin saltos condicionales objetivos (excepto al comienzo)

 Un compilador identifica bloques básicos para


la optimización
 Un procesador avanzado puede acelerar la
ejecución de bloques básicos
Más Operaciones Condicionales

● Resultado en 1 si una condición es verdadera


○ De lo contrario, es 0
● slt rd, rs, rt
○ if (rs < rt) rd = 1; else rd = 0;
● slti rt, rs, constant
○ if (rs < constant) rt = 1; else rt = 0;
● Se utiliza en combinación con beq, bne
slt $t0, $s1, $s2 # si ($s1 < $s2)
bne $t0, $zero, L # salto a L
Diseño de una Instrucción Salto (“Branch”)

● ¿Por qué no blt, bge, etc.?


● Hardware para <, ≥, … es mas lento que =, ≠
○ Combinando con saltos implica más trabajo por instrucción, requiriendo un reloj
más lento
○ Se perjudican todas las instrucciones!
● beq y bne son el caso común
● Este es un buen compromiso de diseño
Con Signo vs. Sin Signo

● Comparación Con Signo: slt, slti


● Comparación Sin Signo: sltu, sltui
● Ejemplos:
○ $s0 = 1111 1111 1111 1111 1111 1111 1111 1111
○ $s1 = 0000 0000 0000 0000 0000 0000 0000 0001
○ slt $t0, $s0, $s1 # con signo
■ –1 < +1  $t0 = 1
○ sltu $t0, $s0, $s1 # sin signo
■ +4,294,967,295 > +1  $t0 = 0
Llamados a Procedimientos

● Pasos requeridos

1. Poner parámetros en registros

2. Transferir control al procedimiento

3. Obtener almacenamiento para el procedimiento

4. Realizar las operaciones del procedimiento

5. Poner resultado en un registro para el programa que llama

6. Retornar al lugar de la llamada


Uso de Registros

● $a0 – $a3: argumentos (registros 4 – 7)


● $v0, $v1: resultado valores (registros 2 and 3)
● $t0 – $t9: temporales

○ Pueden ser modificados por el programa llamado


● $s0 – $s7: guardados

○ Deben ser guardados/recuperados por el programa llamado


● $gp: puntero global para datos estáticos (reg. 28)
● $sp: puntero de stack (“stack pointer” (reg. 29))
● $fp: puntero de trama (“frame pointer” (reg. 30))
● $ra: dirección de retorno (“return address” (reg. 31)
Instrucciones para Llamados de Procedimientos

● Llamada Procedimiento: salto y vínculo


jal ProcedureLabel
○ Dirección de la siguiente instrucción puesta en $ra
○ Saltos a direcciones puntuales
● Retorno de Procedimiento: registro de salto
jr $ra
○ Copia $ra al contador de programa
○ Puede también ser utilizado para saltos calculados
■ e.g., para declaraciones case/switch
Ejemplo Procedimiento “Leaf”

● Código C:

int leaf_example (int g, h, i, j)


{ int f;
f = (g + h) - (i + j);
return f;
}
○ Argumentos g, …, j en $a0, …, $a3

○ f en $s0 (por lo tanto, se necesita guardar $s0 en el stack)

○ Resultado en $v0
Ejemplo Procedimiento “Leaf”

● Código MIPS:
leaf_example:
addi $sp, $sp, -4
sw $s0, 0($sp) Guarda $s0 en el stack

add $t0, $a0, $a1 Cuerpo del procedimiento

add $t1, $a2, $a3


sub $s0, $t0, $t1
Resultado
add $v0, $s0, $zero
Recupera $s0
lw $s0, 0($sp)
addi $sp, $sp, 4
Retorno
jr $ra
Procedimientos “Non-Leaf”

● Procedimientos que llaman a otros procedimientos


● Para llamadas anidadas, el que llama necesita guardar en el stack:
○ Su dirección de retorno
○ Cualquier argumento y variables temporales que se necesitaran después del
llamado
● Recuperar del stack después del llamado
Ejemplo Procedimientos “Non-Leaf”

● Código C:
int fact (int n)
{
if (n < 1) return (1);
else return (n * fact(n - 1));
}
○ Argumento n en $a0
○ Resultado en $v0
Ejemplo Procedimientos “Non-Leaf”
● Código MIPS:
fact:
addi $sp, $sp, -8 # ajusta stack para 2 ítems
sw $ra, 4($sp) # guarda dirección de retorno
sw $a0, 0($sp) # guarda argumento
slti $t0, $a0, 1 # testea para n < 1
beq $t0, $zero, L1 # salta a L1 si n >= 1
addi $v0, $zero, 1 # si n < 1, resultado es 1
addi $sp, $sp, 8 # saca 2 ítems del stack
jr $ra # y retorna
L1: addi $a0, $a0, -1 # si n >= 1, decrementa n
jal fact # llamada recursiva para (n-1)
lw $a0, 0($sp) # recupera n original
lw $ra, 4($sp) # y dirección de retorno
addi $sp, $sp, 8 # saca 2 ítems del stack
mul $v0, $a0, $v0 # multiplica para obtener
# resultado
jr $ra # y retorna
Datos Locales en el Stack

● Datos locales guardados por el programa llamado


○ p.e., variables automáticas de C
● Trama del procedimiento (registro de activación)
○ Utilizado por algunos compiladores para administrar el almacenamiento del
stack
Esquema de la Memoria

● Text: código de programa


● Static data: variables globales
○ p.e., variables estáticas en C, arreglos de
constantes y cadenas de caracteres
○ $gp inicializada en una dirección que
permite ±offsets en este segmento
● Dynamic data: “heap”
○ e.g., malloc en C, new en Java
● Stack: almacenamiento automático
Datos de Caracteres

● Conjunto de caracteres codificados en byte


○ ASCII: 128 caracteres
■ 95 gráficos, 33 control
○ Latin-1: 256 caracteres
■ ASCII, +96 más caracteres gráficos
● Unicode: conjunto de caracteres de 32 bit
○ Utilizado en Java, caracteres extendidos C++, …
○ La mayoría de los alfabetos del mundo, más símbolos
○ UTF-8, UTF-16: codificación de largo variable
ASCII: American Standard Code for Information
Interchange
Operaciones de Byte/”Halfword”

● Podrían utilizar operaciones “bitwise”


● Cargar/guardar byte/halfword MIPS
○ Procesamiento de cadenas de caracteres (“string”) es un caso común
lb rt, offset(rs) lh rt, offset(rs)
○ Extensión de signo a 32 bits en rt
lbu rt, offset(rs) lhu rt, offset(rs)
○ Cero extendido a 32 bits en rt
sb rt, offset(rs) sh rt, offset(rs)
○ Almacena sólo en lado derecho el byte/halfword
Ejemplo Copia de “String”

● Código C (simple):
○ “String” terminado en “Null”
void strcpy (char x[], char y[])
{ int i;
i = 0;
while ((x[i]=y[i])!='\0')
i += 1;
}
○ Direcciones de x, y en $a0, $a1
○ i en $s0
Ejemplo Copia de “String”

● Código MIPS:
strcpy:
addi $sp, $sp, -4 # ajusta stack para 1 ítem
sw $s0, 0($sp) # guarda $s0
add $s0, $zero, $zero # i = 0
L1: add $t1, $s0, $a1 # dirección de y[i] en $t1
lbu $t2, 0($t1) # $t2 = y[i]
add $t3, $s0, $a0 # dirección de x[i] en $t3
sb $t2, 0($t3) # x[i] = y[i]
beq $t2, $zero, L2 # salir del loop si y[i] == 0

addi $s0, $s0, 1 # i = i + 1


j L1 # siguiente iteración del loop
L2: lw $s0, 0($sp) # recupera $s0 guardado
addi $sp, $sp, 4 # sacar 1 ítem del stack
jr $ra # y retorna
Constantes de 32 bit

● La mayoría de las constantes son pequeñas


○ Inmediato de 16 bit es suficiente
● Para las constantes ocasionales de 32 bit
lui rt, constant
○ Copia constante de 16 bit en los 16 bits de la izquierda de rt
○ Limpia los 16 bits de la derecha rt con 0

lhi $s0, 61 0000 0000 0011 1101 0000 0000 0000 0000

ori $s0, $s0, 2304 0000 0000 0011 1101 0000 1001 0000 0000
Direccionamiento Salto Condicional

● Especificar instrucciones de salto


○ Opcode, dos registros, dirección objetivo
● La mayoría de los saltos son direcciones cercanas
○ Hacia adelante o hacia atrás

op rs rt constante o dirección
6 bits 5 bits 5 bits 16 bits

• Direccionamiento relativo al PC
• Dirección objetivo = PC + offset × 4
• PC ya incrementado por 4
Direccionamiento Salto Incondicional

● Saltos (j y jal) podrían ser a cualquier parte del segmento texto

○ Codificar la dirección completa en la instrucción

op dirección
6 bits 26 bits

• (Seudo) Direccionamiento salto directo

• Dirección objetivo = PC31…28 : (dirección × 4)


Ejemplo Direccionamiento Objetivo

● Código de Loop de ejemplo anterior

○ Supongamos Loop en ubicación 80000

Loop: sll $t1, $s3, 2 80000 0 0 19 9 4 0


add $t1, $t1, $s6 80004 0 9 22 9 0 32
lw $t0, 0($t1) 80008 35 9 8 0
bne $t0, $s5, Exit 80012 5 8 21 2
addi $s3, $s3, 1 80016 8 19 19 1
j Loop 80020 2 20000
Exit: … 80024
Salto Condicional a posiciones lejanas

● Si el salto condicional esta muy lejos para ser codificado con un offset de 16 bits, el
assembler rescribe el código
● Ejemplo:

beq $s0,$s1, L1

bne $s0,$s1, L2
j L1
L2: …
Resumen Modos de Direccionamiento
MARS 4.5

● MIPS Assembly and Runtime Simulator


● Release 4.5, Agosto 2014
● Ensambla y simula la ejecución de programas en “assembly language” del procesador
MIPS
● MARS ensambla y simula 155 instrucciones básicas del conjunto de instrucciones
MIPS-32, aproximadamente 370 seudo-instrucciones, 17 funciones “syscall”
principalmente para consola y E/S de archivos, definido por SPIM y 22 “syscall”
adicionales para otros usos como MIDI de salida, generación de números aleatorios,
etc.
● Puede utilizarse desde una línea de comandos o a través de su entorno de desarrollo
integrado (IDE)
● http://courses.missouristate.edu/kenvollmar/mars/
MARS - Edit
MARS - Execute
Sincronización

● Dos procesadores compartiendo un área de memoria


○ P1 escribe, luego P2 lee
○ “Data race” si P1 y P2 no se sincronizan
■ Resultado depende del orden de los accesos
● Se requiere soporte de hardware
○ Operación “atomic” de lectura/escritura de memoria
○ No se permiten otros accesos a la posición de memoria entre la lectura y
escritura
● Podría ser una instrucción única
○ P.e., intercambio “atomic” de registro ↔ memoria
○ O un par “atomic” de instrucciones
Sincronización en MIPS

● Load linked: ll rt, offset(rs)


● Store conditional: sc rt, offset(rs)
○ Tiene éxito si la posición no cambia desde el ll
■ Retorna 1 en rt
○ Falla si posición es cambiada
■ Retorna 0 en rt
● Ejemplo: “atomic swap” (para testear/bloquear una variable)
try: add $t0,$zero,$s4 ;copia valor de intercambio
ll $t1,0($s1) ;load linked
sc $t0,0($s1) ;store conditional
beq $t0,$zero,try ;salta si el guardar falla
add $s4,$zero,$t1 ;pone valor de carga en $s4
Traducción y Ejecución de un Programa C
Muchos compiladores producen
directamente módulos objeto

“Static linking”
Pseudo Instrucciones de Assembler
● La mayoría de las instrucciones de assembler representan una a una instrucciones de
máquina
● Pseudo instrucciones: ficción de la imaginación del assembler

move $t0, $t1 → add $t0, $zero, $t1


blt $t0, $t1, L → slt $at, $t0, $t1
bne $at, $zero, L
○ $at (register 1): registro temporal del assembler
Generación de un Módulo Objeto

● El Assembler (o el compilador) traduce el programa en instrucciones de máquina


● Provee la información para construir un programa completo desde sus partes
○ “Header”: describe contenido del modulo objeto
○ “Text segment”: instrucciones traducidas
○ “Static data segment”: datos asignados para la vida del programa
○ “Relocation info”: para contenidos que dependen de la posición absoluta del
programa cargado
○ “Symbol table”: definiciones globales y referencias externas
○ “Debug info”: para asociaciones con el código fuente
Vinculaciones (“Linking”) de los Módulos Objeto

● Produce una imagen ejecutable


1. Combina segmentos
2. Resuelve los rótulos (determina sus direcciones)
3. Repara las referencias dependientes de la posición y las externas
● Podría dejar las dependencias de posición para ser abordado por un “relocating
loader”
○ Pero con memoria virtual, esto no se necesita
○ El programa se puede cargar en posiciones absolutas en un espacio de memoria
virtual
Carga de un Programa

● Cargar en memoria archivo imagen desde disco


1. Leer el “header” para determinar tamaños de los segmentos
2. Crear espacio de direcciones virtuales
3. Copiar texto e inicializar datos en memoria
■ O establecer las entradas de tabla de página para que pueden funcionar en
ellas
4. Establecer los argumentos en el stack
5. Inicializar registros (incluyendo $sp, $fp, $gp)
6. Saltar a la rutina de partida
■ Copia argumentos a $a0, … y llama al programa principal
■ Cuando el programa principal retorna, salir a syscall
Vinculación Dinámica

● Vincular/cargar procedimientos de librería solo cuando sean llamados


○ Requiere que los códigos de los procedimientos sean reubicables
○ Evita que la imagen se expanda causado por el “static linking” de todas las
librerías (temporalmente) referenciadas
○ Carga automáticamente nuevas versiones de librerías
“Lazy Linkage”

Tabla direcciones
indirectas

Stub: Carga ID rutina,


Salto a linker/loader

Código Linker/loader

Código dinámicamente
mapeado
Ejecución de una Aplicación Java

Conjunto instrucciones
simples portables para
JVM

Compila
bytecodes de Interpreta
métodos “hot” bytecodes
en código nativo
para maquina
anfitriona
Ejemplo Sort en C

● Ilustra el uso de instrucciones de lenguaje assembly para una parte de la función sort
en C
● Procedimiento Swap (“leaf”)
void swap(int v[ ], int k)
{
int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
○ v en $a0, k en $a1, temp en $t0
El procedimiento Swap

swap: sll $t1, $a1, 2 # $t1 = k * 4


add $t1, $a0, $t1 # $t1 = v+(k*4)
# (dirección de v[k])
lw $t0, 0($t1) # $t0 (temp) = v[k]
lw $t2, 4($t1) # $t2 = v[k+1]
sw $t2, 0($t1) # v[k] = $t2 (v[k+1])
sw $t0, 4($t1) # v[k+1] = $t0 (temp)
jr $ra # retorna a rutina llamante
El procedimiento Sort en C
● “Non-leaf” (llama a swap)
void sort (int v[], int n)
{
int i, j;
for (i = 0; i < n; i += 1) {
for (j = i – 1;
j >= 0 && v[j] > v[j + 1];
j -= 1) {
swap(v,j);
}
}
}
○ v en $a0, k en $a1, i en $s0, j en $s1
El Cuerpo del Procedimiento
move $s2, $a0 # guarda $a0 en $s2
move $s3, $a1 # guarda $a1 en $s3 Mueve
move $s0, $zero # i = 0 parámetros
for1tst: slt $t0, $s0, $s3 # $t0 = 0 si $s0 ≥ $s3 (i ≥ n) Loop externo
beq $t0, $zero, exit1 # ir a exit1 si $s0 ≥ $s3 (i ≥ n)
addi $s1, $s0, –1 # j = i – 1
for2tst: slti $t0, $s1, 0 # $t0 = 1 si $s1 < 0 (j < 0)
bne $t0, $zero, exit2 # ir a exit2 si $s1 < 0 (j < 0)
sll $t1, $s1, 2 # $t1 = j * 4
Loop interno
add $t2, $s2, $t1 # $t2 = v + (j * 4)
lw $t3, 0($t2) # $t3 = v[j]
lw $t4, 4($t2) # $t4 = v[j + 1]
slt $t0, $t4, $t3 # $t0 = 0 si $t4 ≥ $t3
beq $t0, $zero, exit2 # ir a exit2 if $t4 ≥ $t3
move $a0, $s2 Pasa
# 1er parámetro de swap es v (antiguo $a0)
move $a1, $s1 # 2do parámetro de swap es j parámetros
y llama
jal swap # llama procedimiento swap
addi $s1, $s1, –1 # j –= 1
j for2tst # salta a test loop interno Loop interno
exit2: addi $s0, $s0, 1 # i += 1
j for1tst # salta a test loop externo
Loop externo
El Procedimiento Completo

sort: addi $sp,$sp, –20 # hace espacio en stack para 5 registros


sw $ra, 16($sp) # guarda $ra en el stack
sw $s3,12($sp) # guarda $s3 en el stack
sw $s2, 8($sp) # guarda $s2 en el stack
sw $s1, 4($sp) # guarda $s1 en el stack
sw $s0, 0($sp) # guarda $s0 en el stack
… # cuerpo del procedimiento

exit1: lw $s0, 0($sp) # recupera $s0 del stack
lw $s1, 4($sp) # recupera $s1 del stack
lw $s2, 8($sp) # recupera $s2 del stack
lw $s3,12($sp) # recupera $s3 del stack
lw $ra,16($sp) # recupera $ra del stack
addi $sp,$sp, 20 # recupera puntero de stack
jr $ra # retorna a rutina llamante
Similitudes entre ARM y MIPS

● ARM: el núcleo incrustado más popular


● Conjunto de instrucciones similar a MIPS

ARM MIPS
Fecha anunciado 1985 1985
Tamano instrucciones 32 bits 32 bits
Espacio direcciones 32-bit flat 32-bit flat
Alineamiento de datos Alineado Alineado
Modos direccionamiento de datos 9 3
Registros 15 × 32-bit 31 × 32-bit
Entrada/salida Memory Memory
mapped mapped
Comparar y Saltos Condicionales en ARM

● Utiliza códigos de condiciones para el resultado de una instrucción aritmética/lógica


○ Negativo, cero, trasporte, overflow
○ Instrucciones de comparación que setean códigos de condiciones sin mantener el
resultado
● Cada instrucción puede ser condicional
○ 4 bits superiores de la palabra de instrucción: valor de condición
○ Puede evitar saltos condicionales sobre instrucciones solas
Codificación de Instrucciones
El ISA x86 de Intel
● Evolución con compatibilidad hacia atrás
○ 8080 (1974): microprocesador de 8 bit
■ Acumulador, mas 3 pares de registros índice
○ 8086 (1978): extensión de 16 bit del 8080
■ Conjunto de instrucciones complejas (CISC)
○ 8087 (1980): coprocesador de punto flotante
■ Agrega instrucciones FP y registro stack
○ 80286 (1982): direccionamiento de 24 bit, MMU
■ Mapeo de memoria segmentada y protección
○ 80386 (1985): extensión de 32 bit (ahora IA-32)
■ Modos y operación de direccionamiento adicionales
■ Mapeo de memoria paginada como también segmentos
El ISA x86 de Intel

● Evolución adicional…
○ i486 (1989): pipelined, caches en el chip y FPU
■ Competidores compatibles: AMD, Cyrix, …
○ Pentium (1993): superscalar, datapath de 64-bit
■ Ultimas versiones agregaron instrucciones MMX (Multi-Media eXtension)
■ El famoso problema FDIV
○ Pentium Pro (1995), Pentium II (1997)
■ Nuevas micro arquitecturas (véase Colwell, The Pentium Chronicles)
○ Pentium III (1999)
■ Se agrega SSE (Streaming SIMD Extensions) y registros asociados
○ Pentium 4 (2001)
■ Nueva micro arquitectura
■ Se agregan instrucciones SSE2
El ISA x86 de Intel
● Y más aún…
○ AMD64 (2003): arquitectura extendida a 64 bits
○ EM64T – Tecnología 64 bits Memoria Extendida (2004)
■ AMD64 adoptado por Intel (con refinamientos)
■ Se agregan instrucciones SSE3
○ Núcleo (“Core”) Intel (2006)
■ Added SSE4 instructions, virtual machine support
○ AMD64 (anunciado el 2007): instrucciones SSE5
■ Intel declina seguirlo, en vez de eso…
○ Advanced Vector Extension (anunciado el 2008)
■ Registros SSE más largos, mas instrucciones
● Si Intel no se extendía con la compatibilidad, sus competidores lo harían!
○ Elegancia técnica ≠ éxito en el mercado
Flynn’s Taxonomy (1966)

SISD: PC, Mainframes


MISD: Fault Tolerant Computers,
Space Shuttle
SIMD: Array Processors
MIMD: Multi-Core Superscalar
Processors
Registros Básicos del x86
Modos de Direccionamientos Básicos del x86

● Dos operandos por instrucción


Operando fuente/destino Segundo operando fuente
Registro Registro
Registro Inmediato
Registro Memoria
Memoria Registro
Memoria Inmediato

• Modos de direccionamiento de memoria


• Dirección en registro
• Dirección = Rbase + desplazamiento
• Dirección = Rbase + 2escala × Rindice (escala = 0, 1, 2, o 3)
• Dirección = Rbase + 2escala × Rindice + desplazamiento
Codificación Instrucción x86

● Codificación largo variable


○ Bytes postfijo especifican el
modo de direccionamiento
○ Bytes prefijo modifican la
operación
■ Largo del operando,
repetición, bloqueo, …
Implementación del IA-32

● Conjunto de instrucciones complejas hacen difícil la implementación


○ El hardware traduce las instrucciones a simples micro operaciones
■ Instrucciones simples: 1–1
■ Instrucciones complejas: 1–muchas
○ Micro-motor similar al RISC
○ La participación de mercado hace esto económicamente viable
● Performance comparable al RISC
○ Los compiladores evitan instrucciones complejas
Instrucciones ARM v8

● Al evolucionar a 64 bit, ARM hizo una completa renovación


● ARM v8 se parece más ahora a MIPS
○ Cambios de v7:
■ No hay campo de ejecución condicional
■ Campo Inmediato es una constante de 12 bit
■ Elimina múltiples “load/store”
■ PC no es más un GPR
■ El conjunto GPR se expande a 32
■ Modos de direccionamiento funcionan para todos los tamaños de palabras
■ Instrucción división
■ Instrucciones ‘”Branch if equal/branch if not equal”
Falacias

● Instrucciones poderosas  alta performance


○ Se requieren menos instrucciones
○ Pero instrucciones complejas son difíciles de implementar
■ Pueden disminuir la velocidad de todas las instrucciones, incluyendo las
más simples
○ Los compiladores son buenos haciendo códigos rápidos de instrucciones simples
● Utilizar código lenguaje assembly para lograr una alta performance
○ Pero los compiladores modernos son mejores con procesadores modernos
○ Mas líneas de código  mas errores y menor productividad
Falacias

● Compatibilidad hacia atrás  conjunto de instrucciones no cambia


○ Pero igual aumenta el numero de instrucciones

Conjunto
instrucciones x86
Errores

● Palabras secuenciales no están en direcciones secuenciales


○ Incrementa por 4, no por 1!
● Mantener un puntero en una variable automática después del retorno del
procedimiento
○ e.g., pasar un puntero hacia atrás vía un argumento
○ Los punteros se hacen inválidos cuando el stack “popped”
Comentarios de Conclusión

● Principios de diseño
1. La simplicidad favorece la regularidad
2. El diseño pequeño es mas rápido
3. Hacer mas rápido el caso común
4. Buenos diseños demandan buenos compromisos
● Capas de software/hardware
○ Compilador, assembler, hardware
● MIPS: típico de los ISAs RISC
○ c.f. x86
Comentarios de Conclusión

● Medición de la ejecución de las instrucciones MIPS en programas de benchmark


○ Considerar hacer rápido el caso común
○ Considerar compromisos

Clase instrucción Ejemplos MIPS SPEC2006 Int SPEC2006 FP


Aritmetica add, sub, addi 16% 48%
Transferencia lw, sw, lb, lbu, 35% 36%
datos lh, lhu, sb, lui
Logica and, or, nor, andi, 12% 4%
ori, sll, srl
Salto condicional beq, bne, slt, 34% 8%
slti, sltiu
Salto j, jr, jal 2% 0%
incondicional

También podría gustarte