Conjunto de Instruções - cic.unb.brrjacobi/ensino/OAC/Instrucoes1x1.pdf · Estruturas de dados...

125
Conjunto de Instruções Para comandar o hardware do computador, é necessário que falemos sua língua: As palavras da linguagem de máquina são chamadas de instruções; O vocabulário forma o conjunto de instruções, que determina a interface hardware/software. Computadores com arquiteturas diferentes implementam conjuntos de instruções distintos

Transcript of Conjunto de Instruções - cic.unb.brrjacobi/ensino/OAC/Instrucoes1x1.pdf · Estruturas de dados...

Conjunto de Instruções

Para comandar o hardware docomputador, é necessário que falemossua língua:

♦ As palavras da linguagem de máquina sãochamadas de instruções;

♦ O vocabulário forma o conjunto de instruções, quedetermina a interface hardware/software.

♦ Computadores com arquiteturas diferentesimplementam conjuntos de instruções distintos

Conjunto de Instruções

It is easy to see by formal-logical methods that there

exist certain [instruction sets] that are in abstract

adequate to control and cause the execution of any

sequence of operations ... The really decisive

considerations from the present point of view, in

selection an [instruction set], are more of a practical

nature: simplicity of the equipment demanded by the

[instruction set], and the clarity of its application to the

actually important problems together with the speed

of its handling of those problems.

Burks, Goldstine and von Neumann, 1947

Conjunto de Instruções

As linguagens de máquina são bastante parecidas

entre si. Aprendendo bem uma é fácil aprender outra.

Isto ocorre porque:♦ Todas são baseadas nos mesmos princípios (arquitetura de von

Neumann);

♦ Existe um conjunto de operações básicas que todas as máquinas

devem fornecer;

♦ Projetistas têm um mesmo objetivo: encontrar uma linguagem que

torne fácil a construção do hardware e de compiladores,maximizando a performance e minimizando os custos →SIMPLICIDADE

Implementação de Programas

♦ Um Programa de Computador é, basicamente, umaseqüência de comandos ou instruções representando umalgoritmo a ser executado pela máquina.

♦ Normalmente os programadores usam Linguagens deProgramação de Alto Nível (LAN), como Pascal e C

♦ Entretanto, estas linguagens correspondem a um nível deabstração elevado.

♦ As linguagens dos processadores como o x86 ou o MIPScorrespondem a um nível de abstração baixo, e sãodenominadas de Linguagens de Baixo Nível (LBN)

♦ Desta maneira é necessário um processo de Tradução

Tradução

♦ As linguagens LBNs são definidas por uma série deMnemônicos, que são, basicamente, símbolos querepresentam código binários

♦ Por exemplo, no caso do MIPS a instrução de adiçãoé representada por add a, b, c• esta instrução determina que o processador some o

conteúdo de dois registradores (b, c) e coloque o resultadoem outro registrador (a)

♦ A instrução ADD segue um formato bem definido:• código correspondente ao mnemônico da instrução add• identificação do registrador destino• identificação do primeiro operando• identificação do segundo operando

Assembler x Linguagem de Máquina

♦ Entretanto, para que um programa seja entendidopela máquina, é necessário que suas instruçõesestejam codificadas na forma binária, isto é, na formade 0s e 1s.

♦ No MIPS, a instrução add corresponde ao códigobinário 000000100000

♦ O conjunto de instruções de uma arquitetura (naforma de Mnemônicos) corresponde à Linguagem deMontagem da arquitetura (Linguagem ASSEMBLY)

♦ O conjunto de instruções de uma arquitetura (naforma binária) corresponde à Linguagem de Máquina

Níveis de Abstração

♦ Diferentes Níveis de Abstração

Tradutores

♦ Tanto os programas implementados em LANs comoem LBN precisam ser traduzidos para a linguagemde máquina do processador

♦ O processo de tradução de uma linguagem de altonível (LAN) para linguagem de máquina é feitocompiladores ou interpretadores

♦ O processo de tradução de uma linguagem deMontagem para linguagem de máquina é feito portradutores denominados de Montadores (ouAssemblers).

Compiladores e Interpretadores

♦ Compiladores são tradutores que após várias fases(análise léxica, análise sintática, análise semântica,geração de código intermediário, otimização decódigo e geração de código de montagem) geramum programa executável.

♦ Na verdade, este programa executável deverá sercarregado em memória para ser executado. Quemfaz esta tarefa é um programa do sistemaoperacional (programa carregador ou loader)

♦ Interpretadores não geram código executável

♦ Os interpretadores traduzem cada instrução doprograma (em LAN ou Assembly) e a executam

Tradutores

♦ Montadores, Compiladores e Interpretadores:

montador

execução

Código fonte

(ling.Montagem)

CódigoObjeto

compilador

Códigofonte(LAN)

CódigoObjeto

execução

Interpretador

Códigofonte

(LAN ouAssembl

y)

execução

Conjunto de Instruções

O conjunto de instruções que veremos vemdo MIPS, utilizado por diversas empresas(NEC, Nintendo, Silicon Graphics, Sony, …)

Utilizaremos um simulador de MIPS chamadoSPIM, que tem versões para Unix, Windowse DOS. O SPIM pode ser baixado a partir daURL:

http://www.mkp.com/cod2e.htm

ISA do MIPS (simplificada)

♦ Categorias de Instruções:• Load/Store• Computação• Jump e Desvio• Ponto Flutuante• Gerenciamento de Memória• Especial

♦ 3 Formatos de Instrução: 32 bits

R0 - R31

PC

HI

LO

OP

OP

OP

rs rt rd sa funct

rs rt imediato

Destino do jump

Registradores

add a, b, c # a = b + cadd a, a, d # a = b + c + dadd a, a, e # a = b + c + d +e

Operações do Hardware

Todo computador deve ser capaz de realizaroperações aritméticas.

Instruções aritméticas no MIPS têm formato fixo,realizando somente uma operação e tendo três“variáveis”

Somente umainstrução porlinha

Comentários

ex: a = b + c + d + e

ex..: add a,b,c a = b+ c

Operações do Hardware

♦ Exigir que toda instrução tenha exatamentetrês operandos condiz com a filosofia demanter o hardware simples: hardware paranúmero variável de parâmetros é maiscomplexo que para número fixo.

Princípio #1 para projetos: Simplicidadefavorece a regularidade

Exemplo

♦ Qual o código gerado por um compilador Cpara o seguinte trecho?

add a, b, c #a = b + csub d, a, e #d = a - e

a = b + c;d = a – e;

Exemplo 2

♦ Qual o código gerado por um compilador Cpara o seguinte trecho?

add t0, g, h # temporário t0 = g+ hadd t1, i, j # temporário t1 = i +jsub f, t0, t1 #f = (g + h) – (I + j)

Somente uma operação é feita por instrução: necessidade de variáveis temporárias.

f = (g + h) – (i + j);

Operandos e Registradores

