Cálculos com Binários
Nesta seção faremos alguns cálculos com números binários, considerando cada um de seus dígitos, também chamados de bits. Além de operações aritiméticas clássicas como adição, subtração, multiplicação e divisão, estudaremos também conjunção, disjunção, negação e disjunção exclusiva. Também incluiremos outras operações bit-a-bit que fogem da álgebra tradicional, como deslocamento e rotação de bits. Todas são importantes pois existem no contexto do Assembly, que estudaremos no futuro.
Conjunção (AND)
Dados dois bits x e y, a conjunção entre eles resulta em 1 se ambos forem iguais a 1. Na programação, o seu símbolo na programação é normalmente o "e comercial" (&). Sendo assim, a chamada tabela verdade desta operação é:
0
0
0
0
1
0
1
0
0
1
1
1
Então suponha que queiramos calcular a conjunção do número 0xa com 12. Sim, estamos misturando dois sistemas de numeração (hexadecimal e decimal) na mesma operação. E por que não? O segredo é converter para binário e fazer o cálculo para cada bit, respeitando a tabela verdade da conjunção. Mãos à obra:
O resultado é 0b1000, ou 8 em decimal. Sendo assim, as linhas abaixo farão o mesmo cálculo, ainda que utilizem sistemas de numeração (bases) diferentes:
Por que utilizei tantas bases diferentes? Quero com isso por na sua cabeça que um número é só um número, independente da base na qual ele está sendo representado.
Disjunção (OR)
O resultado da disjunção entre dois bits x e y é 1 se pelo menos um deles for 1. Sendo assim, segue a tabela verdade:
0
0
0
0
1
1
1
0
1
1
1
1
Na programação, o símbolo normalmente é a barra em pé (|). Por exemplo, vamos calcular a disjunção entre 8 e 5:
O resultado é 0b1101, que é 13 em decimal.
Aí você pode questionar:
Opa, então a disjunção é tipo a soma?
Te respondo:
Não.
Veja que o resultado da disjunção entre 9 e 5, também é 13:
Isso porque numa soma entre 1 e 1 o resultado seria 10 (2 em decimal), já na operação OU o resultado é 1.
Disjunção Exclusiva (XOR)
A disjunção exclusiva entre x e y resulta em 1 se somente um deles for 1. Sendo assim:
0
0
0
0
1
1
1
0
1
1
1
0
Assim como a disjunção é normalmente chamada de "OU", a disjunção exclusiva é chamada de "OU exclusivo", ou simplesmente XOR. O símbolo que representa a disjunção exclusiva em programação é o circunflexo (^).
Algumas propriedades importantes desta operação são:
Você pode aplicá-la em qualquer ordem. Então, x ^ (y ^ z) = (x ^ y) ^ z por exemplo.
O XOR de um número com ele mesmo é sempre zero.
O XOR de um número com zero é sempre ele mesmo.
A operação XOR tem vários usos em computação. Alguns exemplos:
Detecção de Diferenças
É possível saber se um número é diferente de outro com XOR. Se os números forem diferentes, o resultado é diferente de zero. Por exemplo, tomemos um XOR entre 8 e 5 e outro entre 5 e 5:
Zerar Variáveis
Fica claro que é possível zerar variáveis bastando fazer uma operação XOR do valor dela com ele mesmo, independentemente de que valor é este:
Troca de Valores Entre Duas Variáveis
O algoritmo conhecido por XOR swap consiste em trocar os valores de duas variáveis somente com operações XOR, sem usar uma terceira variável temporária. Basta fazer, nesta ordem:
XOR entre x e y e armazenar o resultado em x.
XOR entre x e y e armazenar o resultado em y.
XOR entre x e y e armazenar o resultado em x.
Veja:
Analisando em binário:
Cifragem
Dado um número x, é possível calcular o resultado de uma operação XOR com um valor qualquer que chamaremos de chave. Se usarmos a mesma chave num XOR com este resultado, obtemos o número original:
Portanto, para uma cifrabem básica, se você quiser esconder o valor original de um número antes de enviá-lo numa mensagem, basta fazer um XOR dele com uma chave que só você e o receptor da mensagem conheça (0x42 no exemplo). Assim você usa a chave para fazer a operação XOR com ele e instrui o receptor da mensagem (por outro canal) a usar a mesma chave numa operação XOR afim de obter o número original. Claro que esta cifragem é muito simples, e consequentemente muito fraca e fácil de quebrar, mas está aqui em caráter de exemplo.
Em textos matemáticos sobre lógica, o circunflexo ^ representa conjunção ao invés de disjunção exclusiva. Já em softwares matemáticos, pode significar potência, por exemplo: 2^32 é dois elevado à trigésima segunda potência.
Deslocamento (SHL e SHR)
O deslocamento para a esquerda (shift left) consiste em deslocar todos os bits de um número para a esquerda e completar a posição criada mais à direita com zero. Tomemos por exemplo o número 7 e uma operação SHL com 1 (deslocar uma vez para a esquerda):
Assim podemos perceber que deslocar à esquerda dá no mesmo que multiplicar por 2. Veja:
No exemplo acima deslocamos 1 bit do número 7 (0b111) para a esquerda três vezes, que resultou em 56. Seria o mesmo que deslocar 3 bits de uma só vez:
De forma análoga, o deslocamento para a direita (shift right), ou simplesmente SHR, consiste em deslocar todos os _bits_de um número para a direita e completar a posição criada à esquerda com zero. Tomando o mesmo 7 (0b111):
O resultado é uma divisão inteira (sem considerar o resto) por 2. Assim, 7/2 = 3 (e sobra 1, que é desconsiderado neste cálculo). Esta é de fato uma maneira rápida de dobrar ou calcular a metade de um número.
Rotação (ROL e ROR)
Assim como no deslocamento, a rotação envolve deslocar os bits de um número para a esquerda (rotate left) ou direita (rotate right) mas o bit mais significativo (mais à esquerda) é posto no final (mais à direita), no lugar de zero. Por isso é necessário considerar o tamanho. Tomemos o número 5 como exemplo:
O bit zero, que está mais à esquerda, "deu a volta" e veio parar ao lado direito do bit 1, mais à direita do número 0b00000101.
Analise com o número 133 agora:
Desta vez o bit 1, que estava mais à esquerda, veio parar ao lado direito do bit mais à direita, e todos os outros bits foram "empurrados" para a esquerda.
Não estamos limitados a fazer operações ROL e ROR somente com 1. O byte 133 ROL 3 por exemplo resulta em 0x2c. Você é capaz de conferir se acertei?
Negação (NOT)
Para negar um bit, basta invertê-lo:
0
1
1
0
No entanto, para inverter o número maior, como por exemplo 0b100, é preciso saber seu tamanho. Analise os exemplos abaixo para tamanhos variados:
1 byte
0b00000100
0b11111011
2 bytes (WORD)
0b0000000000000100
0b1111111111111011
4 bytes (DWORD)
0b00000000000000000000000000000100
0b11111111111111111111111111111011
Fazer essa inversão é o mesmo que calcular o complemento (também chamado de "complemento de um") de um número. Para obter seu simétrico, é preciso ainda somar uma unidade, como vimos anteriormente. Por isso, um NOT bit-a-bit no número 4, por exemplo, resulta em -5. Veja:
Os processadores Intel x86 trabalham com muitas outras operações bitwise, mas detalhá-las foge do escopo deste livro. Conforme você avançar no estudo de engenharia reversa, vai se deparar com elas.
Last updated
Was this helpful?