Introdução à linguagem Assembly de programação

Introdução à linguagem Assembly de programação

O Assembly foi uma das primeiras linguagens de programação com a qual eu tive contato na vida, ainda no curso técnico, por volta de 1994-1995 (a outra foi a linguagem Pascal, sobre a qual falarei em outro artigo).

Você talvez já tenha ouvido falar nessa linguagem, mas é possível que nunca tenha tido contato com código-fonte escrito nela, e pode estar se perguntando “para que serve o Assembly?“, ou ainda “a linguagem Assembly ainda é usada?“.

Neste post respondo a essas e outras perguntas, e mostro também código escrito nessa linguagem antiga (porém ainda útil), que você pode experimentar em seu computador usando ferramentas simples e gratuitas.

O que é a linguagem Assembly?

A linguagem Assembly, comumente abreviada por ASM, é uma linguagem de programação de baixo nível que permite aos programadores escreverem código  em instruções de baixo nível, próximas à linguagem de máquina, em vez de usar uma linguagem de alto nível mais abstrata, como C, Python ou Rust, por exemplo.

Trata-se de uma linguagem simbólica que representa as instruções em uma forma mnemônica (códigos de operação), que é mais fácil de entender para os programadores do que a representação binária das instruções. Por exemplo, em uma instrução Assembly, “ADD” pode representar a adição de dois números quaisquer.

Cada instrução Assembly representa uma operação específica que a CPU (Unidade Central de Processamento – Processador) deve executar, como por exemplo mover dados da memória principal para um registrador, realizar operações aritméticas ou executar desvios condicionais ou incondicionais.

A linguagem Assembly é específica para cada tipo de processador e arquitetura de computador, pois as instruções Assembly são diretamente executadas pelo hardware da máquina.

Embora a linguagem Assembly seja mais difícil de aprender e escrever do que as linguagens de programação de alto nível, ela permite um controle muito mais preciso e direto sobre o hardware do sistema, tornando-a ideal para desenvolvedores que precisam escrever software para sistemas embarcados, sistemas operacionais, drivers de dispositivos e outras aplicações que exigem acesso direto ao hardware da máquina, alta velocidade de execução e confiabilidade.

Porém, devido à sua complexidade e à necessidade de escrever códigos em instruções de máquina específicas, a linguagem Assembly não é tão comum quanto as linguagens de programação de alto nível, como C++, Java ou Python.

Quais as aplicações do Assembly hoje em dia?

Embora a linguagem Assembly seja considerada uma linguagem de programação de baixo nível e mais difícil de aprender do que as linguagens de programação de alto nível, ela ainda é amplamente usada em áreas especializadas da programação que exigem alto desempenho e controle preciso sobre o hardware. Algumas das aplicações atuais do Assembly incluem:

  • Desenvolvimento de sistemas operacionais: os sistemas operacionais são um exemplo clássico de aplicação de Assembly, pois exigem um controle preciso sobre o hardware da máquina e um alto desempenho para executar operações em tempo real.
  • Programação de dispositivos embarcados: muitos dispositivos embarcados, como microcontroladores, câmeras digitais, telefones celulares e dispositivos IoT, são programados em Assembly, pois exigem um controle muito preciso sobre o hardware e uma alta eficiência em termos de recursos.
  • Criação de drivers de dispositivos: os drivers de dispositivos são programas que permitem que o sistema operacional se comunique com os dispositivos de hardware, como placas de som, placas de vídeo e dispositivos de rede. Esses drivers são frequentemente escritos em Assembly, pois exigem um controle muito preciso sobre o hardware e um alto desempenho.
  • Processamento de imagens: as operações de processamento de imagens, como convolução, filtragem e detecção de bordas, são frequentemente executadas em Assembly para obter um desempenho máximo.
  • Programação de jogos eletrônicos: muitos jogos eletrônicos ainda são programados em Assembly para obter o máximo desempenho possível, especialmente em consoles de jogos com recursos limitados.
  • Criptografia: muitos algoritmos de criptografia são implementados em Assembly para garantir a segurança dos dados e garantir o desempenho máximo.

Ou seja, a linguagem Assembly é usada em áreas onde é necessário um controle muito preciso sobre o hardware da máquina e um alto desempenho, mesmo que isso signifique uma curva de aprendizado mais íngreme e um processo de desenvolvimento mais complexo.

Quando a linguagem Assembly foi criada?

A linguagem Assembly é uma das linguagens de programação mais antigas que ainda são usadas hoje. Ela foi criada em meados da década de 1940, juntamente com os primeiros computadores eletrônicos, como o EDSAC (Electronic Delay Storage Automatic Calculator) e o ARC (Automatic Relay Computer). Naquela época, a programação era feita diretamente em linguagem de máquina, o que era muito trabalhoso e propenso a erros.

Computador EDSAC em 1948.

