A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Informática Numaboa - Tutoriais e Programação

Trabalhando com estruturas (masm)

Ter

20

Jan

2009


21:24

(1 voto de 5.00) 


Nível Intermediário

Quando se escreve código para Windows, é comum manusear dados em bloco para alguns requisitos de codificação. O método mais comum é usar uma estrutura para agrupar os dados de forma que possam ser endereçados como uma unidade.

Estruturas

Uma estrutura é constituída por membros que têm um tamanho fixo para armazenar os dados. Na estrutura RECT, muito utilizada, existem quatro membros de tamanho DWORD.

RECT STRUCT
   left DWORD ?
   top DWORD ?
   right DWORD ?
   bottom DWORD ?
RECT ENDS

A notação para cada membro é: nome do membro, tamanho do dado e especificador. Na maior parte das vezes o especificador é um ponto de interrogação (?), significando que o membro não foi inicializado com um valor.

A estrutura é colocada na memória como uma sequência de membros. No caso da estrutura RECT, ela é escrita na memória como uma sequência de quatro membros de tamanho DWORD. Os membros de uma estrutura podem ser preenchidos de várias maneiras diferentes, dependendo da modo como a estrutura foi originalmente definida.

Se ela tiver sido alocada na seção .DATA, eles podem ser inicializados com valores predefinidos. Se tiver sido alocada na pilha, como uma variável local de um procedimento, os valores precisam ser inseridos nesta estrutura através de codificação. Por exemplo:

LOCAL Rct:RECT ; código mov Rct.left, 1 mov Rct.top, 2 mov Rct.right, 3 mov Rct.bottom, 4

É preciso salientar que um membro de uma estrutura é um operando de memória, o que significa que você não pode transferir diretamente outro operando de memória para ele. É preciso usar um registrador para copiá-lo ou usar os mnemônicos de pilha push/pop.

Numa chamada com a diretiva invoke podemos nos referir à estrutura preenchida como uma unidade com ADDR Rct. Se uma chamada de API necessitar do endereço de uma estrutura, você deve preencher a estrutura com os valores requeridos e depois chamar a API de acordo com a seguinte sintaxe:

invoke chamadaAPI, parametro1, parametro2, ADDR Rct

Se você escrever um procedimento para o qual você queira passar os valores de uma estrutura, pode passar esta estrutura usando os tipos de dados da estrutura no procedimento.

MeuProc proc par1:DWORD, par2:DWORD, MeuRect:RECT mov eax, MeuRect.left ; copiar o primeiro membro para EAX

No procedimento que recebe RECT como parâmetro, cada um dos membros pode ser acessado através do nome. Você chama o procedimento da seguinte forma:

invoke MeuProc, par1, par2, Rct

Estruturas aninhadas

Um método muito comum no Windows 32 bits é o uso de estruturas aninhadas. O MASM possui uma notação que lida com este tipo de construção. Se você precisar de uma estrutura que possui múltiplas estruturas no seu interior, a coisa funciona assim:

MinhaEstruAninhada STRUCT
   item1 RECT <>
   item2 POINT <>
MinhaEstruAninhada ENDS

Esta estrutura usa a estrutura RECT (mostrada anteriormente) e a seguinte estrutura POINT:

POINT STRUCT
   x DWORD ?
   y DWORD ?
POINT ENDS

Neste caso, existem seis membros na estrutura "MinhaEstruAninhada", quatro da estrutura RECT e dois da estrutura POINT. Alocada na pilha, tem o seguinte aspecto:

LOCAL mea:MinhaEstruAninhada

Os seis membros desta estrutura são:

mea.item1.left
mea.item1.top
mea.item1.right
mea.item1.bottom
mea.item2.x
mea.item2.y

A notação mea.item2.x significa a estrutura alocada mea, seu segundo item (item2) e o primeiro item da estrutura POINT (x).

As estruturas podem ser aninhadas em diversas profundidades, mas todas usam esta mesma notação e a mesma lógica.

Uso avançado de estruturas

Cada vez mais existe a necessidade de manusear estruturas que são passadas como um endereço e este tipo de codificação está-se tornando comum no design de código Windows. O MASM tem uma notação especializada para facilitar o manuseio.

Se, por exemplo, você precisasse passar o endereço de uma estrutura RECT para um procedimento, normalmente iria fazer a chamada da seguinte maneira:

invoke MinhaFuncao, ADDR Rct

No final do procedimento onde foi chamada esta função, normalmente haveria algo parecido com o seguinte:

MinhaFuncao proc lpRect:DWORD

Com uma estrutura simples como a RECT, você pode endereçar manualmente cada um dos parâmetros colocando o endereço num registrador e escrevendo na localização de cada membro:

mov eax, lpRct mov [eax], DWORD PTR 10 mov [eax+4], DWORD PTR 12 mov [eax+8], DWORD PTR 14 mov [eax+12], DWORD PTR 16

Isto funciona muito bem, porém, com estruturas mais complexas, fica mais difícil trabalhar e mais fácil errar. A alternativa é usar um método que o MASM possui para endereçar cada um dos membros: a diretiva ASSUME.

ASSUME eax:PTR RECT mov eax, lpRct mov [eax].left, 10 mov [eax].top, 12 mov [eax].right, 14 mov [eax].bottom, 16 ASSUME eax:nothing

Esta diretiva informa o assembler que o registrador EAX deve ser tratado como uma estrutura RECT. O ASSUME eax:nothing informa o assembler que é para parar de tratar o registrador como uma estrutura RECT.

Há uma notação alternativa onde você pode fazer um "type cast" para cada membro:

mov eax, lpRct mov (RECT PTR [eax]).left, 10 mov (RECT PTR [eax]).top, 12 mov (RECT PTR [eax]).right, 14 mov (RECT PTR [eax]).bottom, 16

A vantagem desta técnica é que ela usa a conveniência e a confiabilidade de uma estrutura, de modo que você não precisa calcular o offset de cada membro, além de usar os nomes normais dos membros. A desvantagem desta técnica é que ela usa um registrador, o que nem sempre é conveniente. Se o uso do registrador for um problema, você precisará alocar variáveis LOCAIS e copiar os dados de cada membro requerido para estas variáveis.

Finalmentes

O assunto parece ser coisa de outro planeta? Se for este o seu caso, ignore este tutorial por enquanto. Em outros tutoriais sobre Assembly estas técnicas serão utilizadas e haverá links para este tutorial. Aí a coisa fica um pouco mais clara, mas se você quiser matar a curiosidade agora mesmo, veja uma aplicação prática no tutorial "Pintando texto".

Abraços da vó Vicki vovo

казино онлайн покергаз гриль отзывыполигон отзывы биолруссбыт тиц и пиарсайт nikas

Informações adicionais