Instrução SLT no MIPS

instrução MIPS LW e SW IF Simples no MIPS

Oi pessoal! Tudo bem com todos? Conseguiram resolver os exercícios que eu deixei no último artigo? Bom, quem conseguiu, parabéns! Quem não conseguiu, hoje vou explicar uma instrução nova que irá ajudar na resolução desses exercícios. Não se esqueçam de verificar os artigos anteriores para conseguir acompanhar o artigo de hoje, beleza? Bora então?

 

 

A Instrução SLT

 

SLT significa Set on less Than, ao pé da letra seria algo como comparar menor que, então essa instrução será muito utilizada em comparações entre registradores, para identificar quem tem o maior ou menor valor. A função desta instrução é comparar dois valores de dois registradores diferentes e atribuir o valor 1 a um terceiro registrador se o valor do primeiro registrador for menor que o valor do segundo registrador. Caso contrário, atribuir zero. A sintaxe é:

 

SLT registrador_temporário, registrador1, registrador2

 

O formato da instrução é: 

OpCodeRSRTRDSHAMTFUNCT
Código da OperaçãoRegistrador TemporárioRegistrador a ser comparado 2Registrador a ser comparado 1não usadocódigo da operação aritmética
6 bits5 bits5 bits5 bits5 bits6 bits

 

 

Vamos supor a seguinte instrução MIPS:

 

SLT $t0, $s1, $s2

 

Isso é o mesmo que:

 

$st0 = $s1 < $s2

 

O registrador temporário $t1 armazena o resultado da avaliação da expressão $s1 < $s2. Se for verdade que $s1 é menor que $s2, então, é atribuído ao registrador temporário o valor 1. Agora se o resultado da comparação entre os dois registradores for FALSO, ou seja, $s1 NÃO é menor que $s2, então, é atribuído ao registrador temporário o valor 0. O registrador temporário será utilizado por outra instrução, para realizar outra tarefa.

 

 

Exemplo

 

Considere o seguinte código em C: 

 

 

Vamos fazer a compilação desse trecho de código em C para MIPS, seguindo o nosso roteiro padrão:

  1. Linguagem de Montagem;
  2. Linguagem de Máquina;
  3. Representação e;
  4. Código de Máquina.

 

Considere a = $s0, b = $s1, c = $s2, i = $s3, j = $s4.

 

a) Linguagem de Montagem

 

linhacódigo
1slt $t0, $s3, $s4
2bne $t0, $zero, ELSE
3add $s0, $s1, $s2 #a = b + c; (se $t0 <> 0)
4j Exit #desvia para exit
5ELSE: sub $s0, $s3, $s4 #a = b – c; (se $t0 = 0)
6Exit:

 

Vamos entender o que acontece aqui a partir do Fluxograma apresentado na Figura 1. Primeiro é feita a comparação entre os registradores $s3 e $s4. Se a resposta for verdadeira, o fluxo segue pelo lado direito do diagrama, em que o registrador $t0 receberá o valor 1. Se a resposta for falsa, então o fluxo segue pelo lado esquerdo do diagrama, em que o registrador $t0 receberá o valor 0. A partir daí, o fluxograma segue para uma próxima avaliação, que será a instrução BNE (branch not equal - desvie se não for igual). Se o conteúdo do registrador $t0 for diferente de zero, que aqui é representado pelo registrador $zero (o qual contém o valor zero SEMPRE), então a resposta é verdadeira, e o fluxo do programa segue pelo lado direito. Caso contrário, a resposta é falsa e o fluxo segue pelo lado esquerdo.

 

Fluxograma de SLT com BNE.
Figura 1: Fluxograma de SLT com BNE.

  

Vamos agora supor alguns valores para esses registradores, pra ficar mais claro o seu uso. Observe a Figura 2. Suponha que $s3 = 50 e $s4 = 100, assim 50 é menor que 100? Sim! Então a resposta é verdadeira. O registrador $t0 receberá o valor 1. Em seguida, BNE fará a comparação do registrador $t0 com o registrador $zero, como $t0 = 1, então t0 não é igual a zero, seguindo pelo lado direito do fluxograma.

 

Representando o Fluxograma quando a resposta é verdadeira.
Figura 2: Representando o Fluxograma quando a resposta é verdadeira.

 

Observe a Figura 3. Suponha que $s3 = 200 e $s4 = 60, assim 200 é menor que 60? Não! Então a resposta é falsa. O registrador $t0 receberá o valor 0. Em seguida, BNE fará a comparação do registrador $t0 com o registrador $zero, como $t0 = 0, então t0 é igual a zero, seguindo pelo lado esquerdo do fluxograma.

 

Instrução SLT no MIPS - Representando o fluxograma quando a resposta é falsa.
Figura 3: Representando o fluxograma quando a resposta é falsa.

 

b) Linguagem de Máquina

