JUMPING INSTRUCTIONS
Jumping instructions are a unique set. They are the ones that reset the IP
register or the CS:IP register pair. By doing so, they cause an alteration of
the standard next instruction program sequence. The CS:IP register pair is used
by the CPU to keep track of where the next instruction to execute is located.
Standard Jumps
In the standard 80X86 instruction set, there are three different size offset
values that can be used for jumping. They are the 8-bit short jumps, the 16-bit
near jumps, and the 32-bit far jumps. The 32-bit far jumps use two 16-bit words
combined to make up a 20-bit segment:offset address. The following are some
common examples of jump instruction statements.
;goto near procedure next_task
jmp next_task
;goto far procedure next_task
jmpf next_task
;the programmer does not need to use the jmpf mnemonic
; because the compiler will decide and use when needed
load BX with location of code routine
mov BX,offset next_task
jmp [BX] ;goto where BX is pointing
;define data word with address of code routine
next dw offset next_task
jmp [next] ;goto next code routine
Conditional Jumps
A standard conditional jump instruction checks the contents of the Flag
register bits relating to the jump condition. If the associated bits are set
correctly for the jump condition, then the IP register is altered and program
execution continues at the new address indicated by the instruction data. All
conditional jump instructions use an eight-bit jump offset. To the programmer,
this means that you can only jump over a few instructions. You can usually jump
over 30 to 40 instructions; beyond that, you take a chance with compiling
errors.
The following is a list of jump mnemonics with conditions and explanatory
notes:
JB
jump below
This is normally used after a compare to see if the first variable was
logically below the second value using unsigned numbers. Same as JC
instruction.
JBE
jump below or equal
This is normally used after a compare to see if the first variable was
logically below or equal to the second value using unsigned numbers.
JA
jump above
This is normally used after a compare to see if the first variable was
logically above the second value using unsigned numbers.
JAE
jump above equal
This is normally used after a compare to see if the first variable was
logically above or equal to the second value using unsigned numbers.
JC
jump carry
This is normally used to test for a set carry bit in the Flag register after an
addition overflow or subtraction borrow. Same as JB instruction.
JNC
jump no carry
This is normally used to test for a no carry bit in the Flag register after an
addition overflow or subtraction borrow.
JL
jump less
This is normally used after a compare to see if the first variable was less
than the second value using signed numbers.
JLE
jump less or equal
This is normally used after a compare to see if the first variable was less
than or equal to the second value using signed numbers.
JG
jump greater
This is normally used after a compare to see if the first variable was greater
than the second value using signed numbers.
JGE
jump greater or equal
This is normally used after a compare to see if the first variable was greater
than or equal to the second value using signed numbers.
JS
jump sign
This jump is used for testing for a set sign bit in the Flag register. The sign
bit is set during some logical instructions to the same value as the most significant
bit of the data.
JNS
jump no sign
This jump is used for testing for a no sign bit in the Flag register. The sign
bit is set during some logical instructions to be a copy of the most
significant bit of the data.
JO
jump overflow
Branch is taken if the overflow bit in the Flag register is set.
JNO
jump no overflow
Branch is taken if the overflow bit in the Flag register is not set.
JP
jump parity
Jump if the parity bit in the Flag register is set. Same as JPE instruction.
JNP
jump no parity
Jump if the parity bit in the Flag register is not set. Same as JPO
instruction.
JCXZ
jump CX zero
This is a special condition jump for quick testing of the CX register and
branching if zero. This does not test or change any bits in the Flag register.
LOOP
decrement CX and jump if CX not
zero
This is a special condition jump normally used in repeat structures; it
decrements the CX register and jumps if CX is not zero. Note that if you start
with the CX register equal to zero, it loops 65536 times. To prevent this
condition, the JCXZ instruction can be used before looping logic begins.
Real-time programmers note that the logical branch instructions execute
several times faster if the jump is not taken. If possible, write your code
such that the jumps are not taken under most conditions.
Subroutine Jumps
When you call a subroutine, the CPU saves the current contents of the CS:IP
register pair or the IP register in the stack area so that when the subroutine
is finished, it can load the return address from the stack area into the IP
register or CS:IP register pair for continuation at the next instruction after
the call statement.
;call procedure, compiler will decide if near or far
call subroutine
;call using address in memory location
call [indirect]
;call using address in register BX
call [BX]
A subroutine call is terminated by a matching return
instruction. The return instruction is a special case load instruction that
loads the IP register or the CS:IP register pair with data indexed by the stack
pointer.
RET
return
This is a standard near return that only pops the IP register from the stack.
This is to be used by subroutines that are defined as near procedures.
RETF
return far
This is used when a subroutine is defined as a far procedure to return. This
pops the CS:IP register pair off the stack. The reason that all calls are not
far calls is to save memory and speed. Normally, the programmer will just use
the RET mnemonic and let the compiler decide if the return is near or far.
Interrupt Jumps
These are normally used for calling system functions.
INT
interrupt
This is a software interrupt instruction that jumps to a location determined by
the data and a vector table lookup. The interrupt vector table occupies the
first 1,024 bytes of CPU addressing range. There are 256 different interrupt
vectors. Each vector is made up of four bytes of memory locations for interrupt
data to define CS:IP to the start of the interrupt routine.
IRET
interrupt return
This is like a normal RETF except the Flag register is popped as well as the
CS:IP register pair. Note that you can make a far call look like an interrupt
call by pushing the Flags before making the far call.
Because the conditional jumps are only eight bit offsets, problems will
occur if you attempt to jump over more than a few instructions. One standard
way to overcome this problem is to translate the jump as follows:
original
jc carry_overflow
nop
carry_overflow:
translates to
jnc no_overflow
jmp carry_overflow
no_overflow:
carry_overflow:
Table Lookup
Jumping
If you have a data variable and you want to execute one of several different
functional routines depending on the data, then the table lookup jump is a good
method for branching control. There are many ways that table lookup jumping can
be performed, depending on the nature of the data that is used to select a
particular subroutine from a set of possible subroutines.
The following is an example to select a jump given a positive binary integer
between 0 and 32000:
function_table dw function_0_routine
dw function_1_routine
dw function_2_routine
;load BX with number
mov bx,function_code
;point DI to index start of jump table
lea di,function_table
;adjust BX to word offset into jump table
shl bx,1
;perform call to routine indexed in table
call [di+bx]
The following is an example of keyboard table lookup
jumping.
keyboard_key dw 0031
function_key_table dw 0031
dw function_1_routine
table_end:
;
;load AX with function code
mov ax,keyboard_key
;ind
ex jump table with SI
lea si,function_key_table
function_loop:
cmp si,table_end ;?? end of table ??
jae no_find_function ;branch if end
;check for match of function codes
cmp ax,[si]
je function_find ;branch if find code
add si,4 ;else point to next entry
jmp function_loop
function_find:
jmp [si+2]
no_find_function: