Informática Numaboa - Tutoriais e Programação
Cap. II - Nossa primeira aplicação
Sex 14 Dez 2007 07:52 |
- Detalhes
- Categoria: MASM + RadASM
- Atualização: Segunda, 01 Março 2010 20:00
- Autor: Alan Moreno
- Acessos: 12866
Masm32+RadASM
Capítulo II - Nossa primeira aplicação
Escrito por: ^A|An M0r3N0^ Conselheiro: RedH@wk Tradução: ~Uglinho~O presente texto foi escrito para fins educacionais e de pesquisa e é de livre distribuição contanto que se preserve o conteúdo e os direitos do autor.
A estrutura dos nossos programas
Para criar um programa em MASM32 deve-se seguir uma estrutura que o nosso compilador possa entender. Por exemplo:
Com este código já criamos um programa que nosso compilador pode entender e assim criar nossa aplicação. Agora explicarei para que serve cada uma destas seções do código:
- .386 - Esta diretiva serve para estabelecer o tipo de processador e as instruções com as quais irá trabalhar. Neste caso é um 80386.
- .model flat, stdcall - Aqui estabelecemos o modelo de memória requerido para nossos programas de 32 bits.
- option casemap:none - Esta opção torna possível a diferenciação de maiúsculas e minúsculas, por exemplo, "Z" é diferente de "z".
- Include e Includelib - O MASM32 inclui arquivos e bibliotecas para manipular um grande número de funções que existem no Windows. Estas funções são conhecidas como API, como por exemplo a API ExitProcess que está em nosso código.
O include se utiliza para adicionar arquivos com extensão .inc e .asm
O includelib se utiliza para adicionar bibliotecas com extensão .lib
O MASM32 também inclui o arquivo window.inc onde encontramos um grande número de constantes e estruturas usadas pelas funções do Windows (API). - .data - Existem dois tipos de informação, a informação inicializada e a não inicializada (.data?)
- Informação Inicializada (.data) - Nesta seção declaramos os dados que conhecemos, com os quais nosso programa se inicia. Por exemplo:
.data
Etiqueta Tipo de variável Dados inicializados Msg_Texto db "BEM VINDO AO CURSO MASM + RADASM",0 Valor_1 dd 7 - Informação Não Inicializada (.data?) - Nesta seção declaramos os dados que não conhecemos ou apenas estarão disponíveis quando o programa for executado. Normalmente a utilizamos para armazenar dados, por exemplo:
.data?
Etiqueta Tipo de variável Dados inicializados Buffer db 128 dup (?) Valor_2 dd ?
- Informação Inicializada (.data) - Nesta seção declaramos os dados que conhecemos, com os quais nosso programa se inicia. Por exemplo:
- .code - Depois das seções de dados, devemos indicar ao MASM32 onde começa o código do programa e também onde termina. Para isto colocamos uma etiqueta, por exemplo Prog001, seguida de ":", para indicar que abaixo começa o código do nosso programa e, ao terminar o código do programa, se escreve end mais a etiqueta que declaramos, ficando desta maneira: end Prog001
Programando no RadASM
Ao nosso código acima adicionaremos uma nova função para que mostre uma janela que nos dê boas vindas. Para isto abriremos o RadAsm.exe e começaremos a programar como mostra o video:
Para assistir ao vídeo, faça o download de prog001.exe.
Explicando o vídeo Prog001.exe
No programa que desenvolvemos foram utilizadas duas funções: MessageBox e ExitProcess.
Se abrirmos nossa documentação das APIs do Windows (Win32 programmer's Reference) e buscarmos a função MessageBox, encontraremos o seguinte:
int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
- hWnd - Este parâmetro serve para identificar o manipulador da janela mãe. No nosso caso colocamos NULL ou "0" porque ela não tem um manipulador (handle).
- lpText - Aqui colocamos o endereço onde se encontra a nossa mensagem.
- lpCaption - Este parâmetro funciona como a lpText, a diferença é que este é o título da janela com a mensagem.
- uType - Este parâmetro é muito útil no momento de criar nossa janela - serve para personalizar a mensagem. Podemos especificar que tipo de botões desejamos usar e também o ícone. Por exemplo, no nosso programa foram usadas as seguintes constantes:
Botões Ícone Estas constantes estão declaradas no arquivo window.inc MB_OK MB_ICONINFORMATION
Para saber mais sobre esta função sugiro que você revise a documentação que mencionei anteriormente.
Em todo programa que escrevemos no MASM32 deve-se colocar a seguinte função:
VOID ExitProcess( UINT uExitCode );
Com esta função encerramos o programa. No parâmetro uExitCode se especifica o código de saída, no nosso caso foi usado "0".
invoke - O MASM32 também tem uma sintaxe de alto nível que facilita a chamada de funções de forma correta e segura na hora de compilar - o MASM32 comprovará se os parâmetros das funções são adequados ou não. É usado desta maneira:
FUNÇÃO é onde escrevemos o nome da função que será usada.
Argumentos são os parâmetros das funções e devem ser separados por virgulas ",".
Operadores no arquivo prog001.asm
- addr - Este operador serve para passar o endereço das nossas etiquetas para a função, por exemplo as etiquetas MsgTexto e MsgTitulo.
- offset - É semelhante ao addr, mas com algumas diferenças como mostra o seguinte quadro:
addr | offset |
Não pode ser usado com instruções mnemônicas. | Se utiliza com instruções mnemônicas. |
Trabalha apenas com referências que estão adiante no código. | Trabalha com referências que estão atrás ou adiante no código. |
Pode operar com estruturas. | Não pode operar com estruturas. |
Operadores no arquivo prog001.inc
O Windows tem uma grande quantidade de APIs no seu sistema que são usadas por todos os programadores para Windows. Estas APIs ou Funções são encontradas nas bibliotecas de vínculo dinâmico (dynamic-linked libraries ou "DLL"), como por exemplo: user32.DLL, kernel32.DLL, shell32.DLL. Para podermos usar estas funções ou APIs em nossos programas, precisamos adicionar 2 arquivos para cada biblioteca:
- user32.inc e kernel.inc - Nestes arquivos encontramos todas as funções declaradas que pertencem à user32.dll e à kernel32.dll respectivamente. Isto nos poupa tempo no momento de programar porque não precisamos declarar as funções que iremos usar. Vamos observar seu conteúdo para ver o que contêm. Para isto devemos abrir os arquivos .inc
Para abrir o arquivo, selecionamos o nome do arquivo .inc que desejamos abrir e pressionamos o botão direito do Mouse. Abre-se um menu onde clicamos na opção Abrir, como mostra a seguinte imagem:
Depois se abre uma nova janelinha no RadAsm mostrando o seguinte:
Buscaremos nossa API MessageBox pressionando as teclas CTRL + F e escrevemos a função que vamos buscar, como mostra a seguinte imagem:
Em seguida damos um clique no botão hallar/Buscar e encontramos o seguinte:
Já encontramos nossa função e comprovamos que esta API está declarada em user32.inc. Se buscarmos a outra API que utilizamos (ExitProcess), não a encontraremos porque esta API está em kernel.inc.
- user32.lib e kernel.lib - Para que nosso programa possa se ligar com as bibliotecas de vínculo dinâmico do Windows, são necessárias informações como o nome da função e o endereço onde ela se encontra para que, no momento em que for executado, nosso programa carregue a biblioteca imediatamente. A informação mencionada se encontra nos arquivos .lib
Variáveis
TIPOS DE VARIÁVEIS | |||
Tipo | Abreviação | Espaço | Descrição |
BYTE | DB | 1 byte ou 8 bits | Cadeias de texto e caracteres |
WORD | DW | 2 bytes ou 16 bits | Valor inteiro que vai de -32.786 a +65.535 |
DWORD | DD | 4 bytes ou 32 bits | Valor inteiro que vai de -2gb a +4gb |
FWORD ou REAL4 | DF | 6 bytes ou 48 bits | 48 bits com ponto flutuante |
QWORD ou REAL8 | DQ | 8 bytes ou 64 bits | 64 bits com ponto flutuante |
TBYTE ou REAL10 | DF | 10 bytes ou 80 bits | 80 bits com ponto flutuante |
Vejamos alguns exemplos de como se deve declarar variáveis (nas seções .data e .data?):
Exemplo de dados inicializados
Que vem a ser o mesmo que:
Exemplo de dados não inicializados
Que vem a ser o mesmo que:
Criando um modelo no RadASM
O programador do RadASM pensou em tudo e, para não voltarmos a escrever toda a estrutura dos nossos programas toda vez que quisermos programar, criamos um modelo como é mostrado no seguinte vídeo:
Para assistir ao vídeo, faça o download de Creando Plantilla.exe.
Se quisermos ir para a pasta onde está nosso código fonte, abrimos o Menu Projeto/Abrir janela do projeto como mostra a imagem:
O que abre a pasta onde está nosso código fonte:
Exercício com dados não inicializados
No exercício anterior foram utilizados dados inicializados, agora falta criar um exemplo utilizando dados não inicializados:
Para assistir ao vídeo, faça o download de prog001a.exe.
No exemplo Prog001a foi usada a função GetModuleFileName que é declarada da seguinte maneira:
Biblioteca kernel32.lib GetModuleFileName,NULL,addr Buffer,225
Esta função extrai o diretório mais o nome da aplicação e o devolve na variável Buffer. Se Buffer já estiver ocupado, ele será modificado com os novos caracteres. O valor 225 significa o comprimento máximo de caracteres que serão devolvidos.
Buffer cumpre a função de armazenador de dados e é onde será armazenada a cadeia de texto devolvida pela função que foi utilizada.
Um programa mais complexo
Façamos nosso programa maior e um pouco mais complexo como mostrado no exemplo a seguir. Para isso utilizaremos a biblioteca masm32.lib.
O Masm32 possui sua própria biblioteca onde podemos encontrar muitas funções úteis, as quais muitas vezes precisamos e não levamos em conta. No seguinte vídeo utilizaremos algumas destas funções. Para isto vamos criar um programa que mostra o diretório da aplicação em uma mensagem e uma segunda mensagem que mostra o nome da aplicação que se está sendo executada:
Para assistir ao vídeo, faça o download de prog002.exe.
Funções utilizadas no vídeo prog002.exe
Biblioteca masm32.lib GetAppPath,addr Buffer
Esta função devolve o diretório da aplicação e o coloca na variável que definimos, neste caso Buffer, que ficará armazenado até que outra função substitua os dados que esta variável contém.
Biblioteca masm32.lib NameFromPath,addr Buffer,addr NomeAplic
Como sabemos, Buffer contém o nome mais o diretório da aplicação porque já foi utilizado pela API GetModuleFileName. A função NameFromPath só extrairá o nome e o armazenará na variável NomeAplic.
- Operador dup - significa duplicação. Se utiliza para alocar espaços na memória e sua sintaxe é a seguinte:
Contador dup (valor inicial)
Em contador escrevemos o tamanho que vamos duplicar. O valor inicial é escrito dentro dos parênteses, onde o sinal ? significa que o valor é indefinido.
No nosso código foi declarado da seguinte maneira:
Etiqueta | Variável | Contador | DUP | Valor Inicial |
Buffer | db | 225 | dup | (?) |
NombreApp | db | 50 | dup | (?) |
E significa o seguinte: Na variável Buffer foram separados 225 bytes na memória e na variável NombreApp foram separados 50 bytes na memória.
Recomendo que, se for utilizada uma variável para armazenar todo tipo de cadeias de texto devolvidas pelas funções, as variáveis declaradas tenham um espaço correspondente ao que se irá obter.
Você deve estar se perguntando porque se faz isto. É que quando você utiliza diversas variáveis no seu código, se não for alocado um espaço apropriado na memória para a dita variável, a cadeia de texto devolvida muitas vezes invade as outras variáveis e isto pode ocasionar problemas.
Exercícios
Com a ajuda do Win32 programmer's Reference, para saber o uso e os parâmetros referentes às funções faça estes exercícios:
- Criar novas mensagens utilizando a API MessageBox - exemplo prog001a:
- No programa anterior adicionar a API MessageBeep, no lugar onde vocês desejarem.
- Crie um programa que mostre o diretório do Windows em uma mensagem e que depois mostre o diretório do Sistema em uma outra mensagem. Utilize as funções: GetWindowsDirectory e GetSystemDirectory.
Vocabulário
API (Application Programming Interface) - Interface de Programação de Aplicações. São funções de uso geral que se encontram no nosso Sistema Windows e que estão armazenadas em bibliotecas como, por exemplo, user32.dll e kernel32.dll.
Sintaxis - Sintaxe é uma forma de combinação das palavras segundo as regras estabelecidas pela linguagem de programação.
Mnemonic (Mnemônico) - Para facilitar o trabalho de escrever código de baixo nível, há muitos anos foi desenvolvido um sistema onde grupos de códigos operacionais semelhantes receberam nomes que lembram suas funções e que os tornaram muito mais práticos de serem usados. Estes nomes são denominados mnemônicos. Este é o sistema utilizado nos assemblers de 32 bits modernos.
Lembrando
Não esquecer de perguntar na lista MASM32-RadASM. As soluções destes exercícios serão enviados para a lista dentro de uma semana. Vocês também podem enviar suas prórias soluções.
Se tiverem dúvidas, sugestões ou outros, faça-as na lista de discussão.
O autor pode ser contactado
eMail: O endereço de e-mail address está sendo protegido de spambots. Você precisa ativar o JavaScript enabled para vê-lo. ou O endereço de e-mail address está sendo protegido de spambots. Você precisa ativar o JavaScript enabled para vê-lo.
Lista de discussão MASM32-RadASM
http://groups.google.es/group/MASM32-RadASM
www
Copyright(c) 2005-2006 RVLCN
Recado da vó
Aqui está o código fonte dos exercícios deste tutorial: