Informática Numaboa - Tutoriais e Programação
Tutorial GoAsm
Dom 5 Abr 2009 14:34 |
- Detalhes
- Categoria: Assembly Numaboa (antigo oiciliS)
- Atualização: Domingo, 05 Abril 2009 15:41
- Autor: vovó Vicki
- Acessos: 7087
Este texto, baseado no original de Jeremy Gordon, autor dos programas GoAsm, GoRC, GoLink e GoBug, parte do princípio que você seja realmente um iniciante em programação e não sabe bulhufas sobre registradores e blocos de elementos funcionais. No começo é assim mesmo e não tem a mínima importância. Vamos lá!
O que é um programa
Um programa contém instruções para o processador do computador. As instruções são chamadas de código do programa. O processador executa as instruções do código, uma por uma – e é por isso mesmo que o programa é chamado de executável. Quando um programa é carregado, o Windows dá ao processador o endereço inicial presente no código, onde a execução deve começar. A partir deste ponto fica a cargo do programa desviar a execução para os pontos apropriados do seu código. Falaremos deste assunto importante mais tarde.
O que faz um programa
Na verdade, o que faz o código? Uma das coisas é transferir números para dentro e para fora dos registradores que existem dentro do processador. Existem oito registradores de uso geral. Cada registrador guarda 32 bits de dados. Isto é denominado de dword (literalmente, palavra dupla ou "double word"). Num dado momento, cada um dos bits pode estar ligado ou desligado (um ou zero, setado ou zerado, etc). Isto é um número binário. Em 32 bits, se todos os bits estiverem ligados, o número decimal correspondente é 4.294.967.295. Também existem diversas instruções aritméticas que podem ser executadas pelo processador.
Outra coisa que o código faz é transferir números dos registradores para a memória e vice-versa, ou colocar números na pilha da memória. A pilha é como se fosse uma pilha de pratos. Você põe um dword na pilha usando a instrução PUSH e retira o último dword que foi PUSHado para o topo da pilha usando a instrução POP. A memória à qual me refiro é a memória RAM (random access memory - memória de acesso randômico), que fica dentro do computador. A pilha fica reservada quando o programa é carregado. Dependendo dos seus dados de instrução, outra área de memória é reservada pelo sistema quando o programa é carregado. Esta memória é chamada de dados do programa. Mais memória será requisitada pelo programa em tempo de execução.
O contexto Windows
No contexto Windows, uma das coisas mais importantes que as instruções do código fazem é chamar funções do Windows, ou seja, desviar a execução para estas funções. As funções do Windows são chamadas de API (Application Programmer’s Interface). Estas funções são armazenadas em DLLs do Windows. Uma Dll é um arquivo executável fornecido pelo sistema operacional Windows. Geralmente estão numa das pastas (diretórios) onde o Windows foi instalado. A maioria das instruções de código restantes são usadas para preparar estas chamadas e para lidar com o resultado delas.
São estas chamadas às APIs que dão uma funcionalidade extraordinária aos seus programas. A possibilidade de chamar o Windows oferece uma imensa gama de processos que resultarão em interação com o usuário, apresentação adequada na tela, impressão, ações com arquivos, etc. Todas estas ações, na realidade, são realizadas pelo Windows assim que forem requisitadas pelo programa.
O processo de construção
Para construir um executável, você vai precisar de ferramentas de desenvolvimento. Como disse anteriormente, este texto se baseia num artigo de Jeremy Gordon. Portanto, as ferramentas usadas serão softwares do autor, disponíveis gratuitamente no seu site, Win32 + Assembler Source Page:
- GoAsm - o assembler. Este programa transforma seu código fonte num arquivo objeto. Para escrever seu código fonte em texto puro você pode utilizar qualquer editor de texto, por exemplo, o Bloco de Notas ou o Wordpad. Assegure-se apenas de salvar o script em texto sem caracteres de controle especiais. Normalmente a extensão do arquivo deve ser ".asm". O script deve conter as linhas de código fonte, o qual contém o código e os dados de instrução. O arquivo objeto é um arquivo preparado para que possa ser lido pelo linker, que é usado para produzir o executável final.
- GoRC - o compilador de recursos. Este programa converte seu script de recursos num arquivo res. O script de recursos é outro arquivo de texto puro só que, neste caso, contém instruções para criar controles do Windows para o seu programa - menus, diálogos, ícones, bitmaps e tabelas de strings. Normalmente possui a extensão rc. Os arquivos res também precisam ser preparados para que possam ser lidos pelo linker.
- GoLink - o linker. Este programa utiliza um ou mais arquivos objeto e arquivos res para criar o executável final.
- GoBug - o debugger. Com esta ferramenta você pode observar seu programa enquanto é executado. Cada instrução, uma a uma, pode ser rastreada e você pode ver como elas afetam os registradores e as áreas de memória.
O processo de construção pode ser resumido da seguinte forma:
Código Fonte texto puro |
Linker | Arquivo Executável |
---|---|---|
.asm | -> .obj | -> .exe |
.rc | -> .res |
Um programa que não faz nada
Faremos um programa que carrega, executa e termina sem fazer qualquer outra coisa. Isto é apenas para demonstrar o processo de construção e para explicar mais algumas coisinhas.
Crie um diretório (ou pasta) com o nome e a localização que mais lhe convier, por exemplo C:\GoAsm\. Isto ajuda na organização do seu trabalho. Você pode colocar todos seus arquivos e ferramentas neste diretório ou em seus sub-diretórios, como preferir.
Copie GoAsm, GoRC, GoLink (e GoBug) neste diretório.
Usando seu editor de texto, crie um novo arquivo e digite as linhas seguintes:
Salve este arquivo no diretório de trabalho com o nome, digamos, de nada.asm. Este é o programa "faz nada".
- CODE SECTION diz ao assembler que, o que se segue, são códigos de instrução.
- START é um marcador (ou etiqueta) de início do código. Este marcador indica ao linker que este é o ponto onde deve começar a execução do programa.
- RET é um mnemônico (instrução do processador em palavras) que diz ao processador para RETornar ao código chamador que, neste caso, é o próprio Windows.
Usando novamente seu editor de texto, crie um novo arquivo e digite o seguinte:
Salve este arquivo no diretório de trabalho com o nome de, por exemplo, gonada.bat. Você acaba de criar um arquivo de lote (batch file), que é um pequeno arquivo muito útil que executa uma linha após a outra através da janela MSDOS. A primeira linha executa o assembler GoAsm que vai usar o arquivo nada.asm (assumindo que a extensão seja asm). Isto cria o arquivo nada.obj, que então é utilizado pelo GoLink para criar o executável nada.exe. GoLink também recebe a informação para criar um programa de console - este é um programa que não faz uso da Interface Gráfica do Windows (o programa não tem janelas)
Dê um duplo clique sobre gonada.bat e observe o assembler e o linker fazerem seu trabalho. Se preferir, abra a janela do MSDOS, vá ao diretório de trabalho e digite gonada.bat - o efeito é o mesmo.
Dê um duplo clique sobre nada.exe e observe. Se nada acontecer, parabéns! Você acaba de construir seu primeiro programa em Assembly e, o mais importante, sem erros!
Se você receber alguma mensagem de erro ou se o executável não foi gerado, revise os textos tanto do código fonte quanto do batch file, verifique se todos os arquivos necessários (fontes, assembler e linker) estão no mesmo diretório e repita o processo.
Um programa que escreve "NumaBoa"
Agora faremos um programa que é carregado através do MSDOS e que escreve "NumaBoa" na tela. É apenas para demonstrar como chamar uma API do Windows. Este tipo de programa é chamado de programa de console, por que ele não faz janelas, ou seja, não faz uso da GUI (Graphical User Interface) do Windows. O processo é o mesmo que o anterior. Apenas é preciso mudar os nomes do código fonte, por exemplo para numaboa.asm, e do arquivo de lote, por exemplo para gonumaboa.bat.
Digamos que você use o seguinte para o batch file:
Na primeira linha, GoAsm numaboa vai transformar numaboa.asm em numaboa.obj. A segunda linha tem algumas novidades. Em primeiro lugar, "/debug coff". Isto adiciona informações de debug ao executável de modo que os símbolos que você esteja usando aparecerão num debugger (usando um debugger você pode executar o programa linha por linha). Isto é opcional e você deveria usar esta chave do linker apenas enquanto estiver desenvolvendo seu programa e tiver que efetuar testes.
"Kernel32.dll" é uma biblioteca necessária para informar o linker de que deve obter as funções da API requeridas pelo programa no arquivo Kernel32.dll do Windows. No caso serão utilizadas as funções GetStdHandle e WriteFile.
Crie um novo arquivo e digite as seguintes linhas:
DATA SECTION diz ao assembler que, a seguir, vem uma instrução (ou instruções) de dados. WRKEEP é um marcador de dados cujo nome indica um lugar em particular na área de dados. DD cria um dword (4 bytes) na área de dados (literalmente "declara dword"). 0 inicializa o dword com um valor, neste caso zero.
Seguindo as linhas acima digite o seguinte:
CODE SECTION e START você já conhece. PUSH põe um valor na pilha. O valor, neste caso, é menos 11 (expresso como um número decimal normal). Isto é PUSHado para a pilha, pronto para ser enviado como parâmetro na chamada da API. CALL transfere a execução para um procedimento, neste caso a função GetStHandle da API do Windows que se encontra na Kernel32.dll. Esta função precisa de um parâmetro e devolve um manipulador (handle) no registrador EAX. Aqui, solicitamos um manipulador -11, que é o manipulador padrão de saída (output) para o console. O console é a interface do usuário que, neste caso, será o MSDOS do Windows. Através deste manipulador poderemos escrever na tela da janela MSDOS.
A seguir adicione:
Aqui PUSHamos parâmetros que serão utilizados na chamada à função da API WriteFile. Esta função escreve no manipulador passado como último parâmetro (que ainda se encontra no registrador EAX). Ela escreve a string de 9 caracteres de comprimento. Também fornecemos o endereço de WRKEEP, o dword de dados feito anteriormente. Isto é necessário porque WriteFile colocará neste dword quantos caracteres foram escritos.
Agora os finalmentes:
Aqui colocamos o valor 0 no registrador EAX (para indicar um final com sucesso) e usamos o RET para voltar ao sistema (fechando o programa).
Compile e linke o programa dando um duplo clique em gonumaboa.bat. Para observar o programa escrever "NumaBoa" na tela você precisa executá-lo através da janela MSDOS, uma vez que se trata de um programa de console.
Agradecimento
Um agradecimento especial a Jeremy Gordon, autor do software e do artigo que serviu de base para este texto. O site do autor é em inglês e, sem dúvida alguma, vale uma visita. Seu trabalho é sério e de excelente qualidade, contribuindo sobremaneira para o aprimoramento do Assembly e sendo um exemplo de despreendimento ao disponibilizar gratuitamente seu software para a comunidade.