7.5 The Conditional Jump Instructions


7.5 The Conditional Jump Instructions

Although the jmp instruction provides transfer of control, it does not allow you to make any serious decisions. The 80x86's conditional jump instructions handle this task. The conditional jump instructions are the basic tool for creating loops and other conditionally executable statements like the if..endif statement.

The conditional jumps test one or more flags to see if they match some particular pattern (just like the setcc instructions). If the flag settings match, the instruction transfers to the target location. If the match fails, the CPU ignores the conditional jump and execution continues with the next instruction. Some conditional jump instructions simply test the setting of the sign, carry, overflow, and zero flags. For example, after the execution of an shl instruction, you could test the carry flag to determine if the shl shifted a one out of the H.O. bit of its operand. Likewise, you could test the zero flag after a test instruction to see if any specified bits were one. Most of the time, however, you will probably execute a conditional jump after a cmp instruction. The cmp instruction sets the flags so that you can test for less than, greater than, equality, and so on.

The conditional jmp instructions take the following form:

 Jcc label; 

The "cc" in Jcc indicates that you must substitute some character sequence that specifies the type of condition to test. These are the same characters the setccinstruction uses. For example, "js" stands for jump if the sign flag is set. A typical js instruction looks like this:

 js ValueIsNegative; 

In this example, the js instruction transfers control to the ValueIsNegative statement label if the sign flag is currently set; control falls through to the next instruction following the js instruction if the sign flag is clear.

Unlike the unconditional jmp instruction, the conditional jump instructions do not provide an indirect form. The only form they allow is a branch to a statement label in your program. Conditional jump instructions have a restriction that the target label must be within 32,768 bytes of the jump instruction. However, because this generally corresponds to somewhere between 8,000 and 32,000 machine instructions, it is unlikely you will ever encounter this restriction.

Note: Intel's documentation defines various synonyms or instruction aliases for many conditional jump instructions. Tables 7-1, 7-2, and 7-3 list all the aliases for a particular instruction. These tables also list out the opposite branches. You'll soon see the purpose of the opposite branches.

Table 7-1: JCC Instructions That Test Flags

Instruction

Description

Condition

Aliases

Opposite


JC

Jump if carry

Carry = 1

JB, JNAE

JNC

JNC

Jump if no Carry

Carry = 0

JNB, JAE

JC

JZ

Jump if zero

Zero = 1

JE

JNZ

JNZ

Jump if not zero

Zero = 0

JNE

JZ

JS

Jump if sign

Sign = 1

JNS

JNS

Jump if no sign

Sign = 0

JS

JO

Jump if overflow

Ovrflw = 1

JNO

JNO

Jump if no overflow

Ovrflw = 0

JO

JP

Jump if parity

Parity = 1

JPE

JNP

JPE

Jump if parity even

Parity = 1

JP

JPO

JNP

Jump if no parity

Parity = 0

JPO

JP

JPO

Jump if parity odd

Parity = 0

JNP

JPE

Table 7-2: JCC Instructions for Unsigned Comparisons

Instruction

Description

Condition

Aliases

Opposites


JA

Jump if above (>)

Carry=0, Zero=0

JNBE

JNA

JNBE

Jump if not below or equal (not <=)

Carry=0, Zero=0

JA

JBE

JAE

Jump if above or equal (>=)

Carry = 0

JNC, JNB

JNAE

JNB

Jump if not below (not <)

Carry = 0

JNC, JAE

JB

JB

Jump if below (<)

Carry = 1

JC, JNAE

JNB

JNAE

Jump if not above or equal (not >=)

Carry = 1

JC, JB

JAE

JBE

Jump if below or equal (<=)

Carry = 1 ro Zero = 1

JNA

JNBE

JNA

Jump if not above (not >)

Carry = 1 or Zero = 1

JBE

JA

JE

Jump if equal (=)

Zero = 1

JZ

JNE

JNE

Jump if not equal (:)