slt $8, $19, $20
bne $8, $zero, ELSE
add $17, $18, $16     
j Exit                      
ELSE: sub $19, $20, $16    
Exit:

 

c) Representação

 

Endereço de Memória

 

Representação

OPCODE

RS

RT

RD

SHAMT

FUNCT

80000

0

$19

$20

$8

0

42

80004

5

$8

$zero

80016

80008

0

$17

$18

$16

0

32

80012

2

80020

80016

0

$19

$20

$16

0

34

80020

 . . .

 

Agora vamos entender algo importante sobre os valores que devem ser inseridos no lugar dos labeLs ELSE e EXIT. Sabemos que o endereço 80004 pula para o endereço 80016, que é a nossa quinta linha de código, ou seja, o ELSE.

 

Precisamos lembrar que as instruções MIPS possuem endereços em bytes, de modo que os endereços das palavras sequenciais diferem em 4 bytes. Começamos esse bloco de comando no endereço 80000 e terminamos no endereço 80020 (exit).

 

Cada instrução está inserida no seu endereço correspondente que difere em quatro bytes. O cálculo que devemos fazer deve considerar o endereço SEGUINTE e NÃO o endereço atual da instrução.

 

Assim, a instrução BNE, na segunda linha, acrescenta duas palavras, ou oito bytes, ao endereço da instrução SEGUINTE, especificando o destino do desvio em relação à instrução seguinte, e não em relação à instrução de desvio.

 

O endereço da instrução seguinte é 80008. Agora, veja que curioso, se você fizer 80016 - 80008, tem-se como resultado o número 8, isto é, oito bytes, o que significa que devemos "pular" duas posições na memória, portanto, o número 2 é quem deve ir no campo endereço da instrução BNE. Se você fizer 80008 + 8, o resultado será 80016, que é exatamente o endereço para onde queremos ir.

 

Ainda está dificil de entender? Vou tentar simplificar, veja como a tabela deve ficar:

 

Endereço de Memória

Representação

OPCODE

RS

RT

RD

SHAMT

FUNCT

80000

0

$19

$20

$8

0

42

80004

5

$8

$zero

2

80008

0

$17

$18

$16

0

32

80012

2

1

80016

0

$19

$20

$16

0

34

80020

 . . .

 

O número 2 é o número de instruções de distância para se desviar até ELSE. O número 1 é o número de instruções de distância para se desviar até EXIT. Abstraindo, podemos resumir o cálculo MANUAL em duas fases:

 

a) Número de Instruções de Distância do Desvio

 

Qtde de bytes = endereço de memória de desvio - endereço de memória seguinte

 

Qtde de bytes = 80016 - 80008 = 8 bytes => 2 instruções de distância

Qtde de byte = 80020 - 80016 = 4 bytes => 1 instrução de distância

 

 

b) Cálculo do endereço de desvio

 

endereço desejado = endereço seguinte ao atual + quantidade de bytes

 

endereço desejado = 80008 + 8 = 80016

endereço desejado = 80016 + 4 = 80020

 

É claro que os compiladores fazem esse cálculo de forma automática, aqui estou mostrando pra vocês algo bem manual, no sentido de aprendizagem didática. Mas, no geral, o cálculo automático é feito usando o PC (Contador de Programa), que contém o valor da instrução corrente. O endereço relativo ao PC é o endereço relativo à instrução seguinte, isto é:

 

PC = PC + 4.

(PC = Endereço Atual + 4 bytes)

 

Assim, EXIT seria calculado como o conteúdo do registrador mais o campo do endereço, o qual é calculado pela própria instrução de desvio condicional. Portanto, a instrução de desvio poderia calcular algo como:

 

Contador de Programa = Contador de Programa + Endereço de Desvio.

 

Vale ressaltar aqui que os desvios condicionais tendem a desviar para a instrução mais próxima e quase metade de todos os desvios condicionais é para endereços situados a menos de 16 instruções (de "distância") da origem do desvio. Se você ainda não conseguiu entender, não se preocupe! Voltarei a falar sobre endereçamento, especificamente sobre eles, então não se preocupe tanto por hora.

  

d) Código de Máquina

 

Endereço de Memória

Representação

OPCODE

RS

RT

RD

SHAMT

FUNCT

80000

000 000

‭10 011‬

10 100‬

000 101

00 000

‭101 010‬

80004

000 101

01000

00 000

‭0000 0000 0000 0010

80008

000000

‭10 001‬

‭10 010‬

10 000‬

00 000

‭100 000‬

80012

000 010

0000 0000 0000 0000 0000 0000 01

80016

000 000

10 011‬

10 100‬

‭10 000‬

00 000

‭100 010‬

80020

 ...

  

Agora que vocês já conhecem essa instrução, que tal refazer alguns dos exercícios apresentados nos artigos anteriores e verificar o resultado? Para concluir, saliento que a arquitetura MIPS não inclui uma instrução "desvie se menor que".

 

