Resumo
Este
trabalho apresenta o desenvolvimento e a implementação de uma calculadora com
interface gráfica nativa para sistemas operacionais Windows, desenvolvida
inteiramente em linguagem Assembly para arquitetura x86-64. Diferente de
abordagens convencionais que utilizam bibliotecas de alto nível e ambientes de
tempo de execução (Runtime C/C++), este programa interage diretamente com a
interface de programação de aplicativos do Windows (Windows API), demonstrando
em detalhe a estrutura de janelas, o fluxo de mensagens, a criação de controles
e a manipulação de dados em nível de arquitetura. O resultado é um executável
de tamanho reduzido, sem dependências externas e que ilustra os princípios
fundamentais de funcionamento de aplicações gráficas na plataforma Windows.
Palavras-chave:
Assembly x86-64; Windows API; Interface Gráfica; Processamento de Mensagens;
Programação de Baixo Nível.
Introdução
A
programação de aplicações gráficas é comumente realizada por meio de linguagens
de alto nível e frameworks que abstraem a complexidade do sistema operacional.
Embora essa prática seja eficiente para o desenvolvimento de software
produtivo, ela oculta os mecanismos fundamentais que regem a criação de
janelas, a comunicação com o sistema operacional e a organização da memória e
da pilha de execução.
A
linguagem Assembly permite ao programador compreender e controlar diretamente
os recursos do processador e do sistema operacional. Em especial, a arquitetura
x86-64 apresenta um conjunto de registradores e uma convenção de chamada bem
definida para a plataforma Windows, que possibilita a construção de aplicações
gráficas funcionais por meio de chamadas diretas às funções do sistema.
Este
trabalho tem como objetivo apresentar o projeto e a implementação de uma
calculadora gráfica desenvolvida puramente em Assembly x64, utilizando
exclusivamente funções da Windows API. Discutem-se a estrutura da aplicação, a
convenção de chamada utilizada, o tratamento de mensagens e a lógica de
funcionamento, bem como as dificuldades encontradas e as soluções adotadas
durante o desenvolvimento.
Fundamentos
Teóricos
A
Plataforma Windows e a Interface Gráfica
As
aplicações com interface gráfica no Windows seguem um modelo orientado a
eventos. O sistema operacional notifica a aplicação sobre ações do usuário
(cliques, digitação, movimentação da janela) por meio de mensagens que são
enfileiradas e processadas pela própria aplicação.
Para
que uma janela exista, é necessário:
1. Registrar
uma classe de janela informando características e procedimento de tratamento de
mensagens;
2. Instanciar
a janela principal;
3. Executar
um laço de leitura e despacho de mensagens.
Convenção
de Chamada na Arquitetura x64 Windows
A
plataforma Windows para processadores de 64 bits adota uma convenção de chamada
padronizada:
- Os quatro primeiros parâmetros são
passados pelos registradores: RCX, RDX, R8 e R9;
- Parâmetros subsequentes são enviados por
meio da pilha, com deslocamentos consecutivos;
- Antes de cada chamada de função, a pilha
deve ser alinhada em endereços múltiplos de 32 bytes;
- A função chamada preserva os registradores
RBX, RBP, RSI, RDI, R12–R15, devolvendo-os inalterados ao chamador.
Funções
Essenciais da Windows API Utilizadas
|
Função |
Propósito |
|
GetModuleHandleA |
Obtém
o endereço da instância do programa |
|
RegisterClassExA |
Registra
as características da classe de janela |
|
CreateWindowExA |
Cria
a janela principal e controles (botões, campos de texto) |
|
ShowWindow
/ UpdateWindow |
Exibe
e redesenha a janela |
|
GetMessageA |
Lê
mensagens da fila de eventos do sistema |
|
TranslateMessage |
Converte
mensagens de teclado |
|
DispatchMessageA |
Envia
mensagens ao procedimento da janela |
|
SetWindowTextA |
Atualiza
o texto exibido no visor |
|
PostQuitMessage |
Encerra
o laço de mensagens |
|
DefWindowProcA |
Processa
mensagens não tratadas pela aplicação |
Metodologia
e Desenvolvimento
Estrutura
Geral do Programa
A
aplicação foi organizada em quatro etapas principais:
- Inicialização: obtenção da instância do
programa e registro da classe de janela;
- Criação da Janela Principal e Controles:
instanciação da janela, do visor e dos botões numéricos e de operação;
- Laço de Mensagens: leitura, tradução e
despacho contínuo de eventos do sistema;
- Procedimento de Janela: tratamento de
criação, comandos e encerramento.
Tratamento
de Mensagens
O
procedimento WindowProc é o núcleo lógico da aplicação. Ele recebe mensagens
enviadas pelo sistema e responde conforme o tipo:
- WM_CREATE: acionada no momento da criação
da janela. Nesta etapa, instancia-se o campo de exibição (visor alinhado à
direita, somente leitura) e cada um dos 16 botões organizados em quatro
linhas: dígitos de 0 a 9, ponto decimal, operadores (+ − × /), botão de limpeza
(C) e botão de igualdade (=). Cada botão é criado por chamada direta à
função CreateWindowExA, com posicionamento e dimensões definidos em
coordenadas de tela.
- WM_COMMAND: acionada quando o usuário
clica em um botão. O identificador do controle é extraído e comparado para
executar a ação correspondente:
- Dígitos: concatenam o caractere ao número
exibido;
- Ponto decimal: insere separador, evitando
repetição;
- Operadores: convertem o valor exibido em
inteiro e armazenam o valor e o tipo de operação;
- Botão de igualdade: realiza a operação
aritmética, trata divisão por zero e converte o resultado de volta para
texto;
- Botão C: reinicia todos os valores e
exibe o número zero.
- WM_DESTROY: encerra a aplicação
corretamente ao fechar a janela.
Mensagens
não tratadas são encaminhadas à função padrão DefWindowProcA.
Conversão
de Dados
Como a
API do Windows trabalha com texto e os cálculos exigem valores numéricos, foram
implementadas duas rotinas auxiliares:
- StringParaInteiro: percorre caractere por
caractere, convertendo o texto em valor inteiro com sinal;
- InteiroParaString: converte o resultado
numérico de volta para sequência de caracteres, tratando sinal negativo e
valor zero.
Compilação
e Linkagem
O
código foi montado com o NASM no formato binário de 64 bits e posteriormente
vinculado ao executável por meio do GCC (MinGW-w64), que realiza a ligação com
as bibliotecas do sistema user32.dll (interface gráfica) e kernel32.dll
(funções básicas).
bash
nasm
-f win64 calc.asm -o calc.o
gcc
calc.o -o calc.exe -mwindows -luser32 -lkernel32
Resultados
e Discussão
Tamanho
e Independência de Runtime
O
executável gerado possui aproximadamente 15 KB e não exige bibliotecas
adicionais ou ambientes de tempo de execução instalados no sistema. Essa
característica contrasta com aplicações compiladas em linguagens de alto nível,
que frequentemente dependem de bibliotecas externas e apresentam tamanho
significativamente maior.
Desafios
e Correções
Durante
o desenvolvimento, foram identificados problemas diretamente relacionados à
programação em nível de arquitetura:
- Alinhamento da Pilha: chamadas a funções
da Windows API exigem que a pilha esteja alinhada em 32 bytes antes de
cada instrução call. O não cumprimento dessa regra causava falhas
silenciosas e fechamento inesperado da janela;
- Convenção de Chamada: o uso incorreto de
registradores e deslocamentos na pilha resultava em parâmetros inválidos
enviados às funções, impedindo a criação de controles;
- Sintaxe e Tamanho de Operandos:
especificadores de tamanho redundantes em instruções de movimentação
causavam erros de montagem, exigindo estrita observância às regras do
montador NASM.
Funcionamento
Final
A
versão corrigida apresenta janela visível imediatamente ao ser executada, com
visor funcional e todos os botões reagindo corretamente aos cliques. As quatro
operações aritméticas funcionam conforme esperado, com tratamento de erro para
divisão por zero e reinicialização completa ao acionar o botão de limpeza.
Conclusão
Este
trabalho demonstrou a viabilidade e a complexidade da construção de uma
aplicação gráfica funcional utilizando exclusivamente linguagem Assembly e
chamadas diretas ao sistema operacional. Foi possível compreender em detalhe a
estrutura de janelas, o fluxo de mensagens, a convenção de chamada da
arquitetura x64 Windows e a forma como o sistema operacional interage com as
aplicações.
Embora
essa abordagem demande conhecimento aprofundado da arquitetura do processador e
das funções do sistema, ela oferece total controle sobre o comportamento do
programa, resultando em executáveis extremamente leves e sem dependências
externas. Os desafios encontrados — especialmente quanto ao alinhamento da
pilha e à passagem de parâmetros — evidenciam a importância de dominar os
fundamentos da arquitetura de computadores para o desenvolvimento de software
robusto.
Como
trabalhos futuros, sugere-se a ampliação da precisão numérica com suporte a
ponto flutuante, a implementação de funções matemáticas adicionais, o suporte a
entrada por teclado e o aprimoramento da apresentação visual por meio de
recursos gráficos avançados da API.
Referências
- RUSSINOVICH, M. E.; SOLOMON, D. A. Windows
Internals: Parte 1. 7. ed. Microsoft Press, 2021.
- FOG, A. Optimizing Subroutines in
Assembly Language. Disponível em: https://www.agner.org/optimize/, 2024.
- MICROSOFT. Windows API Documentation.
Disponível em: https://learn.microsoft.com/windows/win32/api/,
2026.
- NASM Development Team. NASM — The
Netwide Assembler Documentation. Disponível em: https://nasm.us/, 2026.
MINGW-W64 Project. MinGW-w64: GCC for Windows. Disponível em: https://www.mingw-w64.org/, 2026
Repositório: https://github.com/fydelis2025/Calculadora_ASM

Comentários
Enviar um comentário