Sinal e Overflow no MIPS

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

Oi pessoal! Dando continuidade à série MIPS, hoje mostrarei como são tratados os números com sinal, isto é, -1 é a mesma coisa que +1? Isto é importante pois algumas instruções trabalham com essa questão, portanto, vamos ver como funciona o sinal do número, positivo e negativo. Bora!

Representação de Números com e sem Sinal

Os números são divididos pelos positivos e negativos, e o zero. É fácil pra gente entender isso, mas o computador não sabe fazer isso sozinho, na verdade os projetistas têm de pensar em uma forma de dizer ao microprocessador como lidar com números positivos e negativos. E não nos esqueçamos que isso também se aplica a números quebrados, isto é, números reais, números de ponto flutuante, e que os nossos microprocessadores só conhecem 0 e 1.

Normalmente, o sinal positivo é representado com o bit 0 e o sinal negativo é representado com o bit 1. O número é então representado com a sua magnitude mais o bit de sinal, onde a magnitude é a quantidade de bits que pode representar o número. O bit de sinal fica sempre no MSB (Most Significant Bit ou Bit Mais Significativo) do número, que fica mais à esquerda. LSB é o nome dado ao bit mais à direita do número, ou seja, o Least Significant Bit (Bit Menos Significativo). O MSB varia conforme a quantidade de bits que o sistema de computação trabalha. Se for 64 bits, então o bit de sinal fica no bit63, se for 32 bits, então o bit de sinal fica no bit31, e assim por diante.

BIT DE SINALMAGNITUDE0 (+) OU 1 (-)bits

Os sistemas de numeração mais utilizados em computação são: binário (2), octal (8), hexadecimal (16) e decimal (10). Podemos converter as bases dos números, isto é, passar da base binária para a base decimal, e vice-versa, usando métodos de conversão de bases. Para elucidar, vamos ver como fica o número +11 nos três sistemas de numeração. Em binário:

Figura 1: Encontrando o valor binário de +11

Portanto, 11 em binário é 1011, e +11 é 01001, em que 0 é o bit de sinal e 1011 é a magnitude. Bom, apenas para reforçar que esses tipos de conversões já devem ser conhecidas por vocês, estou apenas recapitulando aqui, para que todos possam acompanhar o meu raciocínio e a minha explicação sobre a questão do SINAL. Quando convertemos números decimais para binário, nós usamos a base binária para tal, ou seja, 2x, onde cada posição tem um valor na base 2 correspondente, começando sempre da direita para esquerda, conforme mostra a Figura 1.

Para converter para as bases Octal e Hexadecimal, também usaremos a base binária, porém, dividiremos o Octal em grupos de 3 bits, e o Hexadecimal em grupos de 4 bits. Portanto, a cada 3 bits da base binária, teremos 1 bit na base Octal e, a cada 4 bits da base binária, teremos 1 bit na base Hexadecimal, também seguindo a ordem da direita para a esquerda. Não nos esqueçamos que para obter o valor correspondente, precisamos somar as posições que contém o valor 1.

Figura 2: Convertendo 11 para Octal
Figura 3: Convertendo 11 para Hexadecimal

Ótimo, fazendo isso com o número positivo é fácil e simples, aparentemente, mas e com o número negativo? Até é fácil de fazer isso na mão, mas em termos de projeto de microprocessadores não é tão simples assim e isso gerou inúmeros problemas. Assim, a representação por Sinal e Magnitude não é utilizada na prática, ao invés, é utilizado algo diferente, mais funcional e simples até, que chamamos de complemento a 2. Para facilitar, vocês podem seguir os passos a seguir ao utilizar esta técnica:

Complemento a 1

Para encontrar o complemento a 1 de um número, você precisa inverter o número, isto é, onde é zero troque por um e onde é um troque por zero. Exemplo:

+11001011Complemento a 1 [C1] de +11110100

Complemento a 2

Para encontrar o complemento a 2 você deverá somar 1 ao C1, onde esse 1 deve estar no bit0, da seguinte forma:

Figura 4: Encontrando o valor do complemento a 2 de +11

Assim, o complemento a 2 [C2] de +11 é 110101, ou seja, este é o valor binário de -11. Bem, se você notar o número + 11 começa com zero e o número +11 em C2 começa com um, coincidência será? De qualquer forma, números negativos sempre têm o MSB com 1, e números positivos sempre têm o MSB com 0, da mesma forma que números pares sempre têm o bit0 com zero e, números ímpares têm o bit0 com 1. Para tirar a prova, você fará o seguinte:

Figura 5: Encontrando o valor do complemento a 2 de -11

O resultado do complemento a 2 de -11 é exatamente +11, portanto:

+11001011-11110101

