Conjunto de Instruções - cic.unb.brrjacobi/ensino/OAC/Instrucoes1x1.pdf · Estruturas de dados...
-
Upload
trinhtuyen -
Category
Documents
-
view
214 -
download
0
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
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.