♦ Ao contrário das linguagens de alto nível,operandos de instruções aritméticas não podemser quaisquer variáveis

→ são escolhidos dentre um conjunto deregistradores:

→ Número limitado de endereços especiais construídosdiretamente no hardware;

→ Blocos básicos para construção de computadores, poissão primitivas usadas em projeto de hardware quetambém são vistas pelo programador;

Registradores : benefícios

♦ Registradores no hardware, dentro doprocessador → mais rápidos que memória

♦ Registradores são de mais fácil utilização porcompiladores:

♦ como um local para armazenamento temporário

♦ podem armazenar variáveis para reduzir o tráfegode memória e melhorar a densidade de código (umavez que os registradores podem ser especificadoscom menos bits que um endereço de memória)

Operandos e Registradores

♦ Registradores do MIPS são de 32 bits;♦ no MIPS, blocos de 32 bits são chamados de

palavra;♦ Número de registradores é limitado: MIPS → 32

registradores, numerados de 0 a 31

♦ Princípio #2 para projetos: menor é mais rápido

♦ Um número muito grande de registradoresaumentaria o período de clock.

Operandos e Registradores

♦ Apesar de podermos nos referir aosregistradores através de números, em MIPSexiste uma convenção de se utilizar nomes naforma $xy

♦ Usaremos:

♦ $s0, $s1, $s2, … para registradores quecorrespondam a variáveis em C

♦ $t0, $t1, $t2, … para registradores temporáriosnecessários para compilar o programa eminstruções MIPS

Exemplo

Qual o código gerado por um compilador Cpara o seguinte trecho?

add $t0, $s1, $s2 # temporário t0 = g+ hadd $t1, $s3, $s4 # temporário t1 = i +jsub $s0, $t0, $t1 # f = (g + h) – (I + j)

As variáveis f, g, h, i, j podem ser mapeadas nosregistradores $s0, $s1, $s2, $s3 e $s4, respectivamente.

f = (g + h) – (i + j)

Operandos e Registradores

♦ Estruturas de dados podem ser bastante complexas,com um número de elementos grande demais paraserem armazenados nos registradores♦ Estruturas de dados, como vetores, são armazenadas na

memória

♦ Operações aritméticas em MIPS só podem ser feitasquando os operandos estão em registradores

♦ MIPS deve fornecer instruções para transferir dados entrea memória e os registradores

♦ Para acessar uma palavra na memória, a instrução devefornecer um endereço de memória

Memória

♦ Memória é somente um grande vetorunidimensional, com o endereço atuando comoíndice no vetor, começando em 0.

3210

100101011

Processador

DadosEndereços

Memória

Transferindo dados damemória

♦ A instrução de transferência de dados da memóriapara o registrador é chamada de load.

♦ Formato:

♦ Endereço de memória acessado é dado pela somada constante (chamada de offset) com o conteúdodo registrador base

Em MIPS, o nome da instrução é:lw (load word)

lw registrador destino, constante (registradorbase)

Exemplo♦ Suponha que temos um apontador a para um inteiro que está na

memória, com o endereço de memória dado no registrador $s3(ou seja, o apontador a está em $s3). Suponha ainda que ocompilador associou as variáveis g e h aos registradores $s1 e$s2. Qual o código para o seguinte trecho em C?

♦ Primeiro temos que pegar o operando que está na memória etransferi-lo para um registrador:

g = h + *a;

lw $t0, 0($s3) # temporário t0 =*aadd $s1, $s2, $t0 # g = h + *a

Vetor A = [0,0,0,0,15], com 5 posições, começando noendereço de memória 102. Este endereço é chamado deendereço base do vetor. Assim, 102 é o endereço de A[0],103o de A[1], ...,106 o de A[4].

Vetor na memória

Dados

Endereços

Endereço basede A

... 5 10 0 0 0 0 15 42 ...

... 100 101 102 103 104 105 106 107 ...

Exemplo

♦ Suponha que o vetor A tenha 100 posições, e que ocompilador associou as variáveis g e h aos registradores$s1 e $s2. Temos ainda que o endereço base do vetor A édado em $s3. Qual o código para

♦ Primeiro temos que pegar o operando que está namemória e transferi-lo para um registrador:

g = h + A[8]?

lw $t0, 8($s3) # temporário t0 =A[8]add $s1, $s2, $t0 # g = h + A[8]

10010

1011

Acesso à memória♦ Uma vez que bytes (8 bits) são úteis em muitos

programas, a maior parte das arquiteturas permite acessarbytes;

♦ Portanto, o endereço de uma palavra é o endereço de umdos 4 bytes dentro da palavra

♦ Assim, endereços de palavras consecutivas diferem em 4

12840

ProcessadorDadosEndereços

Memória

Cada posição do vetor (de inteiros) é uma palavra, e portantoocupa 4 bytes

Vetor A = [0,0,0,0,15], com 5 posições, começando noendereço de memória 408. Assim, 408 é o endereço deA[0],412 o de A[1], 416 o de A[2], 420 o de A[3] e 424 o deA[4].

Vetor na memória (2)

Dados

Endereços

Endereço basede A

... 5 10 0 0 0 0 15 4 2 ... ... 400 404 408 412 416 420 424 428 ...

Exemplo♦ Suponha que o vetor A tenha 100 posições, e que o

compilador associou a variável h ao registrador $s2.Temos ainda que o endereço base do vetor A é dado em$s3. Qual o código para:

♦ A nona posição do vetor A, A[8], está no offset 8 x 4 = 32

♦ A décima-terceira posição do vetor A, A[12], está no offset12 x 4 = 48

A[12] = h + A[8] ?

lw $t0, 32($s3) # temporário t0 = A[8]add $t0, $s2, $t0 # temporário t0 = h + A[8]

lw $t0, 48($s3) # carrega A[12] em $t0!!!!

Transferindo dados para amemória

♦ A instrução de transferência de dados de um registradorpara a memória é chamada de store.

♦ Formato:

♦ Endereço de memória acessado é dado pela soma daconstante (chamada de offset) com o conteúdo doregistrador base

No MIPS, o nome da instrução é: sw (store word)

sw registrador fonte, constante (registradorbase)

Endereço absoluto de A[3]

♦ Para obter o endereço absoluto precisamos:

0 1 2 3 4 5 6 7 8 9...

Registrador baseexe. $s2

Variável i ( i = 3) ($s4)

deslocamento(offset)offset = 4*i

endereço = $s2 + 4*3

Exemplo: variável de índice

♦ Suponha que o vetor A tenha 100 posições, e que ocompilador associou as variáveis g, h e i aos registradores$s1, $s2 e $s4. Temos ainda que o endereço base dovetor A é dado em $s3. Qual o código para:

♦ Precisamos primeiro calcular o endereço de A[i]. Antes desomar i ao endereço base de A, devemos multiplicar i por4. Vamos fazer isto por enquanto da seguinte forma:

g = h + A[i] ?

add $t1, $s4, $s4 # $t1 = 2 * iadd $t1, $t1, $t1 # $t1 = 4 * i

