Atualmente estou estudando criptografia e estava pensando em maneiras de reverter os nibbles de um byte (ex. 0xF5
=> 0x5F
). Eu pensei nessa solução:
byte >> 4 | (byte & 0x0F) << 4
Outras soluções que encontrei on-line eram semelhantes, mas adicionavam um operando extra mascarando o nibble esquerdo de um byte:
(byte & 0xF0) >> 4 | (byte & 0x0F) << 4
Em binário, a segunda solução se parece com isto:
# Extract the right nibble of a byte and shift to the left
[0xF5] 1111 0101 # Original Value
[0x0F] 0000 1111 & # Mask Right Nibble
[0x05] 0000 0101 = # Extracted Right Nibble
[0x50] 1010 0000 << 4 # Shift Four Bits to the Left
# Extract the left nibble of a byte and shift to the right
[0xF5] 1111 0101 # Original Value
[0xF0] 1111 0000 & # Mask Left Nibble
[0xF0] 1111 0000 = # Extracted Left Nibble
[0x0F] 0000 1111 >> 4 # Shift Four Bits to the Right
# Combine the shifted nibbles together
[0x05] 0000 1111 # Left Nibble Shifted to the Right
[0xF0] 0101 0000 | # Right Nibble Shifted to the Left
[0xF5] 0101 1111 = # New Value
Corrija-me se eu estiver errado, mas a segunda solução é útil se você estiver lidando com um tipo de dado que é maior que um byte e está focado somente no byte menos significativo. Então, se você fosse deslocar sem mascarar, os bits dos bytes de ordem mais alta se propagariam para o nibble esquerdo. Assim, mascarar o nibble esquerdo é necessário em relação a esse cenário.
# Bits shift into the least significant byte without masking
[0x0AF5] 0000 1010 1111 0101
[0x00AF] 0000 0000 1010 1111 >> 4
Por outro lado, se você estiver realmente trabalhando com um byte, mascarar o nibble esquerdo não é redundante, já que os bits do nibble esquerdo serão zerados após deslocar quatro bits para a direita?
[0xF5] 1111 0101
[0x0F] 0000 1111 >> 4
Talvez existam outras razões para mascarar os bits de nibble esquerdos que eu desconheço. Por exemplo, outros sistemas podem se comportar de forma diferente onde a segunda solução é necessária.
Estou com a cabeça no lugar certo ou há algo que devo considerar?
Aqui está um código de exemplo para maior esclarecimento:
typedef uint8_t byte;
static inline
byte swap_nibbles(byte bits) {
return bits >> 4 | (bits & 0x0F) << 4;
}