Dev (Back & Front)ARTIGO

Go: brincando com bits

Neste artigo, o autor ensina a manipular bits usando Golang.

Como manipular bits usando Golang

Estou brincando com um projeto de um interpretador BASIC escrito em Go, e a saída de video em modo texto, segue o padrão de cores do CGA, ou seja, um byte contém nos quatro bits mais altos o código para a cor do fundo e nos quatro bits mais baixos o código para a cor da fonte. Ou seja, 16 cores para as letras e 16 cores para o fundo. Se o flag de blink estiver ativo, o bit mais alto indicará que o sistema deve “piscar” a letra. Com isso, acontece uma coisa interessante, só as cores de fundo com esse bit ligado podem piscar. Por exemplo, o azul cor 0x09, que em binário é 1001, pisca, mas o vermelho 0x4 não pisca porque em binário é 0100.

Essa brincadeira parece complicada, mas na verdade é muito simples, precisamos apenas aprender algumas poucas operações para poder manipular bits.

Antes de começarmos, vamos combinar o seguinte: quando eu falar sobre a parte superior ou alta de um conjunto de bits, estou me referindo aos bits mais à esquerda, e quando estiver falando da parte inferior ou parte baixa, estou falando dos bits mais à direita. Nem sempre é assim, porém, para efeito desse texto, é assim que funciona. É o que chamamos de little-endian.

Shift (<< e >>, desloca bits)

Shift é o operador para mover bits para direita << ou esquerda >>

Exemplo:

00000001 << 1 resulta em: 00000010
00000001 << 2 resulta em: 00000100
00000001 << 3 resulta em: 00001000

10000000 << 1 resulta em: 01000000
10000000 << 2 resulta em: 00100000
10000000 << 3 resulta em: 00010000

AND (&)

Usamos AND para definir uma máscara e usamos essa mascara para extrair a parte que queremos de um conjunto de bits.

Exemplo:

Digamos que queremos extrair apenas os quatro bits centrais de um byte, para isso definimos a seguinte mascara: 00111100. Note que os bits que queremos extrair estão com 1 e os que não queremos estão com 0. Daí, basta comparar o byte que contém o valor a ser extraído com a máscara, usando AND (&).

valor	 & mascara
10101010 & 00111100 resulta em: 00101000

O que AND faz é comparar cada um dos bits com o seu correspondente na máscara e apenas onde os dois bits forem 1, vai ser 1 no resultado. Com isso, os outros bits fora da máscara foram zerados.

E agora podemos usar shift para a direita , andar duas casas e obter o valor que queremos extrair em um byte.

00101000 >> 2 resulta em: 00001010

Ou seja, usamos AND junto com uma máscara de bits para separar as partes que queremos de um conjunto de bits.

OR (|)

OR nesse caso é o inverso, usaremos para combinar dois conjuntos de bits em um.

Exemplo:

Digamos que queremos juntar esses quatro bits 1010 na parte superior de um byte, seguido desses 4 bits 0101 na parte inferior.

Primeiro movemos os 4 bits para a parte superior do byte:

00001010 << 4 resulta em: 10100000

Daí, usamos OR para juntar a parte superior e a inferior:

10100000 | 00000101 resulta em: 10100101

Vamos ver um exemplo em Go:

package main

import "fmt"

func main() {

	/*
		Pega os códigos da cor da fonte e do fundo
		e combina os dois em um único byte
	*/

	var b, f byte

	b = 0x9 // cor do fundo (azul claro)
	f = 0x4 // cor da fonte (vermelho)

	// combina os dois códigos para compor o código da cor
	c := (f & 0x0f) | (b << 4)

	/*
		Pega o código da cor e separa a cor da fonte
		e do fundo para poder usar separadamente
	*/

	h := (c & 0xf0) >> 4 // High Nibble
	l := c & 0x0f        // Low Nibble
	blink := (c & 0x80) >> 7

	/*
		Mostra os resultados
	*/

	fmt.Printf("cor do fundo.: %04b\n", h)
	fmt.Printf("cor da letra.:     %04b\n", l)
	fmt.Printf("codigo da cor: %08b\n", c)
	fmt.Printf("blink........: %b", blink)
}

Teste no The Go Playground

Trabalha com tecnologia desde a década de 90. Já atuou na área de educação e participou de projetos de mobilidade de grande volume para laboratórios farmacêuticos. Criou games tanto para PC, como para iOS. Hoje está direcionando seus esforços em plataformas de Sistemas Embarcados, IoT, microservices e cloud computing. É um entusiasta de tecnologias como Golang e Docker.

Ver perfil