Variável de índice

♦ Para pegarmos A[i], somamos $t1 com o endereço basede A, dado em $s3:

♦ Agora podemos carregar A[i] para um registradortemporário, e realizar a soma, que será armazenada em g:

add $t1, $t1, $s3 # $t1 = endereço deA[i]

lw $t0, 0($t1) # temporário $t0 = A[i]add $s1, $s2, $t0 # g = h + A[i]

Resumo da Tradução

g = h + A[i]

add $t1, $s4, $s4 # $t1 = 2 * iadd $t1, $t1, $t1 # $t1 = 4 * iadd $t1, $t1, $s3 # $t1 = endereço de A[i]lw $t0, 0($t1) # temporário $t0 = A[i]add $s1, $s2, $t0 # g = h + A[i]

Exercício

Temos ainda que o endereço base do vetor A édado em $s2, e que as variáveis i e g são dadasem $s0 e $s1, respectivamente. Qual o códigopara

A[i+g] = g + A[i] – A[0]?

Solução

add $t0, $s0, $s0 # $t0 = 2*iadd $t0, $t0, $t0 # $t0 = 4*iadd $t0, $t0, $s2 # $t0 = endereço 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 + gadd $t0, $t0, $t0 # $t0 = 2 * (i + g)add $t0, $t0, $t0 # $t0 = 4 * (i + g)add $t0, $t0, $s2 # $t0 = endereço de A[i + g]sw $t1, 0($t0) # A[i + g] = g + A[i] – A[0]

A[i+g] = g + A[i] – A[0]?i,g,A = $s0, $s1,$s2

Utilizando os registradores

♦ Muitos programas têm mais variáveis do que onúmero de registradores presente na máquina.

♦ Compilador tenta manter as variáveis mais usadasnos registradores e coloca o resto na memória,utilizando loads e stores para mover os dadosentre a memória e os registradores:

♦ Compiladores têm que utilizar os registradores deforma eficiente.

♦ MIPS requer que todas as palavras comecem emendereços que são múltiplos de 4 bytes

♦ Chamamos isto de alinhamento: objetos têm que terendereços que sejam múltiplos de seus tamanhos.

0 1 2 3

Alinhado

Não alinhado

Alinhamento de Dados naMemória

♦ Processadores podem numerar bytes dentro de umapalavra, de tal forma que o byte com o menornúmero é o mais a esquerda ou o mais a direita. Istoé chamado de byte order.

♦ Ex: .byte 0, 1, 2, 3

♦ Big endian: IBM 360/370, Motorola 68k, MIPS, Sparc, HPPA

♦ Little Endian: Intel 80x86, MIPS, DEC Vax, DEC Alpha

3 2 1 0little endian

0 1 2 3bigendian

Ordenamento dos Bytes

Representando Instruções noComputador

♦ Números são armazenados no hardware na base2, ou binária.

♦ Instruções podem ser representadas comonúmeros; na verdade, cada pedaço da instrução éum número, e o posicionamento lado a ladodestes números é que formam a instrução.

♦ Existe uma convenção em MIPS para associarnomes de registradores a seus números:

$s0, $s1, …, $s7 → 16, 17, …,23$t0, $t1, …, $t7 → 8, 9, …, 15

Representando Instruções noComputador ...

♦ Linguagem de máquina para a instrução

♦ Cada um destes segmentos é chamado de campo. Oprimeiro e o último campos, juntos, dizem que a instruçãoé uma adição. O segundo diz qual é o primeiro registradorfonte (17 = $s1) e o terceiro o segundo registrador fonte(18 = $s2). O quarto campo é o registrador destino (8 =$t0). O quinto campo não é usado nesta instrução, e poristo tem valor zero.

0 17 18 8 0 32

add $t0, $s1, $s2

♦ Também podemos representar tais números em binário:

♦ Para distinguir da linguagem Assembly, chamamos estarepresentação numérica de linguagem de máquina, e aseqüência de tais instruções de código de máquina

♦ Chamamos esta estrutura de campos de formato dainstrução. Todas as instruções em MIPS possuem 32 bits(“simplicidade favorece regularidade”).

000000 10001 10010 01000 00000100000

Representando Instruções noComputador ...

6 bits 5 bits 5 bits 5 bits 5 bits 6bits

Formato Instrução MIPS

♦ Daremos nomes aos campos para simplificar a discussão:

♦ op: operação básica da instrução (opcode);♦ rs: primeiro registrador fonte;♦ rt: segundo registrador fonte;♦ rd: registrador destino, recebe o resultado da operação♦ shamt: quantidade de shift (veremos no capítulo 4)♦ funct: função; seleciona a variante específica da operação

dada no campo op, também chamada de código de função

op rs rt rd shamtfunct 6 bits 5 bits 5 bits 5 bits 5 bits 6

bits

Formato Instrução MIPS...

♦ Um problema acontece quando uma instrução necessitade campos mais longos que os mostrados neste exemplo.

♦ Ex.: a instrução lw precisa especificar dois registradores euma constante. Se a constante for ser representada nocampo de um dos registradores, o valor dela ficará limitadoa 32 (2^5). Obviamente, este valor é pequeno demaispara ser útil.

♦ Assim, temos um conflito entre o desejo de que todas asinstruções tenham o mesmo tamanho e o desejo de quetenhamos um único formato de instruções.

Formato Instrução MIPS...

♦ Princípio #3 para projetos: bons projetosdemandam bons compromissos.

♦ Compromisso escolhido pelos projetistas do MIPS: mantertodas as instruções com o mesmo tamanho → diferentestipos de instrução podem ter diferentes formatos deinstrução.

♦ O formato mostrado anteriormente é chamado de tipo-R

(de registrador) ou formato-R

♦ Um segundo formato é usado pelas instruções de

transferência de dados: tipo-I ou formato-I

Formato Instrução MIPS...

♦ Formato tipo-I:

♦ O endereço de 16 bits significa que uma instrução lw podecarregar qualquer palavra dentro de uma região de ±2^15ou 32768 bytes (2^13 ou 8192 palavras) em relação aoendereço no registrador base rs.

op rs rt endereço

6 bits 5 bits 5 bits 16 bits

Formato Instrução MIPS...

♦ Ex: lw $t0, 32($s3) #temporário $t0 = A[8]

♦ Neste exemplo, rs recebe 19 ($s3), rt recebe 8 ($t0) e ocampo endereço recebe o valor 32. Op neste caso é 35(lw). Em uma instrução de load, o campo rt determina oregistrador destino!!

♦ Apesar do hardware ficar mais complexo ao utilizarmosdiferentes formatos de instrução, podemos reduzir esteaumento de complexidade ao mantermos certasimilaridade entre os formatos (ex.: 3 primeiros camposnos formatos tipo-R e tipo-I são os mesmos; comprimentodo último campo tipo-I é igual à soma dos 3 últimos tipo-R).

op rs rt endereço

