FLAGS E SALTOS CONDICIONAIS I
Silício ReversooicìliS ©
Assembly Intermediário
TEXTOS ACESSÓRIOS
Notice: Undefined variable: subtitulo in /home/numaboa.com.br/public_html/informatica/oiciliS/assembler/head.php on line 10

(ver 1.1 de 02.08.03)

A tradução literal de "flag" é bandeira. Não é à toa que as "flags" do processador receberam este nome: funcionam como sinalizadores. Vou manter o nome flag e não usar algum tipo de tradução porque esta denominação já foi incorporada ao "computês" do Brasil e não vale a pena discutir ou mudar um hábito.

As flags são apenas um bit de memória e se localizam dentro do processador. Como cada flag é apenas um bit, num dado momento elas só podem ser 1 ou 0 ("setada" ou "zerada"). Existem seis flags usadas para indicar o resultado de certas instruções. Algumas instruções como CMP, TEST e BT não fazem outra coisa a não ser alterar algumas destas flags. Outras instruções realizam outras operações além de alterar algumas das flags. Algumas instruções simplesmente não alteram as flags. Na descrição dos mneumônicos das instruções geralmente são citadas as flags que são alteradas.

Um uso comum das flags é o de desviar a execução para um ponto em particular do código usando instruções de salto condicinal. Estas instruções farão o salto ou não dependendo do estado de uma ou mais flags. Apenas cinco das flags podem ser usadas deste modo - zero, sinal, carry, overflow e paridade. A sexta flag (carry auxiliar) e a sétima flag (flag de direção) são lidas por outro tipo de instrução. A seguir estão informações adicionais a respeito das cinco flags que podem ser usadas por saltos condicionais:

Z (flag zero)

Está setada (possui valor 1) se o resultado for zero. Se, depois de uma instrução aritmética, o número deixado no registrador ou na área de memória objeto da instrução for zero então a flag é setada. Geralmente só é preciso fazer uma simples comparação de dois valores sem alterá-los. Neste caso, pode-se usar a instrução CMP. CMP imita um SUB sem alterar os valores passados como operandos. Por exemplo:

CMP EAX,33h      ;flag zero = 1 se eax = 33h, mas não altera eax
SUB EAX,33h      ;flag zero = 1 se eax = 33h (eax diminui em 33h)
CMP EAX,EDX      ;flag zero = 1 se eax = edx
CMP EAX,[VALOR]  ;flag zero = 1 se eax = o número em VALOR

A flag zero também pode ser usada para mostrar o resultado de uma contagem crescente ou decrescente, por exemplo:

DEC EAX		;flag zero = 1 se eax for zero depois da instrução.
		;flag zero = 0 se eax for diferente de zero.
INC EAX		;flag zero = 1 se eax for zero depois da instrução.
		;flag zero = 0 se eax for diferente de zero.

A flag zero também pode ser usada para controlar a repetição de instruções de string, isto é, LODS, STOS e MOVS:

REPZ     ;repete a instrução string enquanto a flag zero
		estiver setada
REPNZ    ;repete a instrução string enquanto a flag zero
		estiver zerada

O retorno de uma API no Windows com frequência indica que a API falhou. Portanto, também é preciso checar com frequência a ocorrência deste evento. Testando registradores você pode usar estas alternativas:

CMP EAX,0        ;ver se o número em eax é zero
		 ;(flag zero está setada)
OR EAX,EAX       ;faz a mesma coisa mas usa 2 opcodes ao invés de 3
TEST EAX,EAX     ;faz a mesma coisa e também só usa 2 opcodes

As versões de 16 e 8 bits das instruções testam apenas os primeiros 16 ou 8 bits do registrador ou da área de memória. Por exemplo:

CMP W[JOAO],0	;ver se os primeiros 16 bits da memória marcada
		;como JOAO são zero
CMP B[MARIA],0	;ver se os primeiros 8 bits da memória marcada
		;como MARIA são zero
OR DX,DX	;ver se o registrador dx é zero (16 bits)
TEST DH,DH	;ver se o registrador dh é zero (8 bits)
SUB B[VALOR],2	;reduz os 8 bits em VALOR em 2
		;(flag zero setada se for zero)
DEC SI		;flag zero setada quando si for zero (16 bits)
INC B[CONTA]	;flag zero setada quando os 8 bits de CONTA são zero

Já que as flags são muito úteis para indicar se houve retorno com sucesso ou não de uma rotina, algumas vezes será preciso setá-las diretamente. Para setar a flag zero pode-se usar:

CMP EAX,EAX      ;seta a flag zero sem alterar eax
SUB EAX,EAX      ;seta a flag zero fazendo eax = 0
CMP EAX,EDX      ;quando precisam ser diferentes, zera a flag zero
OR EAX,EAX       ;quando eax não pode ser zero, zera a flag zero
TEST EAX,EAX     ;mesmo efeito que OR EAX,EAX

Quando usada com TEST, a flag zero será setada se o bit testado for zero.

MOV ECX,1        ;põe valor 1 em ecx
TEST ECX,1       ;a flag zero não é setada
CMP ECX,1        ;a flag zero é setada
MOV EDX,0      
TEST EDX,1       ;a flag zero é setada
CMP EDX,1        ;a flag zero não é setada
MOV EBX,-1
TEST EBX,-1      ;testa todos os 32 bits (flag zero zerada)
CMP EBX,-1       ;ver se ebx é -1 (flag zero setada)

A flag zero é usada principalmente com as instruções de salto condicional JZ e JNZ, por exemplo:

JZ >L10          ;salta para frente para L10 se flag zero = 1
JNZ L1           ;salta para trás para L1 se flag zero = 0

