Informática Numaboa - Tutoriais e Programação

Cap. IV - Condições e Loops

Dom

16

Dez

2007


14:03

  • Imprimir
(5 votos, média 5.00 de 5) 


Nível Intermediário

Masm32+RadASM

Capítulo IV: Condições e Loops

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.

O Masm32 pode utilizar o bloqueio .if (condição) e também .while, .repeat/.until (Loops). Aprenderemos duas formas de utilizá-las. A primeira será utilizando bloqueios, a outra será usando instruções CMP e JXX.

Condições

Usando o bloqueio .IF - O MASM pode fazer comparações simples e complexas de forma fácil. Conheça a sintaxe.

Uma comparação simples seria desta maneira:

SimplesSimples mais .else
.if Condição ; Se cumprir a condição, faça algo aqui .endif .if Condição ; Se cumprir a condição, faça algo aqui .else ; Caso contrário, faça algo aqui .endif

Se desejar fazer comparações sequenciais:

SequencialSequencial mais .else
.if Condição ; Se cumprir a condição, faça algo aqui .elseif ; Se cumprir a condição, faça algo mais aqui .endif .if Condição ; Se cumprir a condição, faça algo aqui .elseif ; Se cumprir a condição, faça algo mais aqui .else ; Se não cumpriu nenhuma condição, ;faça algo aqui .endif

Antes de começar com os exercícios, observemos a seguinte tabela de operadores para as comparações:

Operadores de Comparação
==igual
!=não igual
>maior
>=maior ou igual
<menor
<=menor ou igual
Operadores de Multi-comparação
&&AND lógico "E"
||OR lógico "OU"
Operador para verificar o estado das bandeiras (flags) do processador
CARRY?bit do Carry setado
OVERFLOW?bit do Overflow setado
PARITY?bit da Paridade setado
SIGN?bit de Sinal setado
ZERO?bit do Zero setado

No exercício a seguir faremos uma série de comparações. Para isto utilizaremos a biblioteca rvlcnrand.lib para gerar valores inteiros aleatórios. Os algoritmos geradores foram criados por Randall Hyde, desenvolvedor do compilador HLA (High Level Assembly) e passado para o MASM32 por minha pessoa.

Biblioteca rvlcnrand.lib
FunçãoDescrição
randzimeCom esta função criamos um ponto ao acaso para que possa ser utilizado pelas 4 funções seguintes: random, range, uniform, urange. Desta maneira sempre se poderá gerar de forma aleatória.
randomGera números aleatórios uniformemente distribuídos utilizando um algoritmo linear. O resultado é devolvido em EAX.
Invoke random
rangeGera um número aleatório usando a função random, levando em conta o limite estabelecido. O resultado é devolvido em EAX.
Invoke range, inicio, final
uniformEsta função gera um novo número aleatório uniformemente distribuído em cada chamada. O resultado é devolvido em EAX.
Invoke uniform
urangeGera um número aleatório usando a função urange levando em conta o limite estabelecido. O resultado é devolvido em EAX.
Invoke urange, inicio, final

Exemplo:

Vídeo 1
prog005_ha_c.exe

vovo Para assistir ao vídeo, faça o download de prog005_ha_c.exe.

Analisando prog005

Como já vimos na ajuda "win32programmer's Reference", a função Messagebox, uma vez executada, devolve para EAX o valor do botão que pressionamos. Para recordar:

Referência
Fig. 1
invoke MessageBox.... .if eax==IDYES ; Compara se EAX é igual à constante IDYES invoke MessageBox.... .endif

O que faz é comparar se pressionamos o botão Yes/Sim e, se esta condição for cumprida, mostrará a mensagem que indicamos.

Analisando o programa prog005a

Este programa é igual ao exercício anterior, só que adicionamos o bloqueio .else para o caso da condição não se cumprir.

invoke MessageBox.... .if eax==IDYES ; Compara se EAX é igual à constante IDYES invoke MessageBox.... .else ; Se não cumprir a condição: invoke MessageBox.... .endif