Formato Instrução MIPS...

♦ Primeiro campo determina tipo do formato.

♦ Pergunta: por que não utilizar somente um campode 12 bits para os campos op e funct nasinstruções de tipo-R??

Codificação das InstruçõesVistas

Instrução

Formato op rs rt rd shamt funct

endereço

add R 0 reg reg reg 0 32 não

sub R 0 reg reg reg 0 34 não

lw I 35 reg reg não

não não ender.

sw I 43 reg reg não

não não ender.

$s0, $s1, …, $s7 → 16, 17, …, 23$t0, $t1, …, $t7 → 8, 9, …, 15

Exemplo de compilaçãomanual

♦ Suponha que $t1 tenha o endereço base de A e que $s2corresponda a h, traduza a seguinte linha em C paracódigo de máquina MIPS: A[300] = h + A[300];

♦ Primeiro, temos que o código em assemblycorrespondente é:

♦ Qual o código de máquina destas 3 instruções?

lw $t0,1200($t1) # $t0 = A[300]add $t0, $s2, $t0 # $t0 = h + A[300]sw $t0, 1200($t1) # A[300] = h +A[300]

Exemplo de compilação manual...

lw $t0,1200($t1)add $t0, $s2, $t0sw $t0, 1200($t1)

op rs rt

rd

Endereço /shamt

funct

35 9 8 1200

0 18

8 8 0 32

43 9 8 1200

op rs rt rd Endereço /shamt

funct

100011 01001 01000 0000 0100 1011 0000

000000 10010 01000 01000 00000 100000

101011 01001 01000 0000 0100 1011 0000

Idéia geral: conceito de programaarmazenado

♦ Computadores de hoje são construídos baseados em doisprincípios fundamentais:

• Instruções podem ser representadas como números

• Programas podem ser armazenados na memória paraserem lidos ou escritos da mesma forma que números

♦ Conceito de programa armazenado, fundamental para aComputação!!!

Instruções para tomada dedecisões

♦ O que distingue um computador de uma calculadorasimples é a habilidade de tomar decisões.

♦ Com base na entrada e nos resultados computados,diferentes instruções são executadas.

♦ Em linguagens de alto nível, uma das formas de se tomardecisões é através das instruções if e goto.

♦ Em MIPS, temos duas instruções que atuam de maneirasimilar a instruções que combinam if com goto:

• beq registr1, registr2, L1 # branch if equal• bne registr1, registr2, L1 # branch if not equal

rótulo (label)

Instruções de decisão no MIPS

♦ em C, isto seria equivalente a:

beq registr1, registr2,L1

Semântica: “Desvie se (valores nos registradores são) iguais”

if (registr1== registr2) gotoL1

Instruções de decisão no MIPS ...

♦ em C, isto seria equivalente a:

♦ Estas instruções são chamadas de desvios condicionais.

bne registr1, registr2, L1

Semântica: “desvie se (valores nos registradores) nãosão iguais”

if (registr1!=registr2) goto L1

Exemplo

♦ Se as variáveis f, g, h, i, j correspondem aos registradores$s0 a $s4, qual é o código compilado para o seguintetrecho em C?

Como instruções são armazenadas na memória, elas têmendereços também!!

if (i == j) goto L1; f = g + h;L1: f = f – i;

beq $s3, $s4, L1 # vá para L1 se $s3 ==$s4 add $s0, $s1, $s2 # f = g + h (se i != j)

L1: sub $s0, $s0, $s3 # f = f – i (se i == j)

Instruções para tomada dedecisões

♦ O montador (assembler) faz com que o compilador ou oprogramador em linguagem assembly não tenha que ficarcalculando endereços para os desvios (branches) aopermitir o uso de rótulos.

♦ Compiladores criam desvios e rótulos sem que oprogramador de linguagens de alto nível os tenha queespecificar. Esta é uma das razões de por que é maisrápido programar em linguagens de alto nível.

Desvio incondicional em MIPS

♦ MIPS tem um desvio incondicional:

♦ Chamada de instrução de salto (jump): salte para o rótuloespecificado, incondicionalmente

♦ Em C, isto seria equivalente a: goto label

♦ Podemos pensar que isto é equivalente a:

• Uma vez que a condição sempre é satisfeita

♦ Existe um formato de instrução para desvio (tipo-J ou formato-J), como veremos mais à frente.

j rotulo

beq $0,$0,rotulo

Exemplo: código para if

♦ Se as variáveis f, g, h, i, j correspondem aos registradores$s0 a $s4, qual é o código compilado para o seguintetrecho em C?

♦ Queremos implementar o seguinte fluxo:

Fim

i == j?

f=g+h f=g-h

(falso) i != j

(verdadeiro) i == j

if (i == j) f = g + h; else f = g – h;

Exemplo: código para if

Primeiro devemos saber se i é igual a j:

Se i == j, somamos g com h e armazenamos em f

Precisamos agora ir para o fim do if. Para istoutilizamos um desvio incondicional ( j, de jump ):

Tratamos agora o caso em que i != j

bne $s3, $s4, else # vá para else se 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)Fim:

Loops

♦ Decisões são importantes para escolher entre duasalternativas, e para iterar uma computação (loop).Usamos as mesmas instruções assembly para as duassituações.

♦ Tudo depende de onde colocamos o rótulo para o qualsaltaremos.

Exemplo de loop♦ Se as variáveis g, h, i, j correspondem aos registradores $s1 a $s4, e

o endereço base do vetor A (de 100 elementos) está em $s5, compileo seguinte trecho em C.

Loop: g = g + A[i];if ( (i = i + j) != h ) goto Loop;

Loop: add $t1, $s3, $s3 # $t1 = 2 * iadd $t1, $t1, $t1 # $t1 = 4 * iadd $t1, $t1, $s5 # $t1 = ender. de

A[i]lw $t0, 0($t1) # $t0 = A[i]add $s1, $s1, $t0 # g = g + A[i]add $s3, $s3, $s4 # i = i + jbne $s3, $s2, Loop # Loop se (i != h)

Compilando um laço do tipo while

♦ Programadores normalmente não utilizam comandos goto(o uso deles não é considerado boa prática deprogramação!!!). Assim, o compilador tem que traduzir osloops tradicionais em linguagem MIPS.

♦ Exemplo em C:

♦ Se i, j, e k correspondem aos registradores $s3, $s4 e$s5, e o endereço base do vetor save está no registrador$s6, qual o código assembly MIPS correspondente?

while (save[j] == k)i = i + j;

♦ Temos inicialmente que carregar save[i] para umregistrador temporário:

♦ Agora fazemos o teste do loop, saindo se save[i] != k

♦ Devemos agora voltar para o while no inicio do loop

Loop: add $t1, $s3, $s3 # $t1 = 2 * iadd $t1, $t1, $t1 # $t1 = 4 * iadd $t1, $t1, $s6 # $t1 = endereço de save[i]lw $t0, 0($t1) # $t0 = save[i]