A flag zero também é utilizada com as instruções de salto condicional JA ("jump if above" - salte se acima), JB ("jump if below" - salte se abaixo) e instruções semelhantes.

Também pode ser usada em loops utilizando instruções especiais ou utilizando apenas a flag, por exemplo:

L1:
...              ;outro código aqui
CMP EDX,EAX
LOOPZ L1         ;decrementa ecx, loop continua até que ecx = 0
                 ;ou até que edx = eax (quando flag zero = 1)
;*******
L1:
...              ;outro código aqui
CMP EDX,EAX
LOOPNZ L1        ;decrementa ecx, loop continua até que ecx = 0
                 ;ou até que edx faz not = eax (quando flag zero = 0)
;*******
L1:
...              ;outro código aqui
CMP EDX,EAX
JZ >L10          ;salte para fora do loop quando edx=eax
		 ;(flag zero = 1)
LOOP L1          ;decrementa ecx, loop continua até que ecx = 0
L10:
;*******
L1:
...              ;outro código aqui
CMP EDX,EAX
JNZ L1           ;loop continua até que edx = eax (flag zero = 1)
S (flag de sinal)

Está setada se o bit mais significante (o bit mais à esquerda) do resultado for 1. A posição deste bit depende do tamanho do dado. Num byte, o bit mais significante é o bit 7 (8° bit dos bits 0 a 7); num word é o bit 15 (16° bit dos bits 0 a 15) e num dword é o bit 31 (32° bit dos bits 0 a 31). Este bit estará setado se o resultado da instrução for 80h ou mais (para um byte), 8000h ou mais (para um word) ou 80000000h ou mais (para um dword). Note que em números com sinal, o bit mais significante indica se o número é negativo ou não.

A flag de sinal é alterada por INC e DEC, que não alteram a flag de carry. Por isso pode ser muito útil testar a flag de sinal em loops. Por exemplo:

L0:
;
DEC ECX          ;reduz ecx em um
JNS L0           ;loop de volta para L0 se ecx ainda não for -1

Seu uso também é muito conveniente em funções de multi-ação, por exemplo:

MULTI_ACTION:    ;na entrada, al guarda a ação desejada
DEC AL           ;ver se al contém zero
JS >L0           ;sim
DEC AL           ;ver se al contém um
JS >L1           ;sim
DEC AL           ;ver se al contém dois
JS >L2           ;sim
DEC AL           ;ver se al contém três
JS >L3           ;sim
DEC AL           ;ver se al contém quatro
JS >L4           ;sim

Usando a flag de sinal é um jeito conveniente de ver se o bit alto de um registrador está setado ou zerado. Várias insruções setam a flag sem alterar o registrador, por exemplo:

OR EDX,EDX       ;seta a flag de sinal se o bit alto de edx
		 ;estiver setado
CMP EDX,EDX      ;   - idem -
TEST EDX,EDX     ;   - idem -
OR CL,CL         ;seta a flag de sinal se o bit alto de cl
		 ;estiver setado
CMP CL,CL        ;   - idem -
TEST CL,CL       ;   - idem -

Entretanto, ao checar áreas de memória, pode-se apenas endereçar a memória uma vez por instrução. Desta forma, é preciso usar CMP, como por exemplo:

CMP B[DATA44],0		;seta a flag de sinal se o 8° bit de
			;DATA44 estiver setado
CMP W[DATA44],0		;seta a flag de sinal se o 16° bit de
			;DATA44 estiver setado
CMP D[DATA44],0		;seta a flag de sinal se o 32° bit de
			;DATA44 estiver setado
CMP B[DATA44+7],0	;seta a flag de sinal se o 64° bit de
			;DATA44 estiver setado
CMP B[DATA44+9],0	;seta a flag de sinal se o 80° bit de
			;DATA44 estiver setado

Observe que a posição do bit mais alto na área de memória chamada de DATA44, usada nestas instruções, depende do tamanho do dado usado na instrução. Isto é porque dados em áreas de memória são armazenados com os bytes em ordem reversa, ou seja, o byte menos significante primeiro e o mais significante por último. Veja A ordem reversa de armazenamento. A instrução CMP B[DATA44+7],0 analisa o 8° byte que contém o 64° bit. Este é o sinal, mas para um dado de 64 bits de tamanho.

A flag de sinal é usada principalmente com as instruções de salto condicional JS e JNS, por exemplo:

JS >L10          ;salta para frente para L10 se a flag de sinal = 1
JNS L1           ;salta para trás para L1 se a flag de sinal = 0

A flag de sinal também é usada com as instruções de salto condicional JG ("jump if greater-than" - salte se maior que), JNG ("jump if not greater-than" - salte se não maior que) e semelhantes.




ESTÁ DANDO BANDEIRA...

Esta é a primeira parte da tradução do texto de Jeremy Gordon sobre saltos condicionais e flags. A continuação do texto você encontra em Flags e Saltos Condicionais II, onde são abordadas as flags de carry, de overflow e de paridade.



Localizador

| AAAA | Página Inicial | Mapa do Site | Novidades | Busca | Indique esta página | Mestre da Teia | Voltar |
| Localizador || @ Info NumaBoa > oicìliS > Assembly > Textos > Flags e Saltos Condicionais
Créditos: vovó Vicki

webdesign sobMedida by vickiSoft - /informatica/oiciliS/assembler/textos/flagJmp1.php (10.04.03) versão 1.1 de 02.08.03
Licença Creative Commons 1998-2006 Aldeia NumaBoa
Exceto onde especificamente declarado, todo material deste site é disponibilizado de acordo com a Licença Creative Commons.