CIS-77 Home http://www.c-jump.com/CIS77/CIS77syllabus.htm
Program logic becomes more complex over time.
Checking various conditions may require jumps, that is, transferring control of the execution to places that handle outcomes of specific condition.
A program may need to repeat a sequence of instructions a few times.
Repeating an action until a specific condition is reachedis known as a loop.
Jumps are the most direct way to change program control from one location to another.
Jump instructions work by changing the value of the EIP (Instruction Pointer) register to a target offset.
Jumps can be intersegment, changing the code segment register CS as well as the EIP.
However, this does not happen with flat memory model programming.
The JMP instruction transfers control unconditionally to another instruction.
JMP corresponds to goto statements in high-level languages.
Unconditional jumps skip over code that should not be executed, for example,
; Handle one case label1: . . . jmp done ; Handle second case label2: . . . jmp done . . done:
The assembler determines the smallest encoding possible for the direct unconditional jump.
The assembler determines the correct distance of the jump.
Unconditional jumps to labels are relative jumps.
Each relative jump instruction contains the displacement of the target from the JMP instruction itself.
This displacement is added to the address of the next instruction to find the address of the target.
The displacement is a signed number, positive for a forward reference and negative for a backward reference.
For the relative short version of the instruction, only a single byte of displacement is stored; this is changed to a sign-extended to a doubleword before the addition.
The relative near format includes a 32-bit displacement.
The 8-bit displacement in a relative short jump can serve for a target statement up to 128 bytes before or 127 bytes after the jmp instruction.
(This displacement is measured from the byte following the object code of the jmp itself since at the time an instruction is being executed, EIP logically contains the address of the next instruction to be executed.)
The 32-bit displacement in a relative near jump instruction can serve for a target statement up to 2,147,483,648 bytes before or 2,147,483,647 bytes after the jmp instruction.
There is no difference in the coding for a relative short jump and for a relative near jump.
The assembler uses a short jump if the target is within the small range in order to generate more compact code.
A near jump is used automatically if the target is more than 128 bytes away.
An indirect operand provides a pointer to the target address.
The indirect jump instructions use a 32-bit address for the target rather than a displacement.
However, this address is not encoded in the instruction itself.
Instead, it is either in a register or in a memory doubleword.
For example,
jmp edx
means to jump to the address stored in EDX.
.DATA jump_anywhere DWORD ? .CODE ; jmp eax ; register indirect jump ; jmp quit_program ; unconditional relative jump ; jmp jump_anywhere ; memory indirect jump ; jmp dword ptr [edi] ; jump via pointer to a variable that contains an address quit_program: ;
Sample one: jump_demo.asm
Sample two: jump_table.asm
The most common way to transfer control in assembly language is to use a conditional jump. This is a two-step process:
First, test the condition.
Then, jump if the condition is true.
Continue, if condition is false.
All conditional jumps except two (JCXZ and JECXZ) use the processor flags for their criteria.
There are about 30 conditional-jump instructions.
Each conditional-jump instruction takes a single operand containing the target address.
Instruction | Jumps if |
---|---|
JC / JB / JNAE | Carry flag is set |
JNC / JNB / JAE | Carry flag is clear |
JBE / JNA | Either carry or zero flag is set |
JA / JNBE | Carry and zero flag are clear |
JE / JZ | Zero flag is set |
JNE / JNZ | Zero flag is clear |
JL / JNGE | Sign flag overflow flag |
JGE / JNL | Sign flag = overflow flag |
JLE / JNG | Zero flag is set or sign overflow |
JG / JNLE | Zero flag is clear and sign = overflow |
JS | Sign flag is set |
JNS | Sign flag is clear |
JO | Overflow flag is set |
JNO | Overflow flag is clear |
JP/JPE | Parity flag is set (even parity) |
JNP/JPO | Parity flag is clear (odd parity) |
For example,
; handle overflow condition add ax, bx ; Add two values jo overflow ; If value too large, adjust ; no overflow occurred . overflow: ; handle overflow condition .
JPE (Jump if Parity Even) and JPO (Jump if Parity Odd), are useful only for communications programs.
The processor sets the parity flag if an operation produces a result with an even number of set bits.
A communications program can compare the flag against the parity bit received through the serial port to test for transmission errors.
Parity flag generation with exclusive NOR gates
The CMP instruction is a common way to test for conditional jumps.
CMP instruction is the same as the SUB instruction, except that CMP does not change the destination operand. Both set flags according to the result of the subtraction.
CMP compares signed or unsigned values, but program must choose appropriate conditional jump to reflect the correct type.
Failure to understand the difference between conditional jump instructions may result in program bugs.
Signed Comparisons | Unsigned Comparisons | ||
---|---|---|---|
Instruction | Jump if True | Instruction | Jump if True |
JE | ZF = 1 | JE | ZF = 1 |
JNE | ZF = 0 | JNE | ZF = 0 |
JG/JNLE | ZF = 0 and SF = OF | JA/JNBE | CF = 0 and ZF = 0 |
JLE/JNG | ZF = 1 or SF OF | JBE/JNA | CF = 1 or ZF = 1 |
JL/JNGE | SF OF | JB/JNAE | CF = 1 |
JGE/JNL | SF = OF | JAE/JNB | CF = 0 |
Individual bit settings in a single value can serve as criteria for a conditional jumps.
The TEST instruction sets the zero flag ZF accordingly to specific bit settings of the instruction operands.
The TEST instruction is the same as AND instruction, except that TEST does not change its operand.
The source operand for TEST is often a mask in which the test bits are specified.
The destination operand contains the value to be tested.
TEST sets the zero flag if none of the bits in the destination operand match the mask
For example,
test al, 10100y jz skip1 ; Do something if either bit 2 or 4 are set, or both . skip1:
Note: There is also BT (Bit Test) instruction, which copies a specified bit from the destination operand to the carry flag CF.
A program can test register for zero value by OR instruction:
or bx, bx ; Is BX = 0? jz is_zero ; Jump if so
This code is functionally equivalent to:
cmp bx, 0 ; Is BX = 0? je is_zero ; Jump if so
but produces smaller and faster code, since it does not use an immediate number as an operand. The same technique also lets you test a registers sign bit:
or dx, dx ; Is DX sign bit set? js sign_set ; Jump if so
Note that none of the above OR instructions change original value in the register.
Conditional jumps on the 80386 and 80486 processors cannot reference a label more than 32 kbytes away.
; Jump to target less than 128 bytes away jz target ; If previous operation resulted ; in zero, jump to target
However, if target is too distant, the following sequence is necessary to enable a longer jump. Note this sequence is logically equivalent to the preceding example:
; Jumps to distant targets previously required two steps jnz skip ; If previous operation result is ; NOT zero, jump to "skip" jmp target ; Otherwise, jump to target skip:
By default MASM enables automatic jump expansion facility:
Jump expansion is based on simple workaround:
jne $ + 2 + (length in bytes of the next instruction) jmp NEAR PTR target
See jump_expansion.asm sample program for a complete example.
Two at signs @@ followed by a colon : create an anonymous label:
jge @F . . . @@:
Conditional jump instruction operand can
use @B (back) to jump to the nearest preceding anonymous label
use @F (forward) to jump to the nearest following anonymous label.
Self-study: Loop Instructions