bne $t0, $s5, Fim # vá para Fim se save[i] != kadd $s3, $s3, $s4 # i = i + j

j Loop # vá para LoopFim:

Compilando um laço do tipo while

Comparando doisregistradores

♦ Os testes de igualdade ou desigualdade sãoprovavelmente os mais populares, mas às vezesqueremos testar se uma variável é menor do que outra

♦ Por exemplo, um for pode querer testar se um índice émenor do que zero.

♦ Em MIPS, temos uma instrução que compara os valoresde dois registradores, e atribui 1 a um terceiro registradorse o primeiro registrador é menor que o segundo, e 0caso contrário:

♦ → Se $s3 < $s4, $t0 recebe 1, caso contrário, recebe 0

slt (set on less than) slt $t0, $s3, $s4

Compilando um laço do tipo while

♦ Compiladores MIPS utilizam as instruções slt, beq, bne, eo valor fixo zero para criar todas as relações decomparação: igual, diferente, menor que, menor ou iguala, maior que e maior ou igual a.

♦ O registrador $zero (registrador 0) tem seu valor fixadoem zero.

Exemplo: desvio se menor que

♦ Qual o código para testar se a variável a, mapeada noregistrador $s0, é menor que a variável b (registrador $s1), edesviar para o rótulo Menor se a condição for satisfeita?

♦ Primeiro usamos a instrução slt e um registrador temporário:

♦ Registrador $t0 é 1 se a < b. Portanto, testamos se $t0 não é 0:

slt $t0, $s0, $s1 # $t0 = (a <b)?

bne $t0, zero, Menor # vá para Menor se $t0!=0# ou seja, se (a < b)

Tradução de if (a < b) then... else

if (i < j) f = g + h;

else f = g – h;

slt $t0, $s0, $s1 # $t0 = (a < b)?

beq $t0, zero, Else # vá para else se a>= b

add $s0, $s1, $s2 # f = g + h (se i == j)

j Fim # vá para FimElse: sub $s0, $s1, $s2 # f = g – h (se i != j)Fim:

Por que não utilizar uma instruçãosó para “desvie se menor que”?

♦ MIPS não tem instruções como “desvie se menor que”porque elas são complicadas demais: ou elasaumentariam o período de clock ou seriam necessáriosmais ciclos de clock por instrução (além de fazer com quefosse necessário mais hardware).

♦ As duas instruções slt e bne são mais rápidas e maisúteis, pois também servem para outros propósitos.

Um outro tipo de desvioincondicional

♦ Até agora vimos uma instrução de desvio incondicional,através da instrução

♦ Nesta instrução, temos que especificar um rótulo, ou sejaum endereço fixo, para o qual o Program Counter serádesviado.

♦ Em diversas situações, pode ser interessante quedesviemos para um endereço variável, armazenado emum registrador. Para tanto, existe a instrução jr:

j Rotulo # desvio para rótulo

jr registrador #desvio para endereço #contido no

registrador

Comando switch

♦ A linguagem C define o comando switch, que permiteque o programador selecione uma alternativa dentrevárias, dependendo de um único valor.

♦ Como compilar o seguinte trecho de código?

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;

}

Comando switch

♦ Uma forma de se fazer isto é tratar o comando switchcomo sendo uma seqüência de comandos 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 f = i + j;

Comando switch

♦ Desta forma, se temos n casos possíveis, teremos, emmédia, que testar n/2 casos contra k para encontrar ocaso desejado.

♦ Como podemos implementar o comando switch demaneira mais eficiente?

♦ Em alguns casos, podemos utilizar uma tabela deendereços, de tal forma que ao acessar a tabela naposição correspondente a k, TabEnd[k], obtenhamos oendereço do rótulo desejado.

♦ Desta maneira, podemos tomar a decisão em tempoconstante.

Comando switch

♦ Melhorando o comando switch:

♦ Vamos supor que as variáveis f, g, h, i, j, k estão nosregistradores $s0 a $s5, e que $t2 contenha o 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;

}

Comando switch

♦ Utilizaremos a variável k como índice na tabela deendereços, e desviar de acordo com o valor carregado;

♦ Primeiro, temos que verificar se 0 <= k <= 3:

♦ Vamos utilizar k para indexação; por isto temos quemultiplicar k por 4.

slt $t3, $s5, $zero # teste se k<0bne $t0, $zero, Fim # se k<0, vá para Fimslt $t3, $s5, $t2 # teste se k<4beq $t3, $zero, Fim # se k>=4 vá para Fim

Comando switch

♦ Suponha que o vetor de endereços TabEnd, cujoendereço está em $t4, possui quatro posições, com osendereços correspondentes aos rótulos L0, L1, L2 e L3:

♦ Agora saltamos para o endereço presente em $t0:

add $t1, $s5, $s5 # t1 = 2 * kadd $t1, $t1, $t1 # t1 = 4 * k

add $t1, $t1, $t4 # t1 = endereço deTabEnd[k]lw $t0, 0($t1) # t0 = TabEnd[k]

jr $t0

Comando switch

♦ Por fim tratamos os casos do switch:

L0: add $s0, $s3, $s4 # f = i+jj Fim

L1: add $s0, $s1, $s2 # f = g + hj Fim

L2: sub $s0, $s1, $s2 # f = g – hj Fim

L3: sub $s0, $s3, $s4 # f = i – j (não precisamos saltar# para o Fim, já que a próxima# instrução tem o rótulo Fim)

Fim:

Resumo: instruções vistas atéagora

Categoria Instrução Exemplo SemânticaAdição add $s1, $s2, $s3 $s1 = $s2 + $s3AritméticaSubtração sub $s1, $s2, $s3 $s1 = $s2 - $s3Load word lw $s1, 100($s2) $s1 = Mem[$s2 + 100]Transferência

de dados Store word sw $s1, 100($s2) Mem[$s2 + 100] = $s1Branch onequal

beq $s1, $s2, L If ($s1 == $s2) goto L

Branch on notequal

bne $s1, $s2, L If ($s1 != $s2) goto L

DesvioCondicional

Set on lessthan

slt $s1, $s2, $s3 if ($s2 < $s3) $s1 = 1; else $s1 = 0;

Jump j 2500 goto 10000DesvioIncondicional Jump register jr $t1 goto $t1

Instruções de suporte aprocedimentos

♦ Procedimentos ou subrotinas são utilizadas pelosprogramadores para:• Facilitar a compreensão e manutenção de código;• Possibilitar o reaproveitamento de código.

♦ O código de um procedimento fica “isolado”, sendo ainterface com o restante do código dada pelosargumentos de entrada e pelos resultados de saída.

Instruções de suporte aprocedimentos

♦ Na execução de um procedimento, um programa deveseguir os seguintes passos:• Colocar os argumentos (parâmetros) em um lugar em

que o procedimento possa acessá-los;• Transferir o controle para o procedimento;• Executar a tarefa desejada;• Colocar o resultado da execução em um lugar em que

