Deslocamento e Rotação de Bits em Assembly NASM: Instruções SHL, SHR, SAR, ROL e ROR
As instruções de deslocamento e rotação permitem manipular diretamente os bits de um número armazenado em registradores ou posições de memória. Essas operações são fundamentais na programação Assembly, pois controlam a forma como os dados binários são processados pelo processador. Elas são amplamente utilizadas em otimizações aritméticas, compressão, criptografia e controle de flags.
Deslocamento para a Esquerda (SHL)
A instrução shl desloca todos os bits de um operando para a esquerda.
Sua sintaxe é:
shl dest, count
O primeiro operando (dest) representa o valor a ser deslocado — normalmente um registrador ou endereço de memória.
O segundo operando (count) indica o número de posições pelas quais os bits serão movidos.
Exemplo no Linux
global _start
section .text
_start:
mov rdi, 5 ; RDI = 5 (00000101)
shl rdi, 1 ; desloca 1 bit à esquerda → 00001010 (10)
mov rax, 60
syscallNesse exemplo, o número 5 (00000101) é deslocado um bit à esquerda, resultando em 00001010, que equivale a 10 em decimal. O bit mais à esquerda é descartado e um novo bit 0 é adicionado à direita. Em termos aritméticos, deslocar à esquerda uma vez equivale a multiplicar o valor por 2.
Exemplo no Windows
global _start
section .text
_start:
mov rax, 5 ; RAX = 5 (00000101)
shl rax, 1 ; desloca 1 bit à esquerda → 00001010 (10)
retDe forma geral, deslocar um número n vezes à esquerda equivale a multiplicá-lo por 2ⁿ.
Durante o deslocamento, o último bit descartado é copiado para o flag de transporte (CF).
Esse flag pode ser verificado com instruções condicionais como jc (jump if carry), permitindo que o programa reaja conforme o valor descartado.
Exemplo com verificação do flag CF
global _start
section .text
_start:
mov al, 69 ; AL = 69 (01000101)
shl al, 2 ; desloca 2 bits à esquerda → 00010100 (20)
jc carry_set ; salta se o bit descartado for 1
mov rdi, 2
jmp exit
carry_set:
mov rdi, 4
exit:
mov rax, 60
syscallOutros flags afetados:
- ZF (Zero Flag) → definido se o resultado for 0
- SF (Sign Flag) → definido se o bit mais significativo do resultado for 1
- OF (Overflow Flag) → definido se o bit de sinal mudar ao deslocar 1 bit
Deslocamento Lógico para a Direita (SHR)
A instrução shr desloca os bits para a direita, preenchendo com zeros à esquerda:
shr dest, count
O deslocamento lógico à direita é o inverso do deslocamento à esquerda e é frequentemente utilizado para dividir valores inteiros sem sinal.
Exemplo
global _start
section .text
_start:
mov rdi, 69 ; RDI = 69 (01000101)
shr rdi, 2 ; desloca 2 bits à direita → 00010001 (17)
mov rax, 60
syscallAo deslocar 69 (01000101) dois bits à direita, obtemos 00010001, ou 17 em decimal.
O deslocamento à direita de n bits equivale a dividir o valor por 2ⁿ, descartando o resto.
Flags afetados:
- CF → recebe o último bit descartado
- ZF → definido se o resultado for 0
- OF → definido se o bit mais significativo mudar ao deslocar 1 bit
- SF → sempre limpo (0), pois entra 0 pela esquerda
Deslocamento Aritmético para a Direita (SAR)
A instrução sar realiza o deslocamento à direita preservando o sinal do número.
O bit mais significativo, que indica se o número é positivo ou negativo, é replicado à esquerda, garantindo consistência no valor.
sar dest, count
Exemplo comparativo
global _start
section .text
_start:
mov rdi, -32 ; RDI = -32 (FFFFFFE0h)
shr rdi, 4 ; deslocamento lógico → 0FFFFFFE (268435454)
mov rax, 60
syscallNesse exemplo, o deslocamento lógico transforma um número negativo em um valor positivo incorreto para o contexto aritmético.
Com sar, o sinal é mantido:
global _start
section .text
_start:
mov rdi, -32 ; RDI = -32 (FFFFFFE0h)
sar rdi, 4 ; deslocamento aritmético → FFFFFFFE (-2)
mov rax, 60
syscallO sar é utilizado principalmente com números com sinal, enquanto o shr é preferido para valores sem sinal.
Flags afetados:
- CF → último bit descartado
- ZF → definido se o resultado for 0
- OF → sempre limpo (0)
- SF → mantém o bit de sinal original
Rotação (ROL e ROR)
As instruções rol (rotação à esquerda) e ror (rotação à direita) deslocam os bits de forma circular,
ou seja, o bit que sai de um lado retorna pelo outro.
rol dest, count ror dest, count
Essas instruções não afetam os flags de sinal ou zero. O último bit deslocado é copiado para o CF, e o OF pode mudar em rotações de 1 bit, dependendo do XOR entre os bits mais altos.
Exemplo de rotação à esquerda
global _start
section .text
_start:
mov rax, 131 ; AL = 131 (10000011)
rol al, 2 ; rotação de 2 bits → 00001110 (14)
mov rdi, rax
mov rax, 60
syscallResultado:
10000011 << 2 = 00001110 → 14
Exemplo de rotação à direita
global _start
section .text
_start:
mov rax, 131 ; AL = 131 (10000011)
ror al, 2 ; rotação de 2 bits → 11100000 (224)
mov rdi, rax
mov rax, 60
syscallResultado:
10000011 >> 2 = 11100000 → 224
Rotação com o Flag de Transporte (RCL e RCR)
As instruções rcl e rcr funcionam como as rotações normais,
mas incluem o CF (Carry Flag) no ciclo de rotação.
rcl dest, count rcr dest, count
rcl(rotação à esquerda com transporte): o bit mais significativo vai para CF, e o valor de CF entra no bit menos significativo.rcr(rotação à direita com transporte): o bit menos significativo vai para CF, e o valor de CF entra no bit mais significativo.

Exemplo de rotação à esquerda com transporte
global _start
section .text
_start:
mov rax, 131 ; AL = 131 (10000011)
rcl al, 2 ; rotação com transporte → 00001101 (13)
mov rdi, rax
mov rax, 60
syscallDurante a execução:
- Antes:
CF = 0,AL = 10000011Após 1ª rotação:CF = 1,AL = 00000110 - Antes:
CF = 1,AL = 00000110Após 2ª rotação:CF = 0,AL = 00001101
Resumo
- SHL → deslocamento lógico à esquerda (multiplica por
2ⁿ) - SHR → deslocamento lógico à direita (divide por
2ⁿ) - SAR → deslocamento aritmético à direita (mantém o sinal)
- ROL / ROR → rotação circular dos bits
- RCL / RCR → rotação incluindo o flag de transporte
- Flags afetados: CF, ZF, SF, OF