Fácil? Difícil? O que você pode fazer para entender melhor isto são exercícios. Tente converter o máximo de números possível, assim o processo ficará mais simples. De qualquer forma, o BIT DE SINAL continua existindo aqui neste método, vamos entender. Um número como o +11, quando o convertemos tem apenas 5 bits, isto é, ele pode ser representado com apenas 5 bits, mas uma máquina que trabalhe com 32 bits precisa de todos os 32 bits preenchidos para a manipulação do número. Assim, um número com o +11 ficaria assim:

0000 0000 0000 0000 0000 0000 0000 1011

e o -11 ficaria assim:

1111 1111 1111 1111 1111 1111 1111 0101

Onde o bit roxo é o bit de sinal quando o número é formado por 5 bits. O bit marcado em azul é o MSB, os bits em verde são o número propriamente dito, o resto disso tudo é a extensão do sinal, isto é, números 1s e 0s foram copiados do sinal (que está em roxo) para completar os 32 bits. O microprocessador agora consegue saber que esse número é positivo ou negativo analisando apenas o BIT DE SINAL, que será o bit31, sendo 0 = positivo e 1 = negativo. Em uma máquina 32 bits a representação dos números inteiros é dada de -231 até (231-1).

Casos Especiais

Tem uma situação interessante quando usamos complemento a 2. Os números binários que ficam nas extremidades da magnitude, entre as faixas positivas e negativas, são um caso particular, pois nestes casos, o complemento de 2 destes números é o próprio número. Vou elucidar mostrando o complemento a 2 do numero 8.

Figura 6: Encontrando o complemento a 2 de +8

 

Figura 7: Encontrando o complemento a 2 de -8

Para quem não entendeu a parte de aritmética, ou seja, porque 1 + 1 = 10, aconselho a estudar ARITMÉTICA DIGITAL, que é referente ao projeto, estudo e aprendizado de operações matemáticas aplicadas a bits. Continuando, perceberam que o número 8 é exatamente o mesmo? A única coisa que mudou foi o sinal, 1 para negativo e 0 para positivo. Esse tipo de situação também acontece com o 16, 32, 64, 128, e assim por diante, faça o teste você mesmo. Portanto:

-81 1000+80 1000

Overflow

O overflow ocorre quando o hardware não é capaz de representar os números que normalmente são resultados de alguma operação aritmética. Vou mostrar um exemplo bem simples do que significa o overflow e assim elucidar a problemática envolvendo essa situação em números com sinal.

Figura 8: Exemplo de Overflow

Neste exemplo estou somando +9 com -4 e Carry significa “Vai um”. A estratégia usada aqui foi a de descartar o bit que ficou sobrando mais à esquerda, logo após o bit de sinal. Se esse bit extra for considerado, ele poderá alterar drasticamente todos os valores, pois não corresponde à realidade. Neste exemplo o bit de sinal é zero e o bit de overflow é um, portanto, a extensão do sinal do número deve ser zero e não um. Se esse bit um for utilizado, o número deixará de ser positivo e se tornará negativo, olha só a dor de cabeça! Portanto, é preciso ter muito cuidado com o sinal do número e o overflow! Tendo em vista essas duas situações para o número binário, Sinal e Overflow, MIPS projetou diversas instruções que tratam de ambas.

Instruções com Sinal e Overflow

Algumas instruções MIPS trabalham com números que tenham ou não sinal, e também com o Overflow, é o caso das instruções listadas abaixo. Como são muitas instruções, nós não estudaremos todas, porém, a partir do exemplo de algumas, já será possível compreender o comportamento das outras.

Até o presente artigo, praticamente todas as instruções que estudamos não tratam do Overflow e Sinal de forma explícita. Por exemplo, as instruções de adição com overflow e sem overflow têm basicamente os mesmos formatos e características, o que muda são os opcodes e mnemônicos: ADD (20) e ADDU (21). A instrução “set se menor que” é o mesmo caso, SLT (42) e SLTU (43). Finalizando, quando precisar trabalhar de forma explícita com sinal e overflow, utilize as instruções projetadas para essas situações.

Conclusão

Bem, basicamente é desta forma que a máquina entende os números com sinal. Agora que você já sabe como isso é feito, podemos trabalhar com instruções específicas para números com sinal. Além disso, as Linguagens de Programação de Médio e Alto Nível também podem fornecer recursos para diferenciar números com e sem sinal, como, por exemplo, a Linguagem C, que permite o uso de UNSIGNED e SIGNED para determinar se aquele tipo numérico tem sinal ou não. Preparados? Estudem, deixem suas dúvidas aqui, responderei assim que puder e, no próximo artigo, mais novidades. Até pessoal.

Saiba mais

Entendendo a Aritmética em Ponto Fixo

Utilizando o ULP do ESP32 para co-processamento

Tipos de dados para uso em algoritmos