o código que chamou o procedimento possa acessar;• Retornar o controle para o ponto de origem.

Instruções de suporte aprocedimentos

♦ Qual o lugar mais rápido que pode armazenar dados emum computador?

♦ Registrador. Queremos utilizar registradoressempre que possível

♦ Software para MIPS aloca os seguintes registradorespara chamada de procedimentos:

♦ $a0 - $a3: quatro registradores que são utilizados parapassar parâmetros para os procedimentos;

♦ $v0 - $v1: dois registradores que são utilizados pararetornar valores calculados pelos procedimentos(resultados)

♦ $ra: registrador utilizado para retornar para o ponto deorigem (ra = return address).

Valores de retorno do procedimento

Desvio para procedimento

Instruções de suporte aprocedimentos

Execução do procedimento

Preparo argumentos para o procedimento $a0-$a3

$ra;desvi

o

$v0-$v1

Continuação do programa

Retorno para a continuação do programa jr $ra

C

MIPS

Exemplo de procedimento

... soma(a,b);... /* a:$s0; b:$s1 */}

int soma(int x, int y) { /* x:$a0; y:$a1 */return x+y;

}

endereço1000 add $a0,$s0,$zero # x = a1004 add $a1,$s1,$zero # y = b1008 addi $ra,$zero,1016 # $ra = 10161012 j soma # desvio para soma1016 ...2000 soma: add $v0,$a0,$a12004 jr $ra # volte p/ origem,

# no endereço1016

jal (jump and link)

♦ O assembly MIPS tem uma instrução de desvio só paraprocedimentos; ela causa um desvio para um endereço,e ao mesmo tempo guarda o endereço da próximainstrução em $ra: jal (jump and link).

jal Rotulo #desvio para o procedimento que tem#endereço marcado por Rótulo

jal (jump and link) ...

♦ Link, neste caso, quer dizer que é formada, no registrador$ra, uma referência para a instrução que vem logo após ainstrução jal, ou seja, a instrução jal é equivalente aoseguinte código:

♦ Por que existe a instrução jal??Procedimentos são muito comuns:

“faça o caso comum ser rápido”

$ra = PC + 4j Rótulo

C

MIPS

Exemplo de procedimento(revisado)

... soma(a,b);... /* a:$s0; b:$s1 */}

int sum(int x, int y) { /* x:$a0; y:$a1 */return x+y;

}

end1000 add $a0,$s0,$zero # x = a1004 add $a1,$s1,$zero # y = b1008 jal soma # prepara $ra e

# jump p/ procsoma1012 ...2000 soma: add $v0,$a0,$a12004 jr $ra # volte p/ origem,

# no endereço 1012

Exercício

♦ Qual o código em assembly para MIPS equivalente aoseguinte trecho em C, estando i em $s0 e j em $s1?

• i = sub(i,j); /* sub(a, b) {return a-b;} */

...add $a0, $s0, $zero # a0 = iadd $a1, $s1, $zero # a1 = jjal sub # chama a função

subadd $s0, $v0, $zero # i = sub(i,j)...

sub: sub $v0, $a0, $a1 # $v0 = a – bjr $ra # retorne para

origem

Usando mais registradores

♦ Suponha que um procedimento necessite de maisregistradores do que os 4 registradores de argumentos eos 2 de retorno.

♦ O código que vai chamar este procedimento pode estarutilizando diversos registradores, de tal forma que oprocedimento não pode utilizar os registradores dequalquer forma, uma vez que valores importantespoderiam ser perdidos.

♦ Assim, qualquer registrador que o procedimento utilize eque possa ser do interesse do código “chamador” deve terseu valor restaurado para o valor anterior à execução doprocedimento.

Usando mais registradores

♦ Como fazer isto?

♦ Processo conhecido por register spilling:• Uso de uma pilha, estrutura de dados do tipo LIFO

(last-in first-out);• Temos um apontador para o topo da pilha;• Este apontador é ajustado em uma palavra para cada

registrador que é colocado na pilha (operaçãoconhecida por push), ou retirado da pilha (operaçãoconhecida por pop).

• Em MIPS, um registrador é utilizado somente paraindicar o topo da pilha: sp (stack pointer)

Usando mais registradores

♦ Por razões históricas, a pilha “cresce” do maior endereçopara o menor endereço:

♦ Para colocar um valor na pilha (push), devemosdecrementar $sp em uma palavra e mover o valordesejado para a posição de memória apontada por $sp;

♦ Para retirar um valor da pilha (pop), devemos ler estevalor da posição de memória apontado por $sp, e entãoincrementar $sp em uma palavra.

0

Endereço

Código Programa

Estático Variáveis declaradas umavez para todo programa

HeapEspaço explicitamente criadomalloc: apontadores em C

PilhaEspaço para procedimentosarmazenarem informações$sp

stackpointer

Alocação de memória em C

Exemplo: exemplo_proc

♦ Suponha que tenhamos o seguinte código:

Vamos gerar o código correspondente em assembly MIPS.

int exemplo_proc (int g, int j, int i, int h){

int f;f = (g+h) – (i+j);return f;

}

Exemplo : exemplo_proc

♦ Os argumentos g, h ,i e j correspondem aos registradores$a0, $a1, $a2 e $a3, e f corresponde a $s0. Primeirocolocamos o rótulo do procedimento:

♦ exemplo_proc:

♦ Devemos então armazenar os registradores que serãoutilizados pelo procedimento. Como estaremos utilizandoos registradores $t0, $t1 e $s0, vamos colocá-los na pilha:

subi $sp, $sp, 12 # cria espaço para mais 3 itens napilhasw $t1, 8(sp) # empilha $t1sw $t2, 4(sp) # empilha $t2sw $s0, 0(sp) # empilha $s0

Exemplo : exemplo_proc

Como ficou a pilha?

$sp

Valoresempilhados

antes dafunção

Pilha antesda função

$t1

$t0

$s0$sp

Valoresempilhados

antes dafunção

Pilha duranteexecução da função

Exemplo : exemplo_proc

♦ As próximas instruções correspondem ao corpo doprocedimento:

♦ O resultado deve ser armazenado no registrador $v0:

add $v0, $s0, $zero # retorna f em $v0

add $t0, $a0, $a1 # $t0 = g + hadd $t1, $a2, $a3 # $t1 = i + jsub $s0, $t0, $t1 # f = $t0 = (g+h) –(i+j)

Exemplo : exemplo_proc

♦ Antes de sair do procedimento, devemos restaurar osvalores de $t0, $t1 e $s0, retirando-os da pilha:

♦ Voltamos então para a instrução seguinte ao ponto emque a função exemplo_proc foi chamada:

lw $s0, 0($sp) # desempilha $s0lw $t0, 4($sp) # desempilha $t0lw $t1, 8 ($sp) # desempilha $t1addi $sp, $sp, 12 # remove 3 itens da pilha

jr $ra # retorna para a subrotina quechamou

# este procedimento

Instruções de suporte aprocedimentos