Zero = 0

JNZ

JE

Table 7-3: JCC Instructions for Signed Comparisons

Instruction

Description

Condition

Aliases

Opposite


JG

Jump if greater (>)

Sign = Ovrflw or Zero=0

JNLE

JNG

JNLE

Jump if not less than or equal (not <=)

Sign = Ovrflw or Zero=0

JG

JLE

JGE

Jump if greater than or equal (>=)

Sign = Ovrflw

JNL

JGE

JNL

Jump if not less than (not <)

Sign = Ovrflw

JGE

JL

JL

Jump if less than (<)

Sign <> Ovrflw

JNGE

JNL

JNGE

Jump if not greater or equal (not >=)

Sign <> Ovrflw

JL

JGE

JLE

Jump if less than or equal (<=)

Sign <> Ovrflw or Zero = 1

JNG

JNLE

JNG

Jump if not greater than (not >)

Sign <> Ovrflw or Zero = 1

JLE

JG

JE

Jump if equal(=)

Zero = 1

JZ

JNE

JNE

Jump if not equal (|)

Zero = 0

JNZ

JE

One brief comment about the "opposites" column is in order. In many instances you will need to be able to generate the opposite of a specific branch instructions (examples appear later in this chapter). With only two exceptions, a very simple rule completely describes how to generate an opposite branch:

  • If the second letter of the Jcc instruction is not an "n", insert an "n" after the "j". E.g., je becomes jne and jl becomes jnl.

  • If the second letter of the Jcc instruction is an "n", then remove that "n" from the instruction. E.g., jng becomes jg and jne becomes je.

The two exceptions to this rule are jpe (jump if parity is even) and jpo (jump if parity is odd). These exceptions cause few problems because (a) you'll hardly ever need to test the parity flag, and (b) you can use the aliases jp and jnp synonyms for jpe and jpo. The "N/No N" rule applies to jp and jnp.

Though you know that jge is the opposite of jl, get in the habit of using jnl rather than jge as the opposite jump instruction for jl. It's too easy in an important situation to start thinking "greater is the opposite of less" and substitute jg instead. You can avoid this confusion by always using the "N/No N" rule.

The 80x86 conditional jump instructions give you the ability to split program flow into one of two paths depending upon some condition. Suppose you want to increment the AX register if BX is equal to CX. You can accomplish this with the following code:

           cmp( bx, cx );           jne SkipStmts;           inc( ax ); SkipStmts: 

The trick is to use the opposite branch to skip over the instructions you want to execute if the condition is true. Always use the "opposite branch (N/no N)" rule given earlier to select the opposite branch.

You can also use the conditional jump instructions to synthesize loops. For example, the following code sequence reads a sequence of characters from the user and stores each character in successive elements of an array until the user presses the ENTER key (carriage return):

          mov( 0, edi ); RdLnLoop:          stdin.getc();             // Read a character into the AL register.          mov( al, Input[ edi ] );  // Store away the character.          inc( edi );               // Move on to the next character.          cmp( al, stdio.cr );      // See if the user pressed Enter.          jne RdLnLoop; 

Like the setcc instructions, the conditional jump instructions come in two basic categories — those that test specific processor flags (e.g., jz, jc, jno) and those that test some condition ( less than, greater than, and so on). When testing a condition, the conditional jump instructions almost always follow a cmp instruction. The cmp instruction sets the flags so you can use a ja, jae, jb, jbe, je, or jne instruction to test for unsigned less than, less than or equal, equality, inequality, greater than, or greater than or equal. Simultaneously, the cmp instruction sets the flags so you can also do a signed comparison using the jl, jle, je, jne, jg, and jge instructions.

The conditional jump instructions only test flags; they do not affect any of the 80x86 flags.




The Art of Assembly Language
The Art of Assembly Language
ISBN: 1593272073
EAN: 2147483647
Year: 2005
Pages: 246
Authors: Randall Hyde

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net