Computador EDSAC em 1948.
Imagem: Wikimedia Commons. Licença CC BY 2.0

A linguagem Assembly foi desenvolvida para tornar a programação mais fácil e menos sujeita a erros, permitindo que os programadores escrevessem instruções em uma linguagem mais próxima da linguagem de máquina, mas com uma sintaxe mais fácil de entender pelos humanos.

O primeiro código no qual uma linguagem Assembly foi usada para representar instruções de código de máquina data do ano de 1947, sendo encontrado em um trabalho de nome Coding for A.R.C (Codificação para o computador Automatic Relay Computer), de Kathleen H. V. Britten e Andrew Donald Booth.

Desde então, a linguagem Assembly tem sido amplamente usada em áreas que exigem controle de baixo nível sobre o hardware, como sistemas operacionais, programação de dispositivos embarcados e processamento de imagens e os outros exemplos citados anteriormente.

Quais versões do Assembly existem?

A linguagem Assembly não tem versões específicas, como outras linguagens de programação. Em vez disso, existem vários conjuntos de instruções Assembly, cada um projetado para um processador ou arquitetura de computador específico. Isso ocorre porque as instruções Assembly são escritas em um nível muito baixo, que é quase diretamente traduzido em instruções de máquina.

Dessa forma, a linguagem Assembly é altamente dependente do hardware subjacente onde as aplicações serão executadas.

Cada arquitetura de computador tem seu próprio conjunto de instruções Assembly que são otimizadas para funcionar com o hardware específico. Por exemplo, a arquitetura x86 é usada por muitos processadores Intel e AMD, enquanto a arquitetura ARM é usada em dispositivos móveis, smartphones e outros sistemas embarcados.

Ou seja, cada uma dessas arquiteturas tem seu próprio conjunto de instruções Assembly distinto.

Sendo assim, não existem diferentes versões da linguagem Assembly, mas sim diferentes conjuntos de instruções que são específicos para diferentes arquiteturas de computador.

Como começar a programar em Assembly?

Começar a programar em Assembly pode parecer bastante complicado a princípio (e é), especialmente se não estivermos acostumados com linguagens de programação de alto nível, mas é possível aprender com bastante prática e paciência. Abaixo listo algumas dicas para quem deseja começar a aprender essa linguagem:

  • Escolha um conjunto de instruções: como mencionado anteriormente, cada arquitetura de processador tem seu próprio conjunto de instruções Assembly. Portanto, o primeiro passo é escolher o conjunto de instruções que você deseja aprender, com base no processador que você está usando (por exemplo, plataforma Intel x86_64).
  • Entenda a estrutura básica do programa Assembly: um programa Assembly é composto por uma série de instruções que são executadas sequencialmente. É importante entender como as instruções são organizadas em um programa Assembly.
  • Aprenda as instruções básicas: Obviamente, devemos começar com as instruções básicas, como movimento de dados, aritmética básica, operações lógicas, desvios condicionais e loops. Essas instruções são as bases do Assembly e são usadas em todos os programas Assembly.
  • Use um ambiente de desenvolvimento integrado (IDE): um ambiente de desenvolvimento integrado é um software que facilita a escrita e execução de código Assembly. Existem vários IDEs disponíveis, como o MASM da Microsoft, o NASM para sistemas Unix e o GCC para várias plataformas.
  • Pratique, pratique e pratique: a melhor maneira de aprender Assembly (ou qualquer outra linguagem de programação) é praticar escrevendo muito código. Comece com programas simples e, gradualmente, escreva programas mais complexos à medida que se torna mais confortável com a linguagem.
  • Recursos de aprendizagem: existem muitos recursos de aprendizagem disponíveis online, como tutoriais, livros e fóruns. Alguns recursos que posso recomendar incluem “Assembly Language Step-by-Step” de Jeff Duntemann e o site “Assembly Language Tutorials” de Ray Seyfarth – além, é claro, dos tutoriais do blog da Bóson Treinamentos em tecnologia!

Lembre-se: programação em Assembly é uma habilidade que leva tempo para ser aprendida. Porém, com bastante prática e paciência, é possível se tornar proficiente nesta linguagem.

Assembly ou Assembler?

Frequentemente ouvimos os termos “assembly” e “assembler” em referência a esta linguagem. Mas do que se tratam essas palavras? Significam a mesma coisa?

Não. Na verdade, “Assembly” e “Assembler” são termos relacionados à programação de baixo nível, mas referem-se a conceitos diferentes, como explico a seguir:

1. Assembly é o nome da linguagem de programação de baixo nível que é mais próxima da linguagem de máquina do que a linguagem de programação de alto nível. É uma representação simbólica da linguagem de máquina de um processador específico.

