Jumps in assembler programs are either conditional or unconditional. The assembler executes conditional jumps only when the jump condition is true. You use the JMP instruction to jump unconditionally to a specified address. Its single operand contains the target address, which can be short, near, or far.
Unconditional jumps are often used to skip over code that should not be executed, as shown in this example.
; Handle one case
label1: .
.
.
jmp continue
; Handle second case
label2: .
.
.
jmp continue
.
.
.
continue:
The distance of the target from the jump instruction and the size of the operand determine the assembler's encoding of the instruction. The larger the distance, the more bytes the assembler uses to code the instruction. In previous versions of MASM, unconditional NEAR jumps sometimes generate inefficient code. Unspecified FAR jumps result in phase errors.
Beginning with MASM 6.0, the assembler determines the smallest encoding possible for the direct unconditional jump. You do not specify a distance operator, so you do not have to determine the correct distance of the jump. If you do specify a distance, however, and it is too short, the assembler generates an error. A specified distance that is too long causes a less efficient jump to be generated than the assembler would generate if the distance had not been specified.
MASM 6.0 optimizes jumps if the following conditions are met:
You do not specify SHORT, NEAR, FAR, NEAR16, NEAR32, FAR16, FAR32, or PROC as the distance of the target.
The target of the jump is not external and is in the same segment as the jump instruction. If the target is in a different segment (but in the same group), it is treated as if external.
If these two conditions are met, MASM uses the instruction, distance, and size of the operand to determine how best to optimize the encoding for the jump. No syntax changes are necessary.
NOTE:
This information about jump optimizing also applies to conditional jumps on the 80386/486.
Indirect operands specify a register or data memory location that holds the address of the jump's destination. Indirect operands differ from the operands of direct jumps by being a memory expression instead of an immediate expression. For indirect jumps, you can specify the encoding for the instruction by giving the size (WORD, DWORD, or FWORD) attributes for the operand.
The default rules are based on the .MODEL and the default segment size.
jmp [bx] ; Uses .MODEL and segment size
; defaults
jmp WORD PTR [bx] ; A NEAR16 indirect call
If the indirect operand is a register, the jump is always a NEAR16 jump for a 16-bit register, and FAR32 for a 32-bit register:
jmp bx ; NEAR16 jump
jmp ebx ; FAR32 jump
A DWORD indirect operand, however, is an ambiguous case:
jmp DWORD PTR [var] ; A NEAR32 jump in a 32-bit segment;
; a FAR16 jump in a 16-bit segment
In this case, you must define a type with TYPEDEF to specify the indirect operand.
NFP TYPEDEF PTR NEAR32
FFP TYPEDEF PTR FAR16
jmp NFP PTR [var] ; NEAR32 indirect jump
jmp FFP PTR [var] ; FAR16 indirect jump
You can use an unconditional jump as a form of conditional jump by specifying the address in a register or indirect memory operand. Also, you can use indirect memory operands to construct jump tables that work like C switch statements,
Pascal CASE statements, or Basic ON GOTO, ON GOSUB, or SELECT CASE statements, as shown in this example:
NPVOID TYPEDEF NEAR PTR VOID
.DATA
ctl_tbl NPVOID extended, ; Null key (extended code)
ctrla, ; Address of CONTROL-A key routine
ctrlb ; Address of CONTROL-B key routine
.CODE
.
.
.
mov ah, 8h ; Get a key
int 21h
cbw ; Stretch AL into AX
mov bx, ax ; Copy
shl bx, 1 ; Convert to address
jmp ctl_tbl[bx] ; Jump to key routine
extended:
mov ah, 8h ; Get second key of extended key
int 21h
. ; Use another jump table
. ; for extended keys
.
jmp next
ctrla: . ; CONTROL-A code here
.
.
jmp next
ctrlb: . ; CONTROL-B code here
.
.
jmp next
.
.
next: . ; Continue
In this example, the indirect memory operands point to addresses of routines for handling different keystrokes.