Uma instrução como esta fugiria do princípio de simplicidade de equipamento proposta por Von Neuman, além de que, ela também poderia esticar o tempo do ciclo de clock, ou ainda exigiria mais ciclos de clock.

 

Assim, duas instruções rápidas são mais úteis do que várias instruções mais complexas. Compiladores MIPS utilizam as instruções SLT, SLTI, BEQ, BNE e o valor fixo ZERO (registrador $zero) para criar todas as condições de operações relacionais: igual, diferente, menor que, maior que, menor ou igual, maior que e maior ou igual.

 

Fiquem atentos, nos próximos artigos falarei sobre como implementar operações lógicas, o uso de valores imediatos, números com e sem sinal, e outras operações matemáticas básicas.

 

Até pessoal!!

Outros artigos da série

<< Instrução IF Composto no MIPSOperações Lógicas no MIPS >>
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Elaine Cecília Gatto
Bacharel em Engenharia de Computação. Mestre em Ciência da Computação. Doutoranda em Ciência da Computação. Co-fundarora e Líder das #GarotasCPBr. Pesquisadora Convidada no Grupo de Pesquisa: "Artes em Tecnologias Emergentes" do Programa de Pós Graduação em Design na UNESP Campus Bauru. Cantora, Docente no Magistério Superior, Geek, Nerd, Otaku e Gamer. Apaixonada por Michael Jackson, Macross, Rocky Balboa, Séries, Filmes, Cervejas e Vinhos. Mais informações sobre mim você encontra em: http://lattes.cnpq.br/8559022477811603.

10
Deixe um comentário

avatar
 
4 Comment threads
6 Thread replies
3 Followers
 
Most reacted comment
Hottest comment thread
6 Comment authors
Elaine Cecília GattoLeonardoTatiana AlmeidaNeto ChavesElaine Cecília Gatto Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Leonardo
Visitante
Leonardo

Acredito que na transformação do exemplo de código em C para Assembly deveria ser usado beq no lugar de bne. Tirando isso, um ótimo artigo!

Elaine Cecília Gatto
Visitante
Elaine Cecília Gatto

Oi! Estou explicando as instruções pouco a pouco, então, um exemplo para cada instrução. Depois cada um pode escolher o comando que desejar para a conversão! Muito Obrigada =)

Tatiana Almeida
Visitante
Tatiana Almeida

b) Linguagem de Máquina
slt $8, $19, $20
bne $8, $zero, ELSE
add $17, $18, $16
j Exit
ELSE: sub $19, $20, $16
Exit:

c) Representação

Endereço de Memória
Representação
OPCODE RS RT RD SHAMT FUNCT
80000 0 $19 $20 $8 0 42
80004 5 $8 $zero 80016
80008 0 $17 $18 $16 0 32
80012 2 80020
80016 0 $19 $20 $16 0 34
80020 . . .

ESTA linha 80004 5 $8 $zero 80016

Tem que ser 4 opcode por ser bne?

Elaine Cecília Gatto
Visitante
Elaine Cecília Gatto

Oi! É de 4 em 4 pois é assim que é feito o endereçamento de memória no MIPS. Esta regra deve ser seguida a risca ok! Explico isso em outro artigo.

Neto Chaves
Visitante
Neto Chaves

Mais um ótimo artigo Elaine meus parabéns! Teve uma coisa que ficou confuso para mim, no exemplo que você usou: if ( i < j ) a = b + c; else a = b – c; Ou seja se i for menor que j faz a = b + c se não for faz a = b – c, mas da forma que você colocou no código de montagem e no fluxograma acontece o contrario. slt $t0, $s3, $s4 bne $t0, $zero, ELSE add $s0, $s1, $s2 #a = b + c; (se $t0 0) j Exit #desvia para… Leia mais »

Elaine Cecília Gatto
Visitante
Elaine Cecília Gatto

Neto, o preenchimento da tabela e código fonte é diferente mesmo, é preciso notar que a representação deve seguir os campos específicos e, os valores, devem ser colocados no campo respectivo. Veja, isso está definido na linguagem e deve ser preenchido assim, mesmo que pareça estar ao contrário.

Luiz Felipe Neves
Visitante

Diz para mim que os copiladores já fazem isto! hahahahah

Elaine Cecília Gatto
Visitante
Elaine Cecília Gatto

Oi Luiz!!!! Os compiladores das Linguagens de alto e médio nível fazem isso sim, você não tem que se preocupar. Logo escreverei um artigo detalhando esse processo de compilação. Mas se você for programar diretamente em Linguagem Assembly, você terá de conhecer essas instruções mais a fundo, tudo bem?

Muito Obrigada!
Até

Luiz Felipe Neves
Visitante

hahahahah ferrou! Obrigado.