Arquitetura e Organização de Computadores Capítulo 2 – Conjunto de Instruções • Material adaptado de: Patterson e Henessy, Computer Organization and Design 4th Edition 2 André Aziz ([email protected]) 21/11/2013 • É o repertório de instruções de um computador; • Computadores diferentes possuem conjuntos de instruções diferentes: • Mas em muitos aspectos eles são comuns; • Computadores antigos tinham conjuntos de instruções bem simples: • Implementação simplificada; • Muitos computadores modernos também possuem conjunto de instruções simplificados. Conjunto de Instruções - ISA André Aziz ([email protected]) 3 21/11/2013 • Usado como exemplo durante este curso; • Stanford MIPS comercializado pelo MIPS Technologies (www.mips.com); • Grande parte do mercado de sistemas embarcados: • Aplicações em Consumer Eletronics, Network/Storage, equipamentos, câmeras, impressoras, ... • Típico de muitos ISAs modernos: • Vejam MIPS Reference Data. MIPS Instruction Set André Aziz ([email protected]) 4 21/11/2013 • Todo computador deve ser capaz de executar operações aritméticas: • Notação da MIPS Assembly Language: add a, b, c instrui o computado a adicionar duas variáveis b e c e colocar o resultado da soma em a: a=b+c Operações Aritméticas André Aziz ([email protected]) 5 21/11/2013 • Essa notação é fixa, ou seja, sem variações. • Se você quiser fazer ... a=b+c+d+e então é necessário... add a, b, c add a, a, d add a, a, e # The sum of b and c is placed in a. # The sum of b, c, and d is now in a. # The sum of b, c, d, and e is now in a. Operações Aritméticas André Aziz ([email protected]) 6 21/11/2013 • “Simplicidade favorece a regularidade”; • Todas as operações aritméticas possuim o mesmo formato; • Regularidade faz implementação mais simples; • Simplicidade permite alto desempenho a um baixo custo. Princípio de Projeto 1 André Aziz ([email protected]) 7 21/11/2013 • Código C: f = (g + h) - (i + j); • Código compilado do MIPS: add t0, g, h add t1, i, j sub f, t0, t1 # temp t0 = g + h # temp t1 = i + j # f = t0 - t1 Exemplo: Operações aritméticas André Aziz ([email protected]) 8 21/11/2013 • Instruções aritméticas usam operandos que vem de registradores; • MIPS possui 32 x32-bit registradores (banco de registradores): • Usado para dados que são frequentemente utilizados; • Numerados de 0 a 31; • 32-bit de dados é chamado de “word”; • Nomes dos registradores: • $t0, $t1, ..., $t9 para dados temporários (variáveis do compilador); • $s0, $s1, ..., $s7 para dados não-temporários (variáveis do programador). Operandos em registradores André Aziz ([email protected]) 9 21/11/2013 • “Menor é mais rápido”; • Um número grande de registradores pode aumentar o tempo do ciclo de clock, tornando o sistema lento. Princípio de Projeto 2 André Aziz ([email protected]) 10 21/11/2013 • Código C: f = (g + h) - (i + j); • f, …, j in $s0, …, $s4 • Código compilado do MIPS: add $t0, $s1, $s2 add $t1, $s3, $s4 sub $s0, $t0, $t1 Exemplo: Operandos em registradores André Aziz ([email protected]) 11 21/11/2013 • Linguagens de programação possuem variáveis que contem dados simples, mas eles também tem estruturas de dados mais complexas (arrays e structures): • Podem conter mais dados do que o número de registradores em um computador. Como computadores podem representar e acessar grandes estruturas de dados? André Aziz ([email protected]) 12 21/11/2013 • Memória principal é usada para dados compostos: • Arrays, structures, dynamic data; • Para realizar operações aritméticas: • Carregar valores da memória em registadores; • Armazenar resultados do registrador na memória. • Memória é endereçada a bytes: • Cada endereço identifica unicamente um byte. Operandos na Memória André Aziz ([email protected]) 13 21/11/2013 • “Words” são alinhadas na memória: • Endereços tem que ser múltiplo de 4 (4 Bytes => 32 bits); • MIPS é Big Endian: • Byte mais significativo está no menor endereço da palavra; • OBS: Little Endian; Byte menos significativo está no menor endereço da palavra. Operandos na memória André Aziz ([email protected]) 14 21/11/2013 • Memória é um grande unidimensional array com o endereço atuando como índice deste array; • Inicia em 0. OBS: O que é a memória? André Aziz ([email protected]) 15 21/11/2013 • A instrução que copia dados da memória para os registradores é tradicionalmente chamada de load; • A que faz a operação inversa é chamada de store; • A instrução de load é composta pelo registrador destino, uma constante e registrador de base: • A soma da constante com o registrador base é utilizado para acessar a memória; • Instrução do MIPS é lw (load word). Carregar dados da memória André Aziz ([email protected]) 16 21/11/2013 • Código C: g = h + A[8]; • g in $s1, h in $s2, base address of A in $s3 • Código compilado do MIPS: • Índice 8 requer um deslocamento (offset) de 32 • 4 bytes por word lw $t0, 32($s3) # load word add $s1, $s2, $t0 offset base register Exemplo 1: Operandos na memória André Aziz ([email protected]) 17 21/11/2013 • Código C: A[12] = h + A[8]; • h está em $s2, endereço base de A está em $s3 • Código compilado para o MIPS: • Índice 8 requer um deslocamento (offset) de 32 • Índice 12 requer um deslocamento (offset) de 48 lw $t0, 32($s3) # load word add $t0, $s2, $t0 sw $t0, 48($s3) # store word Exemplo 2: Operandos na memória André Aziz ([email protected]) 18 21/11/2013 • São constantes especificadas em uma instrução: addi $s3, $s3, 4 • Não possui instrução de subtração com imediato: • Usar constantes negativas: addi $s2, $s1, -1 Operandos Imediatos André Aziz ([email protected]) 19 21/11/2013 • “Faça o caso comum mais rápido” • Pequenas constantes são comuns ao programas; • Operando imediato evita instruções de load. Princípio de Projeto 3 André Aziz ([email protected]) 20 21/11/2013 • O registrador 0 ($zero) é a constante 0: • Não pode ser sobrescrito; • Útil para operações comuns: • Ex: mover dados entre registradores: add $t2, $s1, $zero # move $s1 para $t2 A constante Zero André Aziz ([email protected]) 21 21/11/2013 NÚMEROS INTEIROS COM OU SEM SINAL 22 André Aziz ([email protected]) 21/11/2013 • Dado um número de n-bits: n 1 n 2 x x 2 x 2 x 2 x 2 n 1 n 2 0 1 1 0 • Alcance: 0 até 2n-1 • Exemplo: • 0000 0000 0000 0000 0000 0000 0000 10112 = 0 + … + 1×23 + 0×22 +1×21 +1×20 = 0 + … + 8 + 0 + 2 + 1 = 1110 • Para 32 bits: • 0 até +4.294.967.295 Números Inteiros Binários sem Sinal André Aziz ([email protected]) 23 21/11/2013 • Dado um número de n-bits: n 1 n 2 1 0 x x 2 x 2 x 2 x 2 n 1 n 2 1 0 • Alcance: -2n-1 até 2n-1 – 1 • Exemplo: • 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 • Para 32 bits: • -2.147.483.648 até +2.147.483.647 Inteiros em Complemento a 2 com Sinal André Aziz ([email protected]) 24 21/11/2013 • Bit 31 é o bit de sinal: • 1 para números negativo; • 0 para não números não-negativos; • -(-2n-1) não pode ser representado; • Números não-negativos tem a mesma representação em inteiros sem sinal e em complemento a dois; • Alguns números específicos: • 0: 0000 0000 … 0000 • –1: 1111 1111 … 1111 • Mais-negativo: 1000 0000 … 0000 • Mais-positivo: 0111 1111 … 1111 Inteiros em Complemento a 2 com Sinal André Aziz ([email protected]) 25 21/11/2013 • Complemento dos bits somados a 1: • Complemento significa: 1 → 0, 0 → 1 xx 1 1 1 1 ...1 1 1 1 2 x 1 x • Exemplo: negar +2 • +2 = 0000 0000 … 00102 • –2 = 1111 1111 … 11012 + 1 = 1111 1111 … 11102 Negação com Sinal André Aziz ([email protected]) 26 21/11/2013 • Representando um número utilizando mais bits: • Preservar o valor numérico; • No ISA do MIPS: • addi: estende o valor do imediato; • lb, lh: estende o valor do byte/halfword carregados; • beq, bne: estente o valor do deslocamento; • Replicar o valor do sinal para esquerda: • Valores sem sinal: sempre estender com 0s; • Exemplo: 8-bit para 16-bit • +2: 0000 0010 => 0000 0000 0000 0010 • –2: 1111 1110 => 1111 1111 1111 1110 Extensão de Sinal André Aziz ([email protected]) 27 21/11/2013 REPRESENTANDO INSTRUÇÕES 28 André Aziz ([email protected]) 21/11/2013 • Instruções são codificadas em binário (números): • Chamado de código de máquina: • Instruções do MIPS: • Codificadas como palavras de 32-bits; • Um pequeno número de formatos codificam o código da operação (opcode), números dos registadores, ... • Regularidade! • Números dos registradores: • $t0 - $t7 são os registradores números 8 – 15; • $t8 - $t9 são os registradores números 24 – 25; • $s0 - $s7 são os registradores números 16 – 23; Representação de uma instrução André Aziz ([email protected]) 29 21/11/2013 op rs rt rd shamt funct 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits • Campos da instrução: • • • • • • op: código da operação (opcode); rs: número do primeiro registrador fonte; rt: número do segundo registrador fonte; rd: número do registrador de destino; shamt: quantidade de shifs (00000 por enquanto); funct: código da função (estende o opcode). Instruções do formato R André Aziz ([email protected]) 30 21/11/2013 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 Exemplo do formato R André Aziz ([email protected]) 31 21/11/2013 • Base 16: • Representação compacta de cadeias de bits; • 4 bits por cada dígito hexadecimal; • Example: eca8 6420 • 1110 1100 1010 1000 0110 0100 0010 0000 Hexadecimal André Aziz ([email protected]) 32 21/11/2013 op rs rt constant or address 6 bits 5 bits 5 bits 16 bits • Operações aritméticas com imediatos e instruções de load/store: • rt: número do registrador destino ou fonte; • Constante: -215 até +215-1; • Endereço: deslocamento (offset) adicionado ao registrador base rs; Instruções do formato I André Aziz ([email protected]) 33 21/11/2013 • “Bons projetos demandam bons compromissos”; • Diferentes formatos complicam a decodificação das instruções, mas permite instruções do mesmo tamanho; • Mantenha os formatos das instruções o mais similar possível: • R-type (para registradores) ou R-format. • I-type (para imediatos) ou I-format. Princípio de Projeto 4 André Aziz ([email protected]) 34 21/11/2013 • Se $t1 tem o endereço base do array A e $s2 corresponde ao, então a sentença: é compilada para: lw add sw $t0,1200($t1) $t0,$s2,$t0 $t0,1200($t1) A[300] = h + A[300]; # Temporary reg $t0 gets A[300] # Temporary reg $t0 gets h + A[300] # Stores h + A[300] back into A[300] • Qual é o código de máquina para essas três instruções? Exemplo: Traduzindo Assembly para código de máquina André Aziz ([email protected]) 35 21/11/2013 The BIG Picture • Instruções são representados em binários, como os dados; • Instruções e dados são armazenados na memória; • Programas podem operar sobre programas; • Compatibilidade binária permite programas funcionarem em diferentes computadores • ISAs padronizados. Computadores com programas armazenados André Aziz ([email protected]) 36 21/11/2013 OPERAÇÕES LÓGICAS 37 André Aziz ([email protected]) 21/11/2013 • Instruções para manipulação da cadeia de bits: • Útil para extração ou inserção de grupos de bits em uma palavra. Operações Lógicas André Aziz ([email protected]) 38 21/11/2013 op rs rt rd shamt funct 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits • Desloca a cadeia de bits para esquerda ou direita; • shamt: número de bits para deslocar; • Shift Left Logical (sll): • Desloca para esquerda e preenche com zeros no final; • sll de i-bits multiplica a palavra por 2i; • Shift Right Logical (srl): • Desloca para direita e preenche com zeros no início; • srl de i-bits divide a palavra por 2i (só para números sem sinal). Operações de shift André Aziz ([email protected]) 39 21/11/2013 • Útil para mascarar bits em uma palavra: • Selecionar alguns bits, limpando os outros com 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 Operações de AND André Aziz ([email protected]) 40 21/11/2013 • Útil para incluir bits em uma palavra: • Seta alguns bits para 1 sem mudar os outros; 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 Operações de OR André Aziz ([email protected]) 41 21/11/2013 • Útil para inverter bits em uma palavra: • Muda 0 para 1, e 1 para 0; • MIPS tem uma operação de NOR com 3 operandos: • a NOR b == NOT (a OR b) nor $t0, $t1, $zero Register 0: always read as zero $t1 0000 0000 0000 0000 0011 1100 0000 0000 $t0 1111 1111 1111 1111 1100 0011 1111 1111 Operações de NOT André Aziz ([email protected]) 42 21/11/2013 INSTRUÇÕES PARA TOMAR DECISÕES 43 André Aziz ([email protected]) 21/11/2013 • O que diferencia um computador de uma calculadora simples é a habilidade de tomar decisões; • A tomada de decisão é representada em linguagens de programação através das sentenças de if, algumas vezes combinadas com sentenças de go to e rótulos (labels). O diferencial do computador André Aziz ([email protected]) 44 21/11/2013 • Desvia (branch) para um rótulo se a condição da instrução for verdadeiro: • Caso contrário, continua sequencialmente; • beq rs, rt, L1 • Se (rs == rt) então desvia para a instrução rotulada de L1; • bne rs, rt, L1 • Se (rs != rt) então desvia para a instrução rotulada de L1; • j L1 • Pulo (jump) incondicional para a instrução rotulada de L1. Operações condicionais André Aziz ([email protected]) 45 21/11/2013 • Código C: if (i==j) f = g+h; else f = g-h; • f, g, … em $s0, $s1, … • Código compilado do MIPS: bne $s3, $s4, Else add $s0, $s1, $s2 j Exit Else: sub $s0, $s1, $s2 Exit: … Assembler calculates addresses Exemplo: Compilando sentenças if André Aziz ([email protected]) 46 21/11/2013 • Código C: while (save[i] == k) i += 1; • i em $s3, k em $s5, endereço base do save está $s6 • Código compilado do MIPS: Loop: sll add lw bne addi j Exit: … $t1, $t1, $t0, $t0, $s3, Loop $s3, 2 $t1, $s6 0($t1) $s5, Exit $s3, 1 Exemplo: Compilando sentenças de Loop André Aziz ([email protected]) 47 21/11/2013 • Um bloco básico é uma sequência de instruções com: • Nenhuma instrução de desvio (exceto no final) • Nenhum alvo de uma instrução de desvio (exceto no começo) • Um compilador identifica blocos básicos para otimizações; • Um processador avançado pode acelerar a execução de um bloco básico. Blocos básicos André Aziz ([email protected]) 48 21/11/2013 • Seta o resultado para 1 se a condição é verdadeira: • Caso contrário, seta para 0; • slt rd, rs, rt • Se (rs < rt) então rd = 1, caso contrário rd = 0; • slti rt, rs, constante • Se (rs < constante) então rt = 1, caso contrário rt = 0; • Usado em combinação com beq, bne: • slt $t0, $s1, $s2 bne $t0, $zero, L # if ($s1 < $s2) # branch to L Mais operações condicionais André Aziz ([email protected]) 49 21/11/2013 • Por que não blt, bge, etc? • Hardware para <, ≥, … é mais lento que =, ≠ • Combinando isso com o branch em si envolve mais trabalho por instrução, levando um clock mais lento; • Todas as intruções seriam penalizadas! • beq e bne são os casos mais comuns; • Este é um bom compromisso de projeto (princípio 4); Projeto das instruções de desvio André Aziz ([email protected]) 50 21/11/2013 • Comparação com sinal: slt, slti • Comparação sem sinal: sltu, sltui • Exemplo: • $s0 = 1111 1111 1111 1111 1111 1111 1111 1111 • $s1 = 0000 0000 0000 0000 0000 0000 0000 0001 • slt $t0, $s0, $s1 # signed • –1 < +1 $t0 = 1 • sltu $t0, $s0, $s1 # unsigned • +4,294,967,295 > +1 $t0 = 0 Sinal vs. Sem sinal André Aziz ([email protected]) 51 21/11/2013 CHAMADA DE PROCEDIMENTOS 52 André Aziz ([email protected]) 21/11/2013 • Passos de uma chamada de procedimento: 1. Colocar parâmetros nos registradores; 2. Transferir o controle para o procedimento; 3. Adquirir espaço de armazenamento para o procedimento; 4. Executar as operações do procedimento; 5. Colocar o resultado em um registrador para quem chamou o procedimento; 6. Retornar para o local da chamada. Chamada de procedimento André Aziz ([email protected]) 53 21/11/2013 • $a0 – $a3: parâmetros (reg’s 4 – 7); • $v0, $v1: retorno (reg’s 2 e 3); • $t0 – $t9: temporários: • Podem ser sobrescritos pelo procedimento; • $s0 – $s7: “salvos” ou globais: • Devem ser salvos/recuperados pelo procedimento; • • • • $gp: Ponteiro global para dados estáticos (reg 28); $sp: Ponteiro da pilha (stack pointer) (reg 29); $fp: Ponteiro da janela (frame pointer) (reg 30); $ra: Endereço para retorno do procedimento (reg 31). Convenção: Uso de registradores André Aziz ([email protected]) 54 21/11/2013 • Chamada de procedimento: jump and link (pular e conectar): jal <rótulo> • Salva o endereço da instrução seguinte ao jal no $ra (link); • Pula para o endereço alvo (rótulo); • Retorno de procedimento: jump register (pular para o registrador): jr $ra • Copia $ra no contador de programa; Instruções para chamar procedimentos André Aziz ([email protected]) 55 21/11/2013 • C code: int leaf_exemple (int g, h, i, j) { int f; f = (g + h) - (i + j); return f; } • Parâmetros g, …, j em $a0, …, $a3 • f em $s0 (obriga a salvar $s0 na pilha) • Resultado em $v0 Exemplo: Chamada de procedimento “folha” André Aziz ([email protected]) 56 21/11/2013 • Código MIPS: leaf_example: addi $sp, $sp, -4 sw $s0, 0($sp) add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1 add $v0, $s0, $zero lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra Exemplo: Chamada de procedimento “folha” André Aziz ([email protected]) Save $s0 on stack Procedure body Result Restore $s0 Return 57 21/11/2013 • Procedimentos que chamam outros procedimentos; • Para uma chamada aninhada, os procedimentos devem salvar na pilha: • O seu endereço de retorno; • Quaisquer parâmetros e temporários que serão necessários após a chamada do outro procedimento; • Retirar dados da pilha após a chamada. Procedimentos não-”folha” André Aziz ([email protected]) 58 21/11/2013 • Código C: int fact (int n) { if (n < 1) return f; else return n * fact(n - 1); } • Parâmetros em $a0 • Resultado em $v0 Exemplo: Procedimento não”folha” André Aziz ([email protected]) 59 21/11/2013 • Código MIPS: fact: addi sw sw slti beq addi addi jr L1: addi jal lw lw addi mul jr $sp, $ra, $a0, $t0, $t0, $v0, $sp, $ra $a0, fact $a0, $ra, $sp, $v0, $ra $sp, -8 4($sp) 0($sp) $a0, 1 $zero, L1 $zero, 1 $sp, 8 $a0, -1 0($sp) 4($sp) $sp, 8 $a0, $v0 André Aziz ([email protected]) # # # # adjust stack for 2 items save return address save argument test for n < 1 # # # # # # # # # # if so, result is 1 pop 2 items from stack and return else decrement n recursive call restore original n and return address pop 2 items from stack multiply to get result and return 60 21/11/2013 ORGANIZAÇÃO DA MEMÓRIA 61 André Aziz ([email protected]) 21/11/2013 • Variáveis locais armazenadas pelo procedimento; • Janela do procedimento (frame): • Usado por alguns compiladores para gerenciar o armazenamento na pilha Dados locais na pilha André Aziz ([email protected]) 62 21/11/2013 • Text: código do programa; • Static Data: variáveis globais: • Ex. variáveis estáticas em C, arrays constantes e strings; • $gp inicializado para tratar endereços nesse segmento; • Dynamic Data: heap: • Ex. “malloc” em C, “new” em Java; • Stack: armazenamento automático; Layout da Memória André Aziz ([email protected]) 63 21/11/2013 MANIPULANDO DADOS 64 André Aziz ([email protected]) 21/11/2013 • Conjunto de caracteres codificados em bytes: • ASCII: 128 caracteres: • 95 gráficos, 33 de controle; • Latin-1: 256 caracteres: • ASCII. +96 caracteres gráficos; • Unicode: conjunto de caracteres de 32 bits: • Usado em Java, C++, ... • Maioria dos alfabetos mundiais, mais símbolos; • UTF-8, UTF-16: tamanhos variáveis de codificação. Caracteres André Aziz ([email protected]) 65 21/11/2013 • Load/store byte/halfword instruções do MIPS: • Utilizado principalmente para trabalhar com strings; • lb rt, offset(rs) lh rt, offset(rs) • Estende o sinal para 32 bits em rt • lbu rt, offset(rs) lhu rt, offset(rs) • Estende zero para 32 bits em rt • sb rt, offset(rs) sh rt, offset(rs) • Escreve o byte/halfword mais a direita de rt na memória. Operações com byte e meia-palavra André Aziz ([email protected]) 66 21/11/2013 • Código C: • String terminada em NULL; void strcpy (char x[], char y[]) { int i; i = 0; while ((x[i]=y[i])!='\0') i += 1; } • Endereços de x, y em $a0, $a1; • i em $s0. Exemplo: Copiar String André Aziz ([email protected]) 67 21/11/2013 • MIPS code: strcpy: addi sw add L1: add lbu add sb beq addi j L2: lw addi jr $sp, $s0, $s0, $t1, $t2, $t3, $t2, $t2, $s0, L1 $s0, $sp, $ra $sp, -4 0($sp) $zero, $zero $s0, $a1 0($t1) $s0, $a0 0($t3) $zero, L2 $s0, 1 0($sp) $sp, 4 # # # # # # # # # # # # # adjust stack for 1 item save $s0 i = 0 addr of y[i] in $t1 $t2 = y[i] addr of x[i] in $t3 x[i] = y[i] exit loop if y[i] == 0 i = i + 1 next iteration of loop restore saved $s0 pop 1 item from stack and return Exemplo: Copiar String André Aziz ([email protected]) 68 21/11/2013 • Maioria das constantes são pequenas: • Imediato de 16-bits é suficiente; • Para uma constante ocasional de 32-bits: lui rt, constant • Copia constante de 16 bits para a parte mais significativa do rt • Zera os 16 bits menos significativos. lhi $s0, 61 0000 0000 0111 1101 0000 0000 0000 0000 ori $s0, $s0, 2304 0000 0000 0111 1101 0000 1001 0000 0000 Constantes de 32-bits André Aziz ([email protected]) 69 21/11/2013 ENDEREÇAMENTO DE DESVIOS 70 André Aziz ([email protected]) 21/11/2013 • As instruções de desvio especificam: • Opcode, dois registradores, endereço alvo; • Maioria dos desvios são desvios curtos: • Para cima ou para baixo: op rs rt constant or address 6 bits 5 bits 5 bits 16 bits • Endereçamento relativo ao contador de programa (PC): • Endereço Alvo = PC + (offset x 4); • OBS: PC já incrementado de 4. Endereçamento de desvios condicionais (branch) André Aziz ([email protected]) 71 21/11/2013 • Os alvos da instruções de jump (j e jal) podem ser qualquer lugar no segmento de texto: • O endereço alvo vem codificado na instrução: op address 6 bits 26 bits • (Pseudo) endereçamento direto: • Endereço Alvo = PC31...28 : (address x 4) Concatenação Endereçamento de desvios incodicionais (jump) André Aziz ([email protected]) 72 21/11/2013 • Código de um loop de um exemplo anterior: • Assuma que o loop está localizado a partir do endereço 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 19 19 1 addi $s3, $s3, 1 80016 8 j 80020 2 Loop Exit: … 80024 Exemplo: Endereçamento alvo André Aziz ([email protected]) 20000 73 21/11/2013 • Se o alvo de um branch é um rótulo muito distante para ser codificado em 16 bits, então o Assembler reescreve o código da seguinte forma: • Exemplo: L2: beq $s0,$s1, L1 ↓ bne $s0,$s1, L2 j L1 … Desvios condicionais para áreas distantes André Aziz ([email protected]) 74 21/11/2013 Resumo dos modos de endereçamento André Aziz ([email protected]) 75 21/11/2013 SINCRONIZAÇÃO 76 André Aziz ([email protected]) 21/11/2013 • Dois processadores compartilhando ao mesma região de memória: • P1 escreve, então P2 lê; • Condição de corrida de P1 e P2 não sincronizarem: • Resultado vai depender da ordem dos acessos; • Necessário suporte de hardware: • Operação atômica de leitura/escrita na memória; • Ninguém acessa o dado entre a leitura e a escrita; • Pode ser uma instrução única: • Ex. swap atômico entre registrador e memória; • Ou um par de instruções atômicas. Sincronização André Aziz ([email protected]) 77 21/11/2013 • Load Linked: ll rt, offset(rs) • Store Conditional: sc rt, offset(rs) • Sucesso se o endereço não mudou desde o ll: • Retorna 1 em rt; • Falha se o endereço mudou: • Retorna 0 em rt; Sincronização no MIPS André Aziz ([email protected]) 78 21/11/2013 • Swap atômico (test/set lock) try: add ll sc beq add $t0,$zero,$s4 $t1,0($s1) $t0,0($s1) $t0,$zero,try $s4,$zero,$t1 ;copy exchange value ;load linked ;store conditional ;branch store fails ;put load value in $s4 Exemplo: Swap atômico André Aziz ([email protected]) 79 21/11/2013 TRADUÇÃO E INICIALIZAÇÃO 80 André Aziz ([email protected]) 21/11/2013 Many compilers produce object modules directly Static linking Tradução e Inicialização André Aziz ([email protected]) 81 21/11/2013 • Maioria das instruções do Assembler representam instruções de máquina de uma-para-um; • Pseudoinstruções: fruto da imaginação do Assembler: move $t0, $t1 blt $t0, $t1, L → add $t0, $zero, $t1 → slt $at, $t0, $t1 bne $at, $zero, L • $at (register 1): assembler temporary Pseudoinstruções André Aziz ([email protected]) 82 21/11/2013 • Provê informações para a construção de um programa completo a partir dos pedaços: • Header: descreve o conteúdo do código objeto; • Text Segment: instruções traduzidas; • Static Data Segment: dados alocados durante a vida do programa (variáveis globais); • Relocation Info: para conteúdos que dependem da localização absoluta do programa carregado; • Symbol Table: definições globais e referências externas; • Debug Info: para associação com o código fonte. Produzindo um Código Objeto (Partes dos Programas) André Aziz ([email protected]) 83 21/11/2013 • Produz uma imagem executável: 1. Unifica os segmentos; 2. Resolve os rótulos (determina o seus endereços); 3. Corrige as referências externas e as dependente de localização; • Pode deixar as dependências de localização para serem corrigidas durante o processo de Loader: • Com memória virtual, isso não é necessário; • Programa pode ser carregado em uma localização absoluta no espaço da memória virtual. “Linkando” Código Objeto André Aziz ([email protected]) 84 21/11/2013 • Carrega o arquivo de imagem do disco para a memória: 1. Lê o Header para determinar o tamanho dos segmentos; 2. Cria um espaço de endereçamento virtual; 3. Copia instruções e os dados inicializados para a memória: • Ou configura as entradas da tabela de páginas para que ocorram faltas; 4. Carrega os argumentos na pilha; 5. Inicializa os registradores (incluindo $sp, $fp, $gp); 6. Desvia para a rotina de inicialização: • • Copia os argumentos para $a0, ... e chama a “main”; Quando a “main” retorna, executa a Syscall Exit. Carregando um programa André Aziz ([email protected]) 85 21/11/2013 • Só carrega/linka a biblioteca de procedimentos quando é chamada: • Necessita que o código do procedimento seja realocável; • Evita o “inchaço” do executável causado pela linkagem estática de todas as bibliotecas referenciadas; • Automaticamente pega novas versões das bibliotecas. “Linkagem” Dinâmica André Aziz ([email protected]) 86 21/11/2013 Indirection table Stub: Loads routine ID, Jump to linker/loader Linker/loader code Dynamically mapped code Lazy Linkage André Aziz ([email protected]) 87 21/11/2013 Simple portable instruction set for the JVM Compiles bytecodes of “hot” methods into native code for host machine Iniciando aplicações Java André Aziz ([email protected]) Interprets bytecodes 88 21/11/2013 COLOCANDO TUDO JUNTO 89 André Aziz ([email protected]) 21/11/2013 • Ilustra o uso de instruções em Assembly para uma função de Bubble Sort em C; • Procedimento de SWAP (folha): void swap(int v[], int k) { int temp; temp = v[k]; v[k] = v[k+1]; v[k+1] = temp; } • v em $a0, k em $a1, temp em $t0 Exemplo: Ordenação em C André Aziz ([email protected]) 90 21/11/2013 swap: sll $t1, $a1, 2 # $t1 = k * 4 add $t1, $a0, $t1 # $t1 = v+(k*4) # (address of 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 # return to calling routine Procedimento de SWAP André Aziz ([email protected]) 91 21/11/2013 • Não-folha (chama 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 em $a0, k em $a1, i em $s0, j em $s1 Procedimento de ordenação em C André Aziz ([email protected]) 92 21/11/2013 move $s2, $a0 # save $a0 into $s2 move $s3, $a1 # save $a1 into $s3 move $s0, $zero # i = 0 for1tst: slt $t0, $s0, $s3 # $t0 = 0 if $s0 ≥ $s3 (i ≥ n) beq $t0, $zero, exit1 # go to exit1 if $s0 ≥ $s3 (i ≥ n) addi $s1, $s0, –1 # j = i – 1 for2tst: slti $t0, $s1, 0 # $t0 = 1 if $s1 < 0 (j < 0) bne $t0, $zero, exit2 # go to exit2 if $s1 < 0 (j < 0) sll $t1, $s1, 2 # $t1 = j * 4 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 if $t4 ≥ $t3 beq $t0, $zero, exit2 # go to exit2 if $t4 ≥ $t3 move $a0, $s2 # 1st param of swap is v (old $a0) move $a1, $s1 # 2nd param of swap is j jal swap # call swap procedure addi $s1, $s1, –1 # j –= 1 j for2tst # jump to test of inner loop exit2: addi $s0, $s0, 1 # i += 1 j for1tst # jump to test of outer loop Corpo do procedimento André Aziz ([email protected]) Move params Outer loop Inner loop Pass params & call Inner loop Outer loop 93 21/11/2013 sort: addi $sp,$sp, –20 sw $ra, 16($sp) sw $s3,12($sp) sw $s2, 8($sp) sw $s1, 4($sp) sw $s0, 0($sp) … … exit1: lw $s0, 0($sp) lw $s1, 4($sp) lw $s2, 8($sp) lw $s3,12($sp) lw $ra,16($sp) addi $sp,$sp, 20 jr $ra # # # # # # # make room on stack for 5 registers save $ra on stack save $s3 on stack save $s2 on stack save $s1 on stack save $s0 on stack procedure body # # # # # # # restore $s0 from stack restore $s1 from stack restore $s2 from stack restore $s3 from stack restore $ra from stack restore stack pointer return to calling routine Procedimento completo André Aziz ([email protected]) 94 21/11/2013 Compiled with gcc for Pentium 4 under Linux Relative Performance 3 140000 Instruction count 120000 2.5 100000 2 80000 1.5 60000 1 40000 0.5 20000 0 0 none O1 O2 Clock Cycles 180000 160000 140000 120000 100000 80000 60000 40000 20000 0 none O3 O1 O2 O3 O2 O3 CPI 2 1.5 1 0.5 0 none O1 O2 O3 none Efeitos da otimização do compilador André Aziz ([email protected]) O1 95 21/11/2013 Bubblesort Relative Performance 3 2.5 2 1.5 1 0.5 0 C/none C/O1 C/O2 C/O3 Java/int Java/JIT Java/int Java/JIT Quicksort Relative Performance 2.5 2 1.5 1 0.5 0 C/none C/O1 C/O2 C/O3 Quicksort vs. Bubblesort Speedup 3000 2500 2000 1500 Efeitos da linguagem e algoritmo 1000 500 0 C/none André Aziz ([email protected]) C/O1 C/O2 C/O3 Java/int Java/JIT 96 21/11/2013 • Número de instruções e CPI não são bons avaliadores de de desempenho isolados; • Otimizações do compilador são sensíveis ao algoritmo; • Código compilado para Java/JIT é significantemente mais rápido que o interpretado pela JVM: • Comparável com o código C otimizado; • Nada pode corrigir um algoritmo ruim! Lições aprendidas André Aziz ([email protected]) 97 21/11/2013 • Indexar array envolve: • Multiplicação do índice pelo tamanho do elemento; • Adicionar ao endereço base do array; • Ponteiros corresponde diretamente ao endereço da memória: • Evita a complexidade de indexação. Arrays vs. Ponteiros André Aziz ([email protected]) 98 21/11/2013 clear1(int array[], int size) { int i; for (i = 0; i < size; i += 1) array[i] = 0; } clear2(int *array, int size) { int *p; for (p = &array[0]; p < &array[size]; p = p + 1) *p = 0; } move $t0,$zero loop1: sll $t1,$t0,2 add $t2,$a0,$t1 move $t0,$a0 # p = & array[0] sll $t1,$a1,2 # $t1 = size * 4 add $t2,$a0,$t1 # $t2 = # &array[size] loop2: sw $zero,0($t0) # Memory[p] = 0 addi $t0,$t0,4 # p = p + 4 slt $t3,$t0,$t2 # $t3 = #(p<&array[size]) bne $t3,$zero,loop2 # if (…) # goto loop2 # i = 0 # $t1 = i * 4 # $t2 = # &array[i] sw $zero, 0($t2) # array[i] = 0 addi $t0,$t0,1 # i = i + 1 slt $t3,$t0,$a1 # $t3 = # (i < size) bne $t3,$zero,loop1 # if (…) # goto loop1 Exemplo: Limpando um array André Aziz ([email protected]) 99 21/11/2013 • Multiplicar a “força reduzida” do uso do shift; • Versão com array necessita que os shifts estejam dentro do loop; • Parte do cálculo do índice para o i incrementado; • Compilador por alcançar o mesmo efeito com o uso manual de ponteiros: • Eliminação da variável de indução; • Melhor para fazer o programa mais claro e seguro; Comparação entre Array e Ponteiro André Aziz ([email protected]) 100 21/11/2013 • ARM: processador embarcado mais popular; • Conjunto de instruções similar ao do MIPS; ARM MIPS 1985 1985 Instruction size 32 bits 32 bits Address space 32-bit flat 32-bit flat Data alignment Aligned Aligned 9 3 15 × 32-bit 31 × 32-bit Memory mapped Memory mapped Date announced Data addressing modes Registers Input/output Similaridades ARM & MIPS André Aziz ([email protected]) 101 21/11/2013 • Usa códigos condicionais para resultado de uma operação lógica/aritmética; • Negativo, zero, carry, overflow; • Compara instruções para mudar os código de condição sem manter o resultado; • Cada instrução pode ser condicional: • 4 bits mais significativos da instrução: valor da condição; • Evita branchs sobre instruções simples. Comparação e Desvio no ARM André Aziz ([email protected]) 102 21/11/2013 Codificação das Instruções André Aziz ([email protected]) 103 21/11/2013 • Evolução com compatibilidade: • 8080 (1974): 8-bit microprocessor • Accumulator, plus 3 index-register pairs • 8086 (1978): 16-bit extension to 8080 • Complex instruction set (CISC) • 8087 (1980): floating-point coprocessor • Adds FP instructions and register stack • 80286 (1982): 24-bit addresses, MMU • Segmented memory mapping and protection • 80386 (1985): 32-bit extension (now IA-32) • Additional addressing modes and operations • Paged memory mapping as well as segments Intel x86 ISA André Aziz ([email protected]) 104 21/11/2013 • ... • i486 (1989): pipelined, on-chip caches and FPU • Compatible competitors: AMD, Cyrix, … • Pentium (1993): superscalar, 64-bit datapath • Later versions added MMX (Multi-Media eXtension) instructions • The infamous FDIV bug • Pentium Pro (1995), Pentium II (1997) • New microarchitecture (see Colwell, The Pentium Chronicles) • Pentium III (1999) • Added SSE (Streaming SIMD Extensions) and associated registers • Pentium 4 (2001) • New microarchitecture • Added SSE2 instructions Intel x86 ISA André Aziz ([email protected]) 105 21/11/2013 • ... • AMD64 (2003): extended architecture to 64 bits • EM64T – Extended Memory 64 Technology (2004) • AMD64 adopted by Intel (with refinements) • Added SSE3 instructions • Intel Core (2006) • Added SSE4 instructions, virtual machine support • AMD64 (announced 2007): SSE5 instructions • Intel declined to follow, instead… • Advanced Vector Extension (announced 2008) • Longer SSE registers, more instructions • Se a Intel não estender a compatibilidade, seus concorrentes irão! • Technical elegance ≠ market success Intel x86 ISA André Aziz ([email protected]) 106 21/11/2013 Registradores do x86 André Aziz ([email protected]) 107 21/11/2013 • Dois operandos por instrução: Source/dest operand Second source operand Register Register Register Immediate Register Memory Memory Register Memory Immediate • Modos de endereçamento da memória: • Address in register • Address = Rbase + displacement • Address = Rbase + 2scale × Rindex (scale = 0, 1, 2, or 3) • Address = Rbase + 2scale × Rindex + displacement Modos de endereçamento x86 André Aziz ([email protected]) 108 21/11/2013 • Tamanho da codificação variável: • Sufixo especifica o modo de endereçamento; • Prefixo modifica a operação: • Tamanho do operado, repetição, travamento, ... Codificação das instruções do x86 André Aziz ([email protected]) 109 21/11/2013 • Instruções complexas fazem a implementação difícil: • Hardware traduz instruções para microoperações mais simples: • Instruções simples: 1 – 1; • Instruções complexas: 1 – muitos; • Microengine similar a um RISC; • Marke share tornou isto economicamente viável; • Desempenho comparável ao RISC: • Compiladores evitam instruções complexas. Implementando IA-32 André Aziz ([email protected]) 110 21/11/2013 • Instruções poderosas alto desempenho: • Poucas instruções necessárias; • Instruções complexas são difíceis de implementar: • Podem deixar lenta todas as instruções, incluindo as simples; • Compiladores são bons em fazer código rápido com instruções simples; • Uso de código Assembly para alto desempenho: • Compiladores modernos conseguem lidar melhor com processadores modernos; • Mais linhas de código mais erros e menos produtividade Falácias André Aziz ([email protected]) 111 21/11/2013 • Compatibilidade conjunto de instruções não muda: • Eles acrescentam mais instruções. x86 instruction set Falácias André Aziz ([email protected]) 112 21/11/2013 • Palavras sequenciais não são endereços sequenciais: • Endereços são incrementados por 4 e não por 1! • Mantendo um ponteiro para um variável local depois que o processo retorna: • Ex. passando o ponteiro de volta via um argumento; • Ponteiros ficam inválidos após serem removidos da pilha. Armadilhas André Aziz ([email protected]) 113 21/11/2013 • Princípios de projeto: 1. 2. 3. 4. Simplicidade favorece regularidade; Menor é mais rápido; Faça o caso comum mais rápido; Bons projetos demandam bons compromissos; • Camadas de software/hardware: • Compilador, Assembler, hardware; • MIPS: típico ISA dos RISCs: • Diferente do x86 – CISC. Relembrando André Aziz ([email protected]) 114 21/11/2013 • Meça a execução das instruções do MIPS em programas de benchmarks: • Considere fazendo o caso comum mais rápido; • Considere bons compromissos. Instruction class MIPS examples SPEC2006 Int SPEC2006 FP Arithmetic add, sub, addi 16% 48% Data transfer lw, sw, lb, lbu, lh, lhu, sb, lui 35% 36% Logical and, or, nor, andi, ori, sll, srl 12% 4% Cond. Branch beq, bne, slt, slti, sltiu 34% 8% Jump j, jr, jal 2% 0% Relembrando André Aziz ([email protected]) 115 21/11/2013 Arquitetura e Organização de Computadores Capítulo 2 – Conjunto de Instruções