♦ No exemplo anterior, nós utilizamos registradorestemporários e assumimos que os valores deles deveriamser guardados e restaurados.

♦ Para evitar que registradores que não são utilizados sejamempilhados e desempilhados, MIPS oferece duas classesde registradores:• $t0-$t9: 10 registradores temporários que não são

preservados pela função que é chamada.• $s0-$s7: 8 registradores que têm seus valores

preservados no processo de chamada deprocedimento. Desta forma, se estes registradoresforem utilizados pelo procedimento, eles devem terseus valores empilhados no início do procedimento edesempilhados no final.

Instruções de suporte aprocedimentos

♦ Esta simples convenção faz com que percamos menostempo empilhando e desempilhando registradores

♦ No exemplo, teríamos que preservar somente o valor de$s0.

♦ O que fazer se temos um código que utiliza registradorestemporários e vai chamar uma função??

♦ Podem aparecer problemas quando fazemos funções quechamam outras funções (por exemplo, funçõesrecursivas)??

Procedimentos aninhados

♦ Suponha que o programa principal chama a função A como argumento 3, ao colocar 3 em $a0 e utilizar a instruçãojal A.

♦ Suponha ainda que a função A chama a função B comargumento 7, ao colocar 7 em $a0 e utilizar a instruçãojal B.

♦ Uma vez que A ainda não terminou de executar temos umconflito no uso do registrador $a0.

♦ Um problema também aparece para o registrador $ra, queagora contém o valor para retorno de B.

♦ Se não tomarmos cuidado, poderemos não ser capazesnem de voltarmos para o programa principal!!!

♦ Como resolver?

Procedimentos aninhados:convenção sobre registradores

♦ Uma solução é empilhar todos os registradores queprecisam ser preservados.

♦ Para isto, temos que estabelecer uma convenção entre asubrotina que chama a função e a subrotina chamada,para estabelecer quais registradores serão preservados, epor quem.

♦ Definições• Chamadora: função que faz a chamada, utilizando jal;• Chamada: função sendo chamada.

♦ Podemos pensar nestas convenções como sendo umcontrato entre a Chamadora e a Chamada;

Por que utilizar convenções parachamadas de procedimentos?

♦ Se tanto a sub-rotina Chamadora quanto a Chamadaobedecerem a convenção, temos os seguintesbenefícios:

♦ programadores podem escrever funções quefuncionam juntas;

♦ Funções que chamam outras funções – como asrecursivas – funcionam corretamente.

Atenção!! Chamadora ou chamada não representa umapropriedade da função, mas sim o papel que a função exerceem uma chamada de procedimento específica. Assim, umafunção pode exercer o papel de chamadora e de chamada, sóque em diferentes chamadas de procedimento.

Direitos da Chamadora e daChamada

♦ Direitos da Chamada:• Utilizar livremente os registradores v, a, e t;• Assumir que os argumentos são passados

corretamente.

♦ Registradores que devem ser preservados pelaChamadora:• Endereço de retorno $ra• Argumentos $a0, $a1, $a2, $a3• Valores de retorno $v0, $v1• Registradores temporários $t0 - $t9

♦ Direitos da Chamadora• Utilizar os registradores s, sem que eles sejam

alterados pela Chamada• Assumir que os valores de retorno e a pilha estão

corretos

♦ Registradores que devem ser preservados pelaChamada:• Registradores $s $s0 - $s7

Direitos da Chamadora e daChamada

Exemplo: soma_recursiva

♦ Suponha que tenhamos o seguinte código, que calcula asoma n + (n-1) + … + 2 + 1 de forma recursiva:

♦ Vamos gerar o código correspondente em assemblyMIPS.

int soma_recursiva (int n){

if (n < 1)return 0;

elsereturn n + soma_recursiva(n-

1)}

Exemplo: soma_recursiva

♦ O parâmetro n corresponde ao registrador $a0.♦ Devemos inicialmente colocar um rótulo para a função, e

salvar o endereço de retorno, armazenado em $ra, oparâmetro $a0:

♦ Na primeira vez que soma_recursiva é chamada, o valorde $ra que é armazenado corresponde a um endereçoque está na sub-rotina que chama esta função

Soma_recursiva:subi $sp, $sp, 8 # prepara a pilha para receber

2# valores

sw $ra, 4($sp) # empilha $rasw $a0, 0($sp) # empilha $a0

Exemplo: soma_recursiva

♦ Vamos agora compilar o corpo da função. Inicialmente,testamos se n < 1:

♦ Se n >=1, a função deve retornar o valor 0. Não podemosnos esquecer de restaurar a pilha.

♦ Por que não carregamos os valores de $a0 e $ra antes deajustar $sp??

slti $t0, $a0, 1 # testa se n < 1beq $t0, $zero, L1 # se n>=1, vá paraL1

add $v0, $zero, $zero # valor de retorno é 0add $sp, $sp, 8 # remove 2 itens da pilhajr $ra # retorne para depois dejal

Exemplo: soma_recursiva

♦ Se n >=1, decrementamos n e chamamos novamente afunção soma_recursiva com o novo valor de n.

♦ Quando a soma para (n-1) é calculada, o programa voltaa executar na próxima instrução. Restauramos oendereço de retorno e o argumento anteriores, eincrementamos o apontador de topo de pilha:

L1:subi $a0, $a0, 1 # argumento passa a ser (n-1)

jal soma_recursiva # calcula a soma para (n-1)

lw $a0, 0($sp) # restaura o valor de nlw $ra, 4($sp) # restaura o endereço de retornoaddi $sp, $sp, 8 # retira 2 itens da pilha.

Exemplo: soma_recursiva♦ Agora o registrador $v0 recebe a soma do argumento

antigo $a0 com o valor atual em $v0 (soma_recursivapara n-1):

♦ Por último, voltamos para a instrução seguinte à quechamou o procedimento:

add $v0, $a0, $v0 # retorne n +soma_recursiva(n-1)

jr $ra # retorne para o“chamador”

Variáveis automáticas eestáticas

♦ Variáveis automáticas são aquelas que são locais a umprocedimento, e que portanto só são acessíveis enquantoo procedimento está ativado.

♦ Quando uma função contém dados que são grandesdemais para serem colocados em registradores, eles sãocolocados na pilha. Exemplos são estruturas de dadoscomo registros (structs) ou vetores estáticos (que nãousam malloc para alocação).

♦ Já as variáveis estáticas são aquelas que estão ativasdurante toda a execução do programa. Em C, elas são asvariáveis globais e as variáveis marcadas como static.

Variáveis automáticas eestáticas

♦ A região da pilha onde são armazenados os registradoressalvos e as variáveis locais a um procedimento é chamadade registro de ativação.

♦ Para facilitar o acesso a estas variáveis, o registrador $fp(frame pointer) é utilizado. Ele marca o início do registro deativação, e não é atualizado de forma automática, sósendo utilizado se houver variáveis do procedimento napilha. A vantagem de se usar $fp é que $sp pode ter ovalor alterado durante a execução da função.

