Bahasa Assembler :
Program Flow Control
|
Controlling the program flow is a very important thing, this is where your program
can make decisions according to certain conditions.
Unconditional Jumps
The basic instruction that transfers control to another point in the program is
JMP.
The basic syntax of JMP instruction:
JMP label
To declare a label in your program, just type its name and add
":" to the end, label can be any character combination but it
cannot start with a number, for example here are 3 legal label
definitions:
label1: label2: a:
Label can be declared on a separate line or before
any other instruction, for example:
x1: MOV AX, 1
x2: MOV AX,
2
Here is an example of JMP
instruction:
ORG 100h
MOV AX, 5 ; set AX to 5.
MOV BX, 2 ; set BX to 2.
JMP calc ; go to 'calc'.
back: JMP stop ; go to 'stop'.
calc:
ADD AX, BX ; add BX to AX.
JMP back ; go 'back'.
stop:
RET ; return to operating system.
END ; directive to stop the compiler.
Of
course there is an easier way to calculate the some of two numbers, but
it's still a good example of JMP instruction. As you can see
from this example JMP is able to transfer control both forward
and backward. It can jump anywhere in current code segment (65,535
bytes).
Short Conditional Jumps
Unlike JMP instruction
that does an unconditional jump, there are instructions that do a
conditional jumps (jump only when some conditions are in act). These
instructions are divided in three groups, first group just test single
flag, second compares numbers as signed, and third compares numbers as
unsigned.
Jump instructions that test single flag
Instruction |
Description |
Condition |
Opposite Instruction |
JZ , JE |
Jump if Zero (Equal). |
ZF = 1 |
JNZ, JNE |
JC , JB, JNAE |
Jump if Carry (Below, Not Above Equal). |
CF = 1 |
JNC, JNB, JAE |
JS |
Jump if Sign. |
SF = 1 |
JNS |
JO |
Jump if Overflow. |
OF = 1 |
JNO |
JPE, JP |
Jump if Parity Even. |
PF = 1 |
JPO |
|
JNZ , JNE |
Jump if Not Zero (Not Equal). |
ZF = 0 |
JZ, JE |
JNC , JNB, JAE |
Jump if Not Carry (Not Below, Above Equal). |
CF = 0 |
JC, JB, JNAE |
JNS |
Jump if Not Sign. |
SF = 0 |
JS |
JNO |
Jump if Not Overflow. |
OF = 0 |
JO |
JPO, JNP |
Jump if Parity Odd (No Parity). |
PF = 0 |
JPE, JP |
As you can see there
are some instructions that do that same thing, that's correct, they even
are assembled into the same machine code, so it's good to remember that
when you compile JE instruction - you will get it disassembled
as: JZ. Different names are used to make programs easier to
understand and code.
Jump instructions for signed
numbers
Instruction |
Description |
Condition |
Opposite Instruction |
JE , JZ |
Jump if Equal (=). Jump if Zero. |
ZF = 1 |
JNE, JNZ |
JNE , JNZ |
Jump if Not Equal (<>). Jump
if Not Zero. |
ZF = 0 |
JE, JZ |
JG , JNLE |
Jump if Greater (>). Jump if Not
Less or Equal (not <=). |
ZF = 0 and SF = OF |
JNG, JLE |
JL , JNGE |
Jump if Less (<). Jump if Not
Greater or Equal (not
>=). |
SF <> OF |
JNL, JGE |
JGE , JNL |
Jump if Greater or Equal (>=). Jump if Not Less (not <). |
SF = OF |
JNGE, JL |
JLE , JNG |
Jump if Less or Equal (<=). Jump if Not Greater
(not >). |
ZF = 1 or SF <> OF |
JNLE, JG |
<> - sign means not equal.
Jump instructions for unsigned numbers
Instruction |
Description |
Condition |
Opposite Instruction |
JE , JZ |
Jump if Equal (=). Jump if Zero. |
ZF = 1 |
JNE, JNZ |
JNE , JNZ |
Jump if Not Equal (<>). Jump
if Not Zero. |
ZF = 0 |
JE, JZ |
JA , JNBE |
Jump if Above (>). Jump if Not
Below or Equal (not <=). |
CF = 0 and ZF = 0 |
JNA, JBE |
JB , JNAE, JC |
Jump if Below (<). Jump if Not
Above or Equal (not
>=). Jump if Carry. |
CF = 1 |
JNB, JAE, JNC |
JAE , JNB, JNC |
Jump if Above or Equal (>=). Jump
if Not Below (not
<). Jump if Not Carry. |
CF = 0 |
JNAE, JB |
JBE , JNA |
Jump if Below or Equal (<=). Jump
if Not Above (not >). |
CF = 1 or ZF = 1 |
JNBE, JA |
Generally, when it is required to compare numeric values CMP instruction is
used (it does the same as SUB (subtract) instruction, but does not keep
the result, just affects the flags).
The logic is very simple, for example: it's required to compare 5
Band 2,
5 - 2 = 3
the result is not zero (Zero Flag is set to 0).
Another example: it's required to compare 7 and 7,
7 - 7 = 0 the result is zero! (Zero Flag is set to 1 and
JZ or JE will do the jump).
Here is an example of CMP instruction and conditional jump:
include emu8086.inc
ORG 100h
MOV AL, 25 ; set AL to 25.
MOV BL, 10 ; set BL to 10.
CMP AL, BL ; compare AL - BL.
JE equal ; jump if AL = BL (ZF = 1).
PUTC 'N' ; if it gets here, then AL <> BL,
JMP stop ; so print 'N', and jump to stop.
equal: ; if gets here,
PUTC 'Y' ; then AL = BL, so print 'Y'.
stop:
RET ; gets here no matter what.
END
Try the above example with different numbers for AL and BL, open flags
by clicking on [FLAGS] button, use [Single Step] and see what happens,
don't forget to recompile and reload after every change (use F5 shortcut).
All conditional jumps have one big limitation, unlike JMP instruction they
can only jump 127 bytes forward and 128 bytes backward (note that
most instructions are assembled into 3 or more bytes).
We can easily avoid this limitation using a cute trick:
- Get a opposite conditional jump instruction from the table above, make it jump
to label_x.
- Use JMP instruction to jump to desired location.
- Define label_x: just after the JMP instruction.
label_x: - can be any valid label name.
Here is an example:
include emu8086.inc
ORG 100h
MOV AL, 25 ; set AL to 25.
MOV BL, 10 ; set BL to 10.
CMP AL, BL ; compare AL - BL.
JNE not_equal ; jump if AL <> BL (ZF = 0).
JMP equal
not_equal:
; let's assume that here we
; have a code that is assembled
; to more then 127 bytes...
PUTC 'N' ; if it gets here, then AL <> BL,
JMP stop ; so print 'N', and jump to stop.
equal: ; if gets here,
PUTC 'Y' ; then AL = BL, so print 'Y'.
stop:
RET ; gets here no matter what.
END
Another, yet rarely used method is providing an immediate value instead of a label.
When immediate value starts with a '$' character relative jump is performed, otherwise
compiler calculates instruction that jumps directly to given offset. For example:
ORG 100h
; unconditional jump forward:
; skip over next 2 bytes,
JMP $2
a DB 3 ; 1 byte.
b DB 4 ; 1 byte.
; JCC jump back 7 bytes:
; (JMP takes 2 bytes itself)
MOV BL,9
DEC BL ; 2 bytes.
CMP BL, 0 ; 3 bytes.
JNE $-7
RET
END
|