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

Flags e saltos condicionais

Sab

20

Jun

2009


19:05

(7 votos, média 5.00 de 5) 


S (flag de sinal)

Esta flag está setada quando o bit mais significativo (o bit mais à esquerda) do resultado for 1. A posição deste bit depende do tamanho do dado. Num byte, o bit mais significativo é 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). Lembre-se que, em números com sinal, o bit mais significativo indica se o número é negativo ou não.

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

L0: ; DEC ECX ; reduz ecx em um JNS L0 ; 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_ACAO: ; na entrada, al guarda a ação desejada DEC AL ; ver se al contém zero JS >L0 ; se sim, saltar para L0 DEC AL ; ver se al contém um JS >L1 ; se sim, saltar para L1 DEC AL ; ver se al contém dois JS >L2 ; se sim, saltar para L2 DEC AL ; ver se al contém três JS >L3 ; se sim, saltar para L3 DEC AL ; ver se al contém quatro JS >L4 ; se sim, saltar para L4

A flag de sinal também é um jeito muito prático de ver se o bit alto de um registrador está setado ou zerado. Várias instruçõ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 -

Ao checar áreas de memória, pode-se endereçar a memória apenas 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 significativo primeiro e o mais significativo por último. Veja Little Endian. A instrução CMP B[DATA44+7],0 analisa o 8° byte que contém o 64° bit. Este é o sinal, mas apenas 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.

C (flag de carry)

Esta flag é setada quando o resultado da instrução estourou o limite do tamanho do dado, isto é, houve uma transposição ("carry"), o famoso "vai-um". Imagine, por exemplo, que numa instrução de 8 bits o valor 1 é adicionado a 255. O resultado NÃO pode ser 256 por que 255 é o valor máximo que pode estar contido num byte de 8 bits. O resultado será 0, mas a flag de carry será setada. Imagine também que numa instrução o valor 4 é subtraído de 2. Novamente isto faz com que a flag de carry seja setada (tenha valor 1) por que o resultado caiu abaixo de zero, que é o limite inferior do tamanho do dado.

A flag de carry, portanto, indica que uma transposição ou estouro (overflow) ocorreu quando se estava usando números sem sinal. Veja a flag de overflow para encontrar estouros quando são usados números com sinal.

Diferentemente de outras flags, existem instruções criadas para manipular a flag de carry diretamente.

STC ; seta a flag de carry CLC ; zera a flag de carry CMC ; complementa a flag de carry

Como estas instruções são muito simples, a flag de carry é muito útil para levar o resultado de uma função ao seu chamador, por exemplo:

CALCULA2: ; CMP EBX,ESI JZ >.falhou ; salta para falhou se ebx = esi CMP EAX,ESI JZ >.sucesso ; salta para sucesso se eax = esi .falhou STC ; seta a flag de carry para mostrar falha RET .sucesso CLC ; zera a flag de carry para indicar sucesso RET ; CALCULA1: CALL CALCULA2 JC >L40 ; salta para frente para L40 se falhou

As instruções INC e DEC não alteram a flag de carry. As instruções de loop também não. Isto é útil quando se tem um loop que precisa informar seu resultado. Neste caso também podemos usar a flag de carry, como por exemplo:

.loop ; CMP ESI,EDI ; ver se esi é menor que edi (seta carry se for) DEC ECX ; ver se mais loops precisam ser feitos JNZ .loop ; sim RET ; returna com o resultado de cmp esi,edi na flag de carry

Existem algumas instruções que sempre zeram a flag de carry, o que é bom saber para evitar o uso desnecessário da instrução CLC. Estas instruções são AND, OR e TEST. Algumas instruções respondem a um input da flag de carry; outras fazem seu output na flag de carry. A flag de carry é usada principalmente com as instruções de salto condicional JC e JNC, por exemplo:

JC >L10 ; salta para frente para L10 se a carry estiver setada JNC L1 ; salta para trás para L1 se a carry estiver zerada

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

Informações adicionais