♦ Para facilitar o acesso às variáveis estáticas, o registrador$gp (global pointer) é utilizado. Estas variáveis sãoalocadas na região de memória “dados estáticos”, verfigura 3.22 do livro (seção 3.9)

Exemplo : $fp e $sp

$sp

Registro deativação

anterior (outrafunção)

Pilha antesda função

$fp

Registradores$s salvos (se

houver)

Registradores$a salvos (se

houver)

$ra salvo

Estruturas evetores locais(se houver)$sp

Registro deativação

anterior (outrafunção)

Pilha duranteexecução da função

$fp

0 zero constante 0

1 at reservado para omontador

2 v0 resultados de funções

• v1

4 a0 argumentos

5 a1

6 a2

7 a3

8 t0 temporários: Chamadora

. . . é que deve salvar

15 t7

Registradores MIPS: resumo daconvenção de software

16 s0 Chamada é que deve

. . . salvar

23 s7

24 t8 temporários (cont.)

25 t9

26 k0 reservados para o kernel

27 k1 do sistema operacional

28 gp global pointer

29 sp stack pointer

30 fp frame pointer

31 ra endereço de retorno

Fig. A.10

Categoria Instrução Exemplo SemânticaAdição add $s1, $s2, $s3 $s1 = $s2 + $s3AritméticaSubtração sub $s1, $s2, $s3 $s1 = $s2 - $s3Load word lw $s1, 100($s2) $s1 = Mem[$s2 + 100]Transferência

de dados Store word sw $s1, 100($s2) Mem[$s2 + 100] = $s1Branch onequal

beq $s1, $s2, L If ($s1 == $s2) goto L

Branch on notequal

bne $s1, $s2, L If ($s1 != $s2) goto L

DesvioCondicional

Set on lessthan

slt $s1, $s2, $s3 if ($s2 < $s3) $s1 = 1; else $s1 = 0;

Jump j 2500 goto 10000Jump register jr $t1 goto $t1

DesvioIncondicional

Jump & link jal 2500 $ra = PC + 4; goto 10000

Resumo: instruções vistas até agora

Trabalhando com caracteres estrings

♦ A maior parte dos computadores hoje utiliza bytes pararepresentar caracteres, quase sempre utilizando acodificação ASCII (American Standard Code forInformation Interchange).

♦ A seção 3.7 traz a tabela ASCII, que deve ser utilizadacomo fonte de consulta.

♦ Instruções de transferência de palavras (lw, sw) sãosuficientes para transferir bytes também. Neste caso,bytes individuais poderiam ser lidos ou escritos, através douso de máscaras, com as instruções e e ou lógicos (serãovistas no capítulo 4).

t No entanto, como grande parte dos programasutiliza texto, MIPS fornece instruções específicaspara mover bytes.

t Leitura de bytes:

t load byte (lb): lê um byte da memória,colocando-o nos 8 bits mais à direita de umregistrador

t Ex: lb $t0, 0($sp) # lê byte que está no topo dapilha

Trabalhando com caracteres estrings

♦ Escrita de bytes:

♦ store byte (sb): escreve na memória o byte que estános 8 bits mais à direita de um registrador

♦ Ex: sb $t0, 0($sp) # escreve byte no topo da pilha

Trabalhando com caracteres estrings

♦ Caracteres são normalmente combinados em strings oucadeias de caracteres, que possuem um número variávelde caracteres.

♦ Existem 3 opções para representar uma string:

♦ A primeira posição da string é reservada paraarmazenar o comprimento da cadeia;

♦ Ex: “casa” = 4 _c_ _a_ _s_ _a_ = 4 99 97 11597

♦ Qual o tamanho máximo da string se cadaposição ocupa um byte?

Trabalhando com caracteres estrings

♦ A string é armazenada em uma estrutura, em que umavariável diz o comprimento da cadeia e outra traz oscaracteres que compõe a cadeia;

Ex: “casa” = {4, _c_ _a_ _s_ _a_} = {4, 99 97 115 97}

♦ A última posição de uma cadeia é indicada por umcaractere especial.

Ex: “casa” = _c_ _a_ _s_ _a_ 0 = 99 97 115 97 0

♦ Esta é a representação utilizada pela linguagem C,sendo o marcador de final de string o valor 0.

Trabalhando com caracteres estrings

Exemplo: string_copy

♦ Suponha que tenhamos o seguinte código:

void strcpy(char x[], char y[]){

int i;i = 0;while ((x[i] = y[i]) != 0)

i = i + 1;}

Vamos gerar o código correspondente em assembly MIPS.

♦ Os endereços base de x e de y estão em $a0 e $a1,enquanto que i está em $s0. Precisamos então preservaro valor de $s0:

strcpy:addi $sp, $sp, -4 # espaço para 1 item napilhasw $s0, 0($sp) # salva $s0

♦ Inicializamos i com 0:

add $s0, $zero, $zero # i = 0 + 0

Exemplo: string_copy

♦ Podemos fazer o laço então; o endereço de y[i] é formadoadicionando i com o endereço base de y:

L1:add $t1, $a1, $s0 # $t1 = endereço de y[i]

♦ Por que não multiplicamos i por 4??♦ y é um vetor de bytes, e não de palavras!!!

♦ Agora carregamos o caractere y[i]:

lb $t2, 0($t1) # $t2 = y[i]

Exemplo: string_copy

♦ Preparamos agora o endereço de x[i] em $t3, earmazenamos y[i]:

add $t3, $a0, $s0 # $t3 = endereço de x[i]sb $t2, 0($t3)# x[i] = y[i]

♦ Se o caractere y[i] for 0, saimos do loop:

beq $t2, $zero, L2 # se y[i] == 0, desvie para L2

♦ Senão, incremente i e itere novamante:

addi $s0, $s0, 1 # $s0 = $s0 + 1j L1 # desvie para L1

Exemplo: string_copy

♦ Restauramos $s0, ajustamos $sp e retornamos:

• L2: # fim de string• lw $s0, 0($sp) # restaura $s0• addi $sp, $sp, 4 # retira 1 item da

pilha• jr $ra # retorna para

chamador

♦ Poderíamos ter alocado o registrador $t0 para i, e nestecaso não teríamos que empilhar e desempilhar $s0.

♦ Percebemos que é melhor utilizar primeiro osregistradores $t que $s em funções que não chamamoutra função

Exemplo: string_copy

Padrão Unicode♦ Está se tornando cada vez mais comum um outro tipo de

codificação para caracteres, o padrão Unicode. Javautiliza este padrão.

♦ Este padrão, além de representar todos os caractereslatinos, pode representar símbolos de letras orientais,dentre outros.

♦ Um caractere passa a ocupar 16 bits. Quantos símbolospodem ser representados?

♦ MIPS inclui instruções para trabalhar com 16 bits, masnão veremos elas neste curso. Quem estiver curioso,consulte o apêndice A do livro.