8086 Assembler Tutorial for Beginners (Part 7)
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 and 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
|
<<< Previous Part <<<
>>> Next Part >>>
|