2. Já um Assembler é um tipo de programa de computador que traduz programas escritos em linguagem Assembly para código de máquina executável, de forma análoga a um compilador.
O Assembler lê o código fonte em Assembly e produz código de máquina correspondente, geralmente em formato binário ou hexadecimal.
Além de converter mnemônicos e diretivas em instruções de máquina, o Assembler também resolve rótulos (como identificadores de variáveis e funções) em endereços de memória específicos.

Ou seja, Assembly é a linguagem de programação e Assembler é a ferramenta de software que traduz programas escritos nessa linguagem em instruções de máquina executáveis pelo processador.

Exemplo de código em Assembly

Vejamos um exemplo de código “simples” em Assembly x86 que realiza a soma de dois números e armazena o resultado em uma variável:

section .data
num1 dd 10
num2 dd 20
res dd 0

section .text
global _start

_start:
; move os valores de num1 e num2 para os registradores eax e ebx, respectivamente
mov eax, [num1]
mov ebx, [num2]

; adiciona os valores de eax e ebx e armazena o resultado em eax
add eax, ebx

; move o valor de eax para a variável res
mov [res], eax

; sai do programa
mov eax, 1
xor ebx, ebx
int 0x80

Explicação

Esse código começa definindo três variáveis: num1, num2 e res. Estas são declaradas como palavras duplas, o que significa que cada uma é um inteiro de 32 bits (4 bytes). A variável res é inicializada como zero.

Na seção .text, a função principal começa com o rótulo _start. O primeiro passo é mover os valores das variáveis num1 e num2 para os registradores eax e ebx, respectivamente. Isso é feito usando a instrução mov, que copia os dados de uma posição de memória para um registrador.

O próximo passo é adicionar os valores de eax e ebx usando a instrução add. O resultado da adição é armazenado em eax.

Por fim, o valor de eax é movido para a variável res usando a instrução mov. O programa sai do loop principal e termina usando as instruções mov, xor e int.

Como testar o programa sugerido

Podemos usar um compilador de Assembly para montar e executar o código fornecido anteriormente. Vejamos como fazer isso usando o compilador NASM* em um sistema Linux:

1. Crie um arquivo de texto chamado “soma.asm” usando um editor de sua preferência (vim, nano, emacs, etc.), e cole o código Assembly mostrado anteriormente.

2. Instale o NASM no seu sistema, se ainda não estiver instalado. No Linux Debian ou Ubuntu, podemos instalar o NASM digitando os seguintes comandos no terminal:

$ sudo apt update
$ sudo apt install gcc-multilib
$ sudo apt install nasm

3. Compile o código Assembly usando o NASM. Para isso execute o seguinte comando no terminal (estadnbo no diretório onde o arquivo foi criado):

$ nasm -f elf32 soma.asm

Este comando produz um arquivo objeto chamado “soma.o“.

4. Precisamos ligar o arquivo objeto gerado pelo NASM com a biblioteca padrão do C usando o compilador GCC. Para isso, digite o seguinte comando no terminal:

$ gcc -nostdlib soma.o -m32 -o soma

Este comando produz um arquivo executável chamado “soma“.

5. Vamos executar o programa para testá-lo digitando o seguinte comando no terminal:

$ ./soma

O resultado será armazenado na variável “result” e exibido no terminal. No caso do exemplo, o resultado será 30 (que é a soma de 10 e 20).

O NASM (Netwide Assembler) é um compilador de Assembly de código aberto que suporta várias arquiteturas de processadores, incluindo x86 e x86-64. Ele é usado para escrever programas em linguagem Assembly que podem ser executados em sistemas operacionais variados como Windows, Linux, macOS e até mesmo DOS.

O NASM é uma ferramenta popular para desenvolvedores de software que precisam escrever código de baixo nível para fins de otimização ou para trabalhar com recursos de hardware específicos. Ele é amplamente utilizado em áreas como jogos, programação de sistemas e desenvolvimento de drivers de dispositivos.

Essa ferramenta fornece muitos recursos avançados para programação Assembly, como por exemplo suporte para macros, diretivas e expressões de pré-processador. Ele também inclui um depurador integrado que ajuda os programadores a depurar o código e entender o fluxo de execução do programa.

Conclusão

O Assembly é uma linguagem antiga de baixo nível e, portanto, altamente específica e dependente da arquitetura do processador (CPU). Código em Assembly é muito mais difícil de ler e escrever do que código criado em linguagens de programação de alto nível, como Python, C# ou Java.

No entanto, a linguagem Assembly oferece controle absoluto sobre o hardware e pode ser usada em situações onde a eficiência é crítica, como na programação de drivers de dispositivo, sistemas embarcados ou no desenvolvimento de sistemas operacionais.

Quer saber mais sobre Assembly? confira nosso tutorial “Olá Mundo em Assembly no Ubuntu Linux, com Yasm Assembler“.

 

Sobre Fábio dos Reis (1195 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 30 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Ciência e Tecnologia em geral, adora Viagens e Música, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.

Escreva um comentário

Seu e-mail não será divulgado


*