Se nossa primeira condição não se cumprir, a outra mensagem que está sob o bloqueio .else será mostrada.

Analisando o programa prog005b

Neste exercício utilizamos o bloqueio .elseif para realizar várias comparações porque a função Messagebox contém 3 botões diferentes e EAX pode ter qualquer um desses 3 valores.

invoke MessageBox.... .if eax==IDYES ; Compara se EAX é igual à constante IDYES invoke MessageBox.... .elseif eax==IDNO ; Compara se EAX é igual à constante IDNO invoke MessageBox.... .endif

Neste exercício não levamos em consideração o botão Cancel, mas se quiser, você pode adicioná-lo.

Analisando o programa prog005c

Neste exercício utilizamos a biblioteca rvlcnrand.lib para criarmos uma série de comprovações utilizando a maioria de operadores que vimos:

invoke randzime invoke range,1,20 .if eax > 10 && eax <=15 ; Compara se EAX é maior que 10 ; e se EAX é menor ou igual a 15 invoke MessageBox,... .elseif eax < 5 ; Compara se EAX é menor que 5 invoke MessageBox,... .elseif eax == 15 || eax == 16 ; Compara se EAX é igual a 10 ; ou se EAX é igual a 16 invoke MessageBox,... .elseif eax >= 19 ; Compara se EAX é maior ou igual a 19. invoke MessageBox,... .else ; Se não cumprir nenhuma das condições, ; faça o seguinte: invoke MessageBox,... .endif

No primeiro bloqueio, .if eax > 10 && eax <=15, se o valor de EAX for maior que 10 e se for menor ou igual a 15, a mensagem será mostrada. Repare que o operador && é um elo para outra comparação e significa "E". Então, para que a mensagem ser mostrada, as duas condições precisam ser cumpridas.

No terceiro bloqueio, .elseif eax == 15 || eax == 16, se o valor de EAX for igual a 15 ou se EAX for igual a 16, a mensagem será mostrada. Também há outro operador elo "||", que significa "OU". Então, para que a mensagem possa ser mostrada, as duas condições precisam ser cumpridas.


Também podemos fazer comparações utilizando instruções:

CMP (compara) DESTINO FONTE

Destino - podem ser variáveis e registradores de 8, 16, 32 bits. Fonte - podem ser variáveis, registradores e valores inteiros.

Esta instrução compara os dois operandos e, por sua vez, modifica as bandeiras AF, CF, OF, PF, SF, ZF do microprocessador.

jxx (salta) ETIQUETA

Esta instrução salta até um endereço. Vejamos a tabela de alguns saltos e seus significados:

InstruçãoDescriçãoEstado das bandeiras
JAsaltar se estiver acimaCF=0 e ZF=0
JAEsaltar se estiver acima ou for igualCF=0
JBsaltar se estiver abaixoCF=1
JBEsaltar se estiver abaixo ou for igualCF=1 ou ZF=1
JEsaltar se for igualZF=1
JGsaltar se for maiorZF=0 ou SF = OF
JGEsaltar se for maior ou igualSF = OF
JLsaltar se for menorSF != OF
JLEsaltar se for menor ou igualZF=1 ou SF != OF
JMPsaltar diretamente-
JNAsaltar se não estiver acimaCF=1 ou ZF=1
JNAEsaltar se não estiver acima ou for igualCF=1
JNBsaltar se não estiver abaixoCF=0
JNBEsaltar se não estiver abaixo ou for igualCF=0 e ZF=0
JNEsaltar se não for igualZF=0
JNGsaltar se não for maiorZF=1 ou SF != OF
JNGEsaltar se não for maior ou igualSF != OF
JNLsaltar se não for menorSF = OF
JNLEsaltar se não for menor ou igualZF=0 e SF = OF

Pergunta: Para que serve o estado da bandeira ou Flag? Cada instrução e salto é executada se uma determinada condição for cumprida. Por exemplo:

JA será executado quando a bandeira CF for igual a 0 e ZF também for igual a zero.

JBE será executado quando a bandeira CF for igual a 1 ou ZF for igual a 1.

