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: |
|||
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)
|
|||
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. |
|||
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 | ||
|
| 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. | ||