Reparem que JMP não tem condição. Isto significa que essa instrução não precisa de nenhuma condição para ser executada.

É por isso que a instrução CMP modifica essas bandeiras, é para que o salto colocado na linha seguinte possa ser executado.

Então vamos analisar o prog006, onde encontraremos o seguinte:

.code prog006: invoke MessageBox ....... cmp eax, IDYES ; Compara EAX com a constante IDYES jne Fim ; Salta para Fim se não forem iguais. invoke MessageBox,NULL,addr MsgIDYES,addr MsgTitulo,MB_OK Fim: invoke ExitProcess,0 end prog006

Primeiro utilizamos CMP para comparar EAX com a constante IDYES. Se não forem iguais, saltará para a etiqueta Fim; se coincidir, mostrará a mensagem.

Este exercício seria o mesmo que o prog005. A diferença é que não utilizamos o bloqueio .if. Façamos o mesmo com o prog005b usando instruções:

.code prog006a: invoke MessageBox,....... cmp eax, IDYES ; Compara EAX com a constante IDYES jne _ElseIF ; Salta para _ElseIF se não forem iguais. invoke MessageBox,NULL,addr MsgIDYES,addr MsgTitulo,MB_OK _ElseIF: cmp eax,IDNO ;Compara EAX com a constante IDNO jne Fim ; Salta para Fim se não forem iguais. invoke MessageBox,NULL,addr MsgIDNO,addr MsgTitulo,MB_OK Fim: invoke ExitProcess,0 end prog006a

Para fazer comparações com instruções, devemos saber cada significado dos saltos.

Agora utilizaremos as bibliotecas rvlcnrand.lib para gerar um valor aleatório e a biblioteca masm.lib, porque será usada a função dwtoa para mostrar o resultado.

.code prog006b: invoke randzime invoke urange,1,15 cmp eax,5 ; Compara EAX com 5 jg Maior ; Salta se for Maior invoke MessageBox... jmp Fim ; salta diretamente Maior: cmp eax,10 ; Compara EAX com 10 jl Menor ; Salta se for menor invoke MessageBox........ jmp Fim ; salta diretamente Menor: invoke dwtoa,eax,addr Cmp_03 invoke MessageBox,...... Fim: invoke ExitProcess,0 end prog006b

Quando a mensagem será mostrada?

A mensagem será mostrada quando EAX for menor que 5

A mensagem será mostrada quando EAX for maior que 10

O valor será mostrado quando nenhuma condição for cumprida.


Loops

Nos loops estudaremos os bloqueios .while e .repeat/.until para criar laços que se repitam até que a condição que determinamos seja cumprida ou não.

.while

Este bloqueio criará um laço ou loop sempre e enquanto a condição for cumprida. Caso não se cumpra, o laço é interrompido. Sua sintaxe é a seguinte:

.while condição ; codigo .endw

Exemplo:

Mov eax,6 .while eax > 1 sub eax, 1 .endw

Este laço se repetirá sempre e enquanto eax for maior que 1. Se não for cumprida, o laço se romperá. Se não quisermos fazê-lo com bloqueios, também podemos fazer com instruções puras desta maneira:

Mov eax,6 jmp comprova loop: sub eax, 1 ; tiramos 1 do conteúdo de EAX comprova: cmp eax, 1 ja loop

Como imitamos o bloqueio .while, criamos um salto diretamente para a instrução cmp. Logo em seguida vem o salto JA (saltar se estiver acima), o que acontece caso eax estiver acima de 1. Este laço se romperá quando eax for 0.

.repeat / .until

Este laço funciona ao contrário de .while. Neste caso o laço terminará quando cumprir a condição e sua sintaxes é assim:

.repeat ;codigo .until condição

Exemplo:

mov eax,0 .repeat add eax, 1 ; somamos 1 ao conteúdo de eax .until eax > 6

O laço se repetirá até que eax seja maior que 6. Assim como no bloqueio .while, também podemos obter o mesmo resultado com instruções feitas desta maneira:

mov eax,0 loop: add eax, 1 cmp eax, 6 jnb loop

Vejamos o seguinte video com exemplos de loops (laços):

Vídeo 2
prog007_ha_b.exe

vovo Para assistir ao vídeo, faça o download de prog007_ha_b.exe.


Analisando o prog007 - Criando loop com o bloqueio .while:

Biblioteca user32.lib FindWindow,NULL,addr MsgTitulo
FindWindow
Fig. 2

Esta função busca o título da janela ou também a classe da janela e, se a encontra, devolve o manipulador (handle) da janela para o registro EAX. Para mais informação revisem a documentação Win32 Programmer's Reference Fig. 2.

Linha 9

Linha 9 - Buscamos o título da janela. Se a encontrar, devolverá o manipulador (handle) em EAX.

Linha 10 - Criamos um laço com o bloqueio .while. Se EAX for maior que 1, o laço se realizará sempre e enquanto EAX for maior do que 1. É por isto que foi posta novamente a função Findwindow antes de .endw, na linha 12, para que o laço prossiga até que não encontre o título da janela. Se não o encontrar, EAX será 0 e o laço se romperá.

Analisando o prog007a - Criando laço com o bloqueio .repeat/.until:

Linha 10

Linha 9 - Criamos um ponto ao acaso para que possa criar valores aleatórios com a função range.

Linha 10 - A função range devolve em EAX um valor compreendido entre 0 e 100.

Este laço se repetirá até que o conteúdo de EBX seja maior do que EAX. É por isto que se soma 1 a EBX a partir de 0. Como se sabe, o valor de EAX é desconhecido porque este valor é determinado pela função range.

Biblioteca kernel32.lib wsprintf,addr buffer,addr Msgtexto,ebx

Com esta função passamos o conteúdo de ebx para o formato ASCII, mas este não é o único formato para o qual podemos passar. Vejamos o seguinte exemplo:

Linhas

Agora mostraremos 2 valores, em decimal e hexadecimal. Outra coisa importante é que a função wsprintf só tem 2 parâmetros fixos, os outros são opcionais. Só podemos adicioná-los quando queremos passar de um formato para outro como, por exemplo:

  • %d para formato decimal
  • %x para formato hexadecimal

Nossa cadeia tem 2 formatos:

MsgTexto db "Decimal: %d ; hexadecimal: %x" ,0

Por isto é necessário colocar 2 parâmetros a mais na nossa função que, no caso, são eax e ebx. Vejamos como se alinha cada registro com seu formato:

Alinhamento


No exemplo a seguir adicionaremos um ícone na nossa aplicação:

Agregando um ícone

Algumas aplicações no nosso PC têm seus próprios ícones. Nós também personalizaremos nosso programa com um ícone próprio. O que devemos fazer é por nosso ícone num recurso e o faremos desta maneira:

Vídeo 3
prog008.exe

vovo Para assistir ao vídeo, faça o download de prog008.exe.

Nota - É importante que o ícone esteja dentro da pasta do nosso projeto.

Adicionando uma ferramenta

Alguma vez você já se perguntou como saber quais funções pertencem a qual biblioteca? Pois ao nosso RADASM adicionaremos um programa para buscar a função e nos mostrar que biblioteca onde se encontra.

Vídeo 4
Add_tools.exe

vovo Para assistir ao vídeo, faça o download de Add_tools.exe.

Exercícios

  1. Crie um loop que se repita 1000 vezes com .while e .repeat/.until
  2. Crie um loop para que mostre uma mensagem 5 vezes.
  3. Utilizando a função wsprintf e gerando um valor aleatório, crie um programa que mostre uma mensagem com o valor decimal e hexadecimal:
Valores


Vocabulário

handle - É o manipulador da janela. Cada janela de nosso sistema tem um handle diferente, é um valor para identificar cada janela.

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


Setembro-2006
Copyright(c) 2005-2006 RVLCN



Recado da vó vovo

Aqui está o código fonte dos exercícios deste tutorial:



mfx broker как вывести средствакосметические интернет магазиныполигон ооо одесса программа qlikviewfb consultпроверить позиции сайтакласс супермаркет