UNIT I
8086 INTRODUCTION
1.1) An over view of 8085
1.2) Architecture of 8086 Microprocessor
1.3) Special functions of General purpose registers
1.4) 8086 flag register and function of 8086 Flags
1.5) Addressing modes of 8086
1.6) Instruction set of 8086
1.7) Assembler directives
1.8) Procedures, and macros
MPI
MPI
3) 8085 Registers:
The 8085 have six general-purpose registers to store 8-bit data during program
execution.
MPI
MPI
If the result of arithmetic and logical operation is zero, then zero flag is set
otherwise it is reset.
C) Auxiliary Carry Flag (AC):
If D3 generates any carry when doing any arithmetic and logical operation, this
flag is set. Otherwise it is reset.
D) Parity Flag (P):
If the result of arithmetic and logical operation contains even number of 1's then
this flag will be set and if it is odd number of 1's it will be reset.
E) Carry Flag (CY):
If any arithmetic and logical operation result any carry then carry flag is set
otherwise it is reset.
iii) Arithmetic and Logic Unit (ALU):
It is used to perform the arithmetic operations like addition, subtraction,
multiplication, division, increment and decrement and logical operations like
AND, OR and EX-OR.
It receives the data from accumulator and registers. According to the result it set
or reset the flags.
iv) Program Counter (PC):
This 16-bit register is used to sequencing the execution of instructions.
It is a memory pointer. Memory locations have 16-bit addresses, and that is why
this is a 16-bit register.
The function of the program counter is to point to the memory address of the next
instruction to be executed.
When an opcode is being fetched, the program counter is incremented by one to
point to the next memory location.
v) Stack Pointer (Sp)
The stack pointer is also a 16-bit register used as a memory pointer.
It points to a memory location in R/W memory, called the stack.
The beginning of the stack is defined by loading a 16-bit address in the stack
pointer (register).
vi) Temporary Register:
It is used to hold the data during the arithmetic and logical operations.
vii) Instruction Register:
When an instruction is fetched from the memory, it is loaded in the instruction
Register.
viii) Instruction Decoder:
It gets the instruction from the instruction register and decodes the instruction.
MPI
It has three control signals ALE, RD (Active low) and WR (Active low) and three
status signals IO/M (Active low), S0 and S1.
ALE is used for provide control signal to synchronize the components of
miroprocessor and timing for instruction to perform the operation.
RD (Active low) and WR (Active low) are used to indicate whether the operation
is reading the data from memory or writing the data into memory respectively.
IO/M (Active low) is used to indicate whether the operation is belongs to the
memory or peripherals.
MPI
Types of Interrupts:
It supports two types of interrupts.
i) Software
ii) Hardware
i) Software interrupts:
The software interrupts are program instructions.
These instructions are inserted at desired locations in a program.
The 8085 has eight software interrupts from RST 0 to RST 7.
The vector address for these interrupts can be calculated as follows.
Interrupt number * 8 = vector address
EX: - For RST 5, 5 * 8 = 40 = 28H
Vector address for interrupt RST 5 is 0028H
The Table shows the vector addresses of all interrupts.
MPI
The RST 6.5 has the third priority whereas RST 5.5 has the fourth priority.
(4) INTR:
INTR is a maskable interrupt. It is disabled by, 1.DI, SIM instruction 2.System or
processor reset. 3. after reorganization of interrupt.
a)
It is enabled by EI instruction.
MPI
EDGE/LEVEL
SENSITIVE
EDGE&LEVEL
EDGE
LEVEL
LEVEL
LEVEL
VECTORED/NON
VECTORED
VECTORED
VECTORED
VECTORED
VECTORED
NON VECTORED
Vcc
+ 5 volt power supply
MPI
Vss
Ground
X1, X2: Crystal or R/C network or LC network connections to set the frequency
of internal clock generator.
The frequency is internally divided by two. Since the basic operating timing
frequency is 3 MHz, a 6 MHz crystal is connected externally.
CLK (output)-Clock Output is used as the system clock for peripheral and devices
interfaced with the microprocessor.
ii)
Address Bus:
A8 - A15 lines.
It carries the most significant 8 bits of the memory address or the 8 bits of the I/O
address.
iii)
Multiplexed Address / Data Bus:
These multiplexed set of lines used to carry the lower order 8 bit address as well
as data bus.
During the opcode fetch operation, in the first clock cycle, the lines deliver the
lower order address A0 - A7.
In the subsequent IO / memory, read / write clock cycle the lines are used as data
bus.The CPU may read or write out data through these lines.
Fig (a) - Pin Diagram of 8085 & Fig (b) - logical schematic of Pin diagram.
10
MPI
This signal helps to capture the lower order address presented on the multiplexed
address / data bus.
This indicates that the selected memory location or I/O device is to be read and
that the data bus is ready for accepting data from the memory or I/O device.
This indicates that the data on the data bus is to be written into the selected
memory location or I/O device.
This status signal indicates that the read / write operation relates to whether the
memory or I/O device. It goes high to indicate an I/O operation. It goes low for memory
operations.
Status Signals:
11
MPI
3 output states are high & low states and additionally a high impedance state.
When enable E is high the gate is enabled and the output Q can be 1 or 0 (if A is
0, Q is 1, otherwise Q is 0).
However, when E is low the gate is disabled and the output Q enters into a high
impedance state.
12
MPI
13
MPI
It is a 16-bit p.
8086 has a 20 bit address bus can access up to 220 memory locations (1 MB).
It can support up to 64K I/O ports.
It provides 14, 16 -bit registers.
It has multiplexed address and data bus AD0- AD15 and A16 A19.
It requires single phase clock with 33% duty cycle to provide internal timing.
8086 is designed to operate in two modes, Minimum and Maximum.
It can prefetches upto 6 instruction bytes from memory and queues them in order
to speed up instruction execution.
It requires +5V power supply.
A 40 pin dual in line package.
8086 has two blocks BIU and EU.
The BIU performs all bus operations such as instruction fetching, reading and
writing operands for memory and calculating the addresses of the memory
operands. The instruction bytes are transferred to the instruction queue.
EU executes instructions from the instruction system byte queue.
Both units operate asynchronously to give the 8086 an overlapping instruction
fetch and execution mechanism which is called as Pipelining. This results in
efficient use of the system bus and system performance.
BIU contains Instruction queue, Segment registers, Instruction pointer, and
Address adder.
EU contains Control circuitry, Instruction decoder, ALU, Pointer and Index
register, Flag register.
14
MPI
These prefetching instructions are held in its FIFO queue. With its 16 bit data bus,
the BIU fetches two instruction bytes in a single memory cycle.
After a byte is loaded at the input end of the queue, it automatically shifts up
through the FIFO to the empty location nearest the output.
The EU accesses the queue from the output end. It reads one instruction byte after
the other from the output of the queue. If the queue is full and the EU is not requesting
access to operand in memory.
These intervals of no bus activity, which may occur between bus cycles, are
known as idle state.
If the BIU is already in the process of fetching an instruction when the EU request
it to read or write operands from memory or I/O, the BIU first completes the
instruction fetch bus cycle before initiating the operand read / write cycle.
The BIU also contains a dedicated adder which is used to generate the 20bit
physical address that is output on the address bus. This address is formed med by
combining the current contents of the code segment CS register and the current
contents of the instruction pointer IP register.
The BIU is also responsible for generating bus control signals such as those for
15
MPI
The Execution unit is responsible for decoding and executing all instructions.
The EU extracts instructions from the top of the queue in the BIU, decodes them,
generates operands if necessary, passes them to the BIU and requests it to perform
the read or write bys cycles to memory or I/O and perform the operation specified
by the instruction on the operands.
During the execution of the instruction, the EU tests the status and control flags
and updates them based on the results of executing the instruction.
If the queue is empty, the EU waits for the next instruction byte to be fetched and
shifted to top of the queue.
When the EU executes a branch or jump instruction, it transfers control to a
location corresponding to another set of sequential instructions.
Whenever this happens, the BIU automatically resets the queue and then begins to
fetch instructions from this new location.
16
MPI
17
MPI
Source Index (SI) is a 16-bit register. SI is used for indexed, based indexed and
register indirect addressing, as well as a source data address in string
manipulation instructions.
Destination Index (DI) is a 16-bit register. DI is used for indexed, based indexed
and register indirect addressing, as well as a destination data address in string
manipulation instructions.
The si and di registers (Source Index and Destination Index) have some special
purposes as well. You may use these registers as pointers (much like the bx
register) to indirectly access memory. You'll also use these registers with the 8086
string instructions when processing character strings.
The bp register (Base Pointer) is similar to the bx register. You'll generally use
this register to access parameters and local variables in a procedure.
The sp register (Stack Pointer) has a very special purpose - it maintains the
program stack. Normally, you would not use this register for arithmetic
computations. The proper operation of most programs depends upon the careful
use of this register.
SEGMENTATION:
Since address registers and address operands are only 16 bits they can only
address 64k bytes.
In order to address the 20-bit address range of the 8086, physical addresses (those
that are put on the address bus) are always formed by adding the values of one of
the instruction are executed? The use of segment registers reduces the size of
pointers to 16 bits.
This reduces the code size but also restricts the addressing range of a pointer to
64k bytes. Performing address arithmetic within data structures larger than 64k is
awkward. This is the biggest drawback of the 8086 architecture. We will restrict
ourselves to short programs where all of the code, data and stack are placed into
the same 64k segment (i.e. CS=DS=SS).
Most of the registers contain data/instruction offsets within 64 KB memory
segment.
There are four different 64 KB segments for instructions, stack, data and extra
data.
To specify where in 1 MB of processor memory these 4 segments are located the
processor uses four segment registers:
Memory:
Program, data and stack memories occupy the same memory space. As the most
18
MPI
19
MPI
20
MPI
21
MPI
Byte (Reg 8)
Word
16)
Accumulator
Base
AL, AH
BL, BH
AX
BX
Count
Data
CL, CH
DL, DH
CX
DX
Stack pointer
Base pointer
SP
BP
Source index
SI
Destination
index
DI
Code segment
Data segment
CS
DS
Stack segment
Extra segment
SS
ES
22
(Reg
MPI
23
MPI
PA =
CS
SS
DS
ES
BX
BP
SI
DI
8-bit displacement
16-bit displacement
Not all elements are always used in the effective address calculation
In fact, three addressing modes are defined by using various combination of these
elements:
i.
Register indirect addressing mode
ii.
Based addressing mode
iii.
Indexed addressing mode
iv.
Based-indexed addressing mode
For e.g. in based addressing mode, the EA calculation only includes the base
PA =
CS
SS
DS
ES
Direct address
24
MPI
Memory
content
01000
01001
01002
01003
01004
8B
0E
34
12
XX
8088/8086 MPU
0000
IP
0100
0200
CS
DS
SS
ES
XXXX
AX
BX
CX
DX
BP
SI
DI
Next instruction
.
.
.
PA = 02000H + 1234H
= 03234H
SP
Instruction
02000
02000
.
XX
XX
.
.
03234
03235
ED
BE
Source operand
After calculating the physical address of the operand, the 8086 reads the word of
data starting at that address (which is BEEDH) and loads it into the CS register.
Address
Memory
content
Instruction
01000
8B
01001
01002
0E
34
8088/8086 MPU
0004
IP
0100
0200
CS
DS
SS
01003
12
01004
XX
Next instruction
ES
.
AX
BX
BEED
CX
DX
.
.
02000
XX
02001
XX
SP
BP
SI
.
03234
ED
03235
BE
DI
25
Source operand
MPI
8 0 8 8 /8 0 8 6 M P U
0002
0100
0200
IP
CS
DS
A d d re ss
M e m o ry
co n te n t
In stru ctio n
01000
8B
M O V A X , [S I]
01001
04
01002
XX
N e x t in stru ctio n
SS
.
ES
.
BEED
AX
BX
CX
DX
02000
XX
02001
XX
1234
SP
BP
SI
DI
8088/8086 MPU
0000
0100
0200
IP
CS
DS
03234
ED
03235
BE
Address
Memory
content
Instruction
01000
8B
01001
01002
04
XX
Next instruction
SS
ES
XXXX
AX
BX
.
PA = 02000H + 1234H
= 03234H
CX
DX
1234
S o u rc e o p e ra n d
SP
BP
SI
DI
.
.
02000
02001
XX
XX
.
.
.
03234
03235
26
ED
BE
Source operand
MPI
Segment base
PA =
CS
SS
DS
ES
Effective address
BX
BP
8-bit displacement
16-bit displacement
Base register
Element 0
Element 1
Element 2
.
.
.
Displacement
Array of
data
Element n-2
Element n-1
The value in the base register defines the beginning of a data structure (e.g. array)
in memory, and the displacement selects an element of data within the structure
To access a different element in the array, the programmer simply changes the
value of the displacement
To access the same element in another similar array, the programmer can change
the value in the base register so that it points to the beginning of the new array
Consider the instruction: MOV [BX]+1234H, AL
This instruction uses base register BX and direct displacement 1234H to derive
the destination operand.
27
MPI
Address
Memory
content
Instruction
IP
01000
88
MOV [BX]+1234H, AL
CS
DS
01001
01002
01003
87
34
12
SS
ES
01004
.
XX
8088/8086 MPU
0000
0100
0200
BE
ED
1000
Next instruction
.
.
AX
BX
02000
02001
CX
DX
XX
XX
SP
BP
SI
.
04234
04235
DI
XX
XX
Destination operand
Address
Memory
content
Instruction
IP
01000
88
MOV [BX]+1234H, AL
CS
DS
01001
01002
01003
87
34
12
SS
ES
01004
.
XX
8088/8086 MPU
0004
0100
0200
BE
ED
1000
AX
BX
CX
DX
SP
BP
SI
DI
Next instruction
.
.
02000
02001
XX
XX
.
.
.
04234
04235
28
ED
XX
Destination operand
MPI
PA =
CS
SS
DS
ES
Effective address
SI
DI
Displacement
Element 0
Element 1
Element 2
8-bit displacement
16-bit displacement
Index register
.
.
.
Array of
data
Element n-2
Element n-1
8088/8086 MPU
Address
Memory
content
01000
01001
8A
84
0000
IP
0100
CS
01002
34
0200
DS
01003
12
SS
01004
XX
ES
XX
XX
CX
DX
BP
Next instruction
BX
2000
.
.
AX
SP
Instruction
02000
XX
02001
XX
.
PA = 02000H + 2000H + 1234H
.
= 05234H
.
SI
DI
05234
BE
05235
XX
29
Source operand
MPI
The physical address of the source operand is first calculated from the contents of
DS, SI and the direct displacement
The data byte stored at 05234H is then moved to AL
8 08 8 /8 08 6 M PU
A d d ress
M e m ory
con ten t
Instru ction
M O V A L , [S I]+ 123 4 H
000 4
IP
01 00 0
8A
010 0
CS
01 00 1
01 00 2
84
34
020 0
DS
01 00 3
12
SS
ES
01 00 4
.
XX
AX
.
.
XX
BE
BX
CX
DX
02 00 0
XX
02 00 1
XX
.
.
SP
BP
200 0
N e xt in stru ction
SI
DI
.
05 23 4
BE
05 23 5
XX
S ou rce op e ra nd
This addressing mode is a combination of the based addressing mode and the
indexed addressing mode
The effective address is formed by three elements: base register, index register
and a displacement
Segment base
CS
SS
PA =
DS
ES
Effective address
BX
BP
SI
DI
8-bit displacement
16-bit displacement
30
MPI
13
14
14
10
11
2D array
of data
Index register
+
Displacement
Changing the values in the base and index registers permits access to other
elements in the array
Consider the instruction: MOV AH, [BX][SI]+1234H
Before the source operand can be moved to the destination, the 8086 calculates its
physical address
The effective address is formed by BX and SI registers with 16-bit displacement
The physical address is then computed from the current contents of DS register
and the effective address.
8088/8086 MPU
Address
Memory
content
Instruction
MOV AH, [BX][SI]+1234H
0000
IP
01000
8A
0100
0200
CS
DS
01001
01002
01003
A0
34
12
SS
ES
01004
.
XX
XX
XX
1000
2000
SP
BP
SI
Next instruction
.
.
AX
BX
02000
02001
CX
DX
XX
XX
DI
Base register
.
.
.
06234
06235
BE
XX
Source operand
Execution of the instruction moves the value stored at the physical address into AH
31
MPI
Address
Memory
content
Instruction
MOV AH, [BX][SI]+1234H
0004
IP
01000
8A
0100
0200
CS
DS
01001
01002
01003
A0
34
12
SS
ES
01004
.
XX
BE
XX
1000
AX
BX
CX
DX
2000
SP
BP
SI
DI
Next instruction
.
.
02000
02001
XX
XX
.
.
.
06234
06235
32
BE
XX
Source operand
MPI
AAA
AAD
AAM
AAS
ADC
ADD
AND
CALL
CBW
CLC
CLD
CLI
CMC
CMP
CMPSB
CMPSW
CWD
DAA
DAS
DEC
DIV
HLT
IDIV
IMUL
IN
INC
INT
INTO
IRET
JA
JAE JNBE
JB
JNC
JBE
JNE
JC
JNG
JCXZ JNGE
JE
JNL
JG
JNLE
JGE
JNO
JL
JNP
JLE
JNS
JMP
JNZ
JNA
JO
JNAE
JP
JNB
JPE
JPO
JS
JZ
LAHF
LDS
LEA
LES
LODSB
LODSW
LOOP
LOOPE
LOOPNE
LOOPNZ
LOOPZ
MOV
MOVSB
MOVSW
MUL
NEG
NOP
NOT
OR
OUT
POP
POPA
POPF
PUSH
PUSHA
PUSHF
RCL
RCR
REP
REPE
REPNE
REPNZ
REPZ
RET
RETF
ROL
ROR
SAHF
SAL
SAR
SBB
SCASB
SCASW
SHL
SHR
STC
STD
STI
STOSB
STOSW
SUB
TEST
XCHG
XLATB
XOR
Operand types:
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
SREG: DS, ES, SS, and only as second operand: CS.
Memory: [BX], [BX+SI+7], variable, etc...(See Memory Access).
Immediate: 5, -24, 3Fh, 10001101b, etc...
Notes:
When two operands are required for an instruction they are separated by comma.
For example:
REG, memory
When there are two operands, both operands must have the same size (except shift
and rotate instructions). For example:
AL, DL
DX, AX
m1 DB ?
AL, m1
33
MPI
Some examples contain macros, so it is advisable to use Shift + F8 hot key to Step
Over (to make macro code execute at maximum speed set step delay to zero),
otherwise emulator will step through each instruction of a macro. Here is an
example that uses PRINTN macro:
include 'emu8086.inc'
ORG 100h
MOV AL, 1
MOV BL, 2
PRINTN 'Hello World!' ; macro.
MOV CL, 3
PRINTN 'Welcome!'
; macro.
RET
AAA
Operands
No
operands
Description
ASCII Adjust after Addition.
Corrects result in AH and AL after addition when working
with BCD values.
It works according to the following Algorithm:
34
MPI
AL = AL + 6
AH = AH + 1
AF = 1
CF = 1
else
AF = 0
CF = 0
in both cases:
clear the high nibble of AL.
Example:
MOV AX, 15 ; AH = 00, AL = 0Fh
AAA
; AH = 01, AL = 05
RET
CZSOPA
r ? ? ? ? r
AAD
AAM
No
operands
No
operands
AL = (AH * 10) + AL
AH = 0
Example:
MOV AX, 0105h ; AH = 01, AL = 05
AAD
; AH = 00, AL = 0Fh (15)
RET
CZSOPA
? r r ? r ?
35
MPI
AH = AL / 10
AL = remainder
Example:
MOV AL, 15 ; AL = 0Fh
AAM
; AH = 01, AL = 05
RET
CZSOPA
? r r ? r ?
AAS
No
operands
AL = AL - 6
AH = AH - 1
AF = 1
CF = 1
else
AF = 0
CF = 0
in both cases:
clear the high nibble of AL.
Example:
MOV AX, 02FFh ; AH = 02, AL = 0FFh
AAS
; AH = 01, AL = 09
RET
CZSOPA
r ? ? ? ? r
36
MPI
ADC
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
Algorithm:
operand1 = operand1 + operand2 + CF
Example:
STC
; set CF = 1
MOV AL, 5 ; AL = 5
ADC AL, 1 ; AL = 7
RET
CZSOPA
r r r r r r
Add.
ADD
AND
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
Algorithm:
operand1 = operand1 + operand2
Example:
MOV AL, 5 ; AL = 5
ADD AL, -3 ; AL = 2
RET
CZSOPA
r r r r r r
Example:
37
MPI
Example:
ORG 100h ; directive to make simple .com file.
CALL
procedure
name
label
4-byte
address
CALL p1
ADD AX, 1
RET
; return to OS.
No
operands
AH = 255 (0FFh)
else
38
MPI
AH = 0
Example:
MOV AX, 0 ; AH = 0, AL = 0
MOV AL, -5 ; AX = 000FBh (251)
CBW
; AX = 0FFFBh (-5)
RET
CZSOPA
unchanged
No
operands
CF = 0
C
0
No
operands
DF = 0
D
0
No
operands
Algorithm:
IF = 0
39
MPI
I
0
CMC
No
operands
if CF = 1 then CF = 0
if CF = 0 then CF = 1
C
r
Compare.
Algorithm:
CMP
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
operand1 - operand2
result is not stored anywhere, flags are set (OF, SF, ZF,
AF, PF, CF) according to result.
Example:
MOV AL, 5
MOV BL, 5
CMP AL, BL ; AL = 5, ZF = 1 (so equal!)
RET
CZSOPA
r r r r r r
No
operands
DS:[SI] - ES:[DI]
set flags according to result:
OF, SF, ZF, AF, PF, CF
if DF = 0 then
40
MPI
o
o
else
SI = SI - 1
DI = DI - 1
o
o
Example:
see cmpsb.asm in c:\emu8086\examples\.
CZSOPA
r r r r r r
CMPSW
No
operands
DS:[SI] - ES:[DI]
set flags according to result:
OF, SF, ZF, AF, PF, CF
if DF = 0 then
o SI = SI + 2
o DI = DI + 2
else
SI = SI - 2
DI = DI - 2
o
o
Example:
see cmpsw.asm in c:\emu8086\examples\.
CZSOPA
r r r r r r
No
operands
Algorithm:
if high bit of AX = 1 then:
41
MPI
DX = 65535 (0FFFFh)
else
DX = 0
Example:
MOV DX, 0 ; DX = 0
MOV AX, 0 ; AX = 0
MOV AX, -5 ; DX AX = 00000h:0FFFBh
CWD
; DX AX = 0FFFFh:0FFFBh
RET
CZSOPA
unchanged
AL = AL + 6
AF = 1
No
operands
AL = AL + 60h
CF = 1
Example:
MOV AL, 0Fh ; AL = 0Fh (15)
DAA
; AL = 15h
RET
CZSOPA
r r r r r r
42
MPI
DAS
No
operands
AL = AL - 6
AF = 1
AL = AL - 60h
CF = 1
Example:
MOV AL, 0FFh ; AL = 0FFh (-1)
DAS
; AL = 99h, CF = 1
RET
CZSOPA
r r r r r r
Decrement.
Algorithm:
operand = operand - 1
DEC
REG
memory
DIV
REG
memory
Example:
MOV AL, 255 ; AL = 0FFh (255 or -1)
DEC AL
; AL = 0FEh (254 or -2)
RET
ZSOPA
r r r r r
CF - unchanged!
Unsigned divide.
43
MPI
HLT
No
operands
Example:
MOV AX, 5
HLT
CZSOPA
unchanged
Signed divide.
Algorithm:
IDIV
REG
memory
44
MPI
Signed multiply.
Algorithm:
IMUL
IN
REG
memory
AL,
im.byte
AL, DX
AX,
im.byte
AX, DX
Increment.
Algorithm:
operand = operand + 1
INC
REG
memory
Example:
MOV AL, 4
INC AL
; AL = 5
RET
ZSOPA
r r r r r
CF - unchanged!
45
MPI
INT
immediate
byte
flags register
CS
IP
IF = 0
Transfer control to interrupt procedure
Example:
MOV AH, 0Eh ; teletype.
MOV AL, 'A'
INT 10h
; BIOS interrupt.
RET
CZSOPAI
unchanged
0
INTO
No
operands
Example:
; -5 - 127 = -132 (not in -128..127)
; the result of SUB is wrong (124),
; so OF = 1 is set:
MOV AL, -5
SUB AL, 127 ; AL = 7Ch (124)
INTO
; process error.
RET
Interrupt Return.
IRET
No
operands
Algorithm:
Pop from stack:
46
MPI
IP
CS
flags register
o
o
o
CZSOPA
popped
JA
label
ORG 100h
MOV AL, 250
CMP AL, 5
JA label1
PRINT 'AL is not above 5'
JMP exit
label1:
PRINT 'AL is above 5'
exit:
RET
CZSOPA
unchanged
label
if CF = 0 then jump
Example:
include 'emu8086.inc'
ORG 100h
MOV AL, 5
47
MPI
JB
label
ORG 100h
MOV AL, 1
CMP AL, 5
JB label1
PRINT 'AL is not below 5'
JMP exit
label1:
PRINT 'AL is below 5'
exit:
RET
CZSOPA
unchanged
label
Algorithm:
if CF = 1 or ZF = 1 then jump
Example:
include 'emu8086.inc'
48
MPI
ORG 100h
MOV AL, 5
CMP AL, 5
JBE label1
PRINT 'AL is not below or equal to 5'
JMP exit
label1:
PRINT 'AL is below or equal to 5'
exit:
RET
CZSOPA
unchanged
JC
label
ORG 100h
MOV AL, 255
ADD AL, 1
JC label1
PRINT 'no carry.'
JMP exit
label1:
PRINT 'has carry.'
exit:
RET
CZSOPA
unchanged
label
Algorithm:
if CX = 0 then jump
Example:
49
MPI
JE
label
ORG 100h
MOV AL, 5
CMP AL, 5
JE label1
PRINT 'AL is not equal to 5.'
JMP exit
label1:
PRINT 'AL is equal to 5.'
exit:
RET
CZSOPA
unchanged
label
Algorithm:
50
MPI
JGE
label
ORG 100h
MOV AL, 2
CMP AL, -5
JGE label1
PRINT 'AL < -5'
JMP exit
label1:
PRINT 'AL >= -5'
exit:
RET
CZSOPA
unchanged
JL
label
51
MPI
Algorithm:
if SF <> OF then jump
Example:
include 'emu8086.inc'
ORG 100h
MOV AL, -2
CMP AL, 5
JL label1
PRINT 'AL >= 5.'
JMP exit
label1:
PRINT 'AL < 5.'
exit:
RET
CZSOPA
unchanged
JLE
label
ORG 100h
MOV AL, -2
CMP AL, 5
JLE label1
PRINT 'AL > 5.'
JMP exit
label1:
PRINT 'AL <= 5.'
exit:
RET
CZSOPA
unchanged
52
MPI
JMP
label
4-byte
address
always jump
Example:
include 'emu8086.inc'
ORG 100h
MOV AL, 5
JMP label1 ; jump over 2 lines!
PRINT 'Not Jumped!'
MOV AL, 0
label1:
PRINT 'Got Here!'
RET
CZSOPA
unchanged
label
ORG 100h
MOV AL, 2
CMP AL, 5
JNA label1
PRINT 'AL is above 5.'
JMP exit
label1:
PRINT 'AL is not above 5.'
exit:
RET
CZSOPA
53
MPI
JNAE
label
ORG 100h
MOV AL, 2
CMP AL, 5
JNAE label1
PRINT 'AL >= 5.'
JMP exit
label1:
PRINT 'AL < 5.'
exit:
RET
CZSOPA
unchanged
label
ORG 100h
MOV AL, 7
CMP AL, 5
JNB label1
PRINT 'AL < 5.'
JMP exit
label1:
PRINT 'AL >= 5.'
54
MPI
JNBE
label
ORG 100h
MOV AL, 7
CMP AL, 5
JNBE label1
PRINT 'AL <= 5.'
JMP exit
label1:
PRINT 'AL > 5.'
exit:
RET
CZSOPA
unchanged
JNC
label
if CF = 0 then jump
Example:
include 'emu8086.inc'
ORG 100h
MOV AL, 2
ADD AL, 3
JNC label1
PRINT 'has carry.'
JMP exit
55
MPI
JNE
label
ORG 100h
MOV AL, 2
CMP AL, 3
JNE label1
PRINT 'AL = 3.'
JMP exit
label1:
PRINT 'Al <> 3.'
exit:
RET
CZSOPA
unchanged
label
56
MPI
JNGE
label
ORG 100h
MOV AL, 2
CMP AL, 3
JNGE label1
PRINT 'AL >= 3.'
JMP exit
label1:
PRINT 'Al < 3.'
exit:
RET
CZSOPA
unchanged
label
if SF = OF then jump
Example:
include 'emu8086.inc'
57
MPI
JNLE
label
ORG 100h
MOV AL, 2
CMP AL, -3
JNLE label1
PRINT 'AL <= -3.'
JMP exit
label1:
PRINT 'Al > -3.'
exit:
RET
CZSOPA
unchanged
label
Algorithm:
if OF = 0 then jump
Example:
58
MPI
JNP
label
ORG 100h
MOV AL, 00000111b ; AL = 7
OR AL, 0
; just set flags.
JNP label1
PRINT 'parity even.'
JMP exit
label1:
PRINT 'parity odd.'
exit:
RET
CZSOPA
unchanged
59
MPI
JNS
label
ORG 100h
MOV AL, 00000111b ; AL = 7
OR AL, 0
; just set flags.
JNS label1
PRINT 'signed.'
JMP exit
label1:
PRINT 'not signed.'
exit:
RET
CZSOPA
unchanged
JNZ
label
ORG 100h
MOV AL, 00000111b ; AL = 7
OR AL, 0
; just set flags.
JNZ label1
PRINT 'zero.'
JMP exit
label1:
PRINT 'not zero.'
exit:
RET
CZSOPA
unchanged
60
MPI
label
org 100h
MOV AL, -5
SUB AL, 127 ; AL = 7Ch (124)
JO label1
PRINT 'no overflow.'
JMP exit
label1:
PRINT 'overflow!'
exit:
RET
CZSOPA
unchanged
JP
label
if PF = 1 then jump
Example:
include 'emu8086.inc'
ORG 100h
MOV AL, 00000101b ; AL = 5
OR AL, 0
; just set flags.
JP label1
PRINT 'parity odd.'
JMP exit
61
MPI
JPE
label
ORG 100h
MOV AL, 00000101b ; AL = 5
OR AL, 0
; just set flags.
JPE label1
PRINT 'parity odd.'
JMP exit
label1:
PRINT 'parity even.'
exit:
RET
CZSOPA
unchanged
label
if PF = 0 then jump
Example:
include 'emu8086.inc'
ORG 100h
62
MPI
JS
label
ORG 100h
MOV AL, 10000000b ; AL = -128
OR AL, 0
; just set flags.
JS label1
PRINT 'not signed.'
JMP exit
label1:
PRINT 'signed.'
exit:
RET
CZSOPA
unchanged
label
Algorithm:
if ZF = 1 then jump
Example:
63
MPI
No
operands
AH bit: 7 6 5 4 3 2 1 0
[SF] [ZF] [0] [AF] [0] [PF] [1] [CF]
bits 1, 3, 5 are reserved.
CZSOPA
unchanged
LDS
REG,
memory
Example:
ORG 100h
LDS AX, m
RET
64
MPI
Example:
LEA
REG,
memory
; AX = offset of m
CZSOPA
unchanged
REG,
memory
Algorithm:
65
MPI
ES = second word
Example:
ORG 100h
LES AX, m
RET
m DW 1234h
DW 5678h
END
AX is set to 1234h, ES is set to 5678h.
CZSOPA
unchanged
AL = DS:[SI]
if DF = 0 then
o SI = SI + 1
else
o
LODSB
No
operands
SI = SI - 1
Example:
ORG 100h
LEA SI, a1
MOV CX, 5
MOV AH, 0Eh
m: LODSB
INT 10h
LOOP m
RET
a1 DB 'H', 'e', 'l', 'l', 'o'
CZSOPA
66
MPI
AX = DS:[SI]
if DF = 0 then
o SI = SI + 2
else
o
LODSW
No
operands
SI = SI - 2
Example:
ORG 100h
LEA SI, a1
MOV CX, 5
REP LODSW ; finally there will be 555h in AX.
RET
a1 dw 111h, 222h, 333h, 444h, 555h
CZSOPA
unchanged
LOOP
CX = CX - 1
if CX <> 0 then
o jump
label
else
o
no jump, continue
Example:
include 'emu8086.inc'
ORG 100h
67
MPI
CX = CX - 1
if (CX <> 0) and (ZF = 1) then
o jump
else
o
LOOPE
label
no jump, continue
Example:
; Loop until result fits into AL alone,
; Or 5 times. The result will be over 255
; on third loop (100+100+100),
; So loop will exit.
include 'emu8086.inc'
ORG 100h
MOV AX, 0
MOV CX, 5
label1:
PUTC '*'
ADD AX, 100
CMP AH, 0
LOOPE label1
RET
CZSOPA
unchanged
68
MPI
CX = CX - 1
if (CX <> 0) and (ZF = 0) then
o jump
else
o
no jump, continue
Example:
; Loop until '7' is found,
; Or 5 times.
LOOPNE
label
include 'emu8086.inc'
ORG 100h
MOV SI, 0
MOV CX, 5
label1:
PUTC '*'
MOV AL, v1[SI]
INC SI
; next byte (SI=SI+1).
CMP AL, 7
LOOPNE label1
RET
v1 db 9, 8, 7, 6, 5
CZSOPA
unchanged
label
CX = CX - 1
if (CX <> 0) and (ZF = 0) then
o jump
else
69
MPI
no jump, continue
Example:
; Loop until '7' is found,
; Or 5 times.
include 'emu8086.inc'
ORG 100h
MOV SI, 0
MOV CX, 5
label1:
PUTC '*'
MOV AL, v1[SI]
INC SI
; next byte (SI=SI+1).
CMP AL, 7
LOOPNZ label1
RET
v1 db 9, 8, 7, 6, 5
CZSOPA
unchanged
CX = CX - 1
if (CX <> 0) and (ZF = 1) then
o jump
else
o
LOOPZ
no jump, continue
label
Example:
; Loop until result fits into AL alone,
; or 5 times. The result will be over 255
; on third loop (100+100+100),
; so loop will exit.
include 'emu8086.inc'
ORG 100h
MOV AX, 0
MOV CX, 5
label1:
PUTC '*'
70
MPI
MOV
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
SREG,
memory
memory,
SREG
REG,
SREG
SREG,
REG
Algorithm:
operand1 = operand2
Example:
ORG 100h
MOV AX, 0B800h ; set AX = B800h (VGA memory).
MOV DS, AX
; copy value of AX to DS.
MOV CL, 'A'
; CL = 41h (ASCII code).
MOV CH, 01011111b; CL = color attribute.
MOV BX, 15Eh
; BX = position on screen.
MOV [BX], CX ; w.[0B800h:015Eh] = CX.
RET
; returns to operating system.
CZSOPA
unchanged
No
operands
Algorithm:
ES:[DI] = DS:[SI]
if DF = 0 then
71
MPI
o
o
else
SI = SI - 1
DI = DI - 1
o
o
Example:
ORG 100h
CLD
LEA SI, a1
LEA DI, a2
MOV CX, 5
REP MOVSB
RET
a1 DB 1,2,3,4,5
a2 DB 5 DUP(0)
CZSOPA
unchanged
MOVSW
No
operands
ES:[DI] = DS:[SI]
if DF = 0 then
o SI = SI + 2
o DI = DI + 2
else
o
o
SI = SI - 2
DI = DI - 2
Example:
ORG 100h
CLD
LEA SI, a1
72
MPI
Unsigned multiply.
Algorithm:
MUL
REG
memory
NEG
REG
memory
Example:
MOV AL, 5 ; AL = 05h
NEG AL ; AL = 0FBh (-5)
NEG AL ; AL = 05h (5)
RET
CZSOPA
r r r r r r
73
MPI
No Operation.
Algorithm:
NOP
No
operands
Do nothing
Example:
; do nothing, 3 times:
NOP
NOP
NOP
RET
CZSOPA
unchanged
NOT
REG
memory
if bit is 1 turn it to 0.
if bit is 0 turn it to 1.
Example:
MOV AL, 00011011b
NOT AL ; AL = 11100100b
RET
CZSOPA
unchanged
OR
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
74
MPI
OUT
im.byte,
AL
im.byte,
AX
DX, AL
DX, AX
Example:
MOV AX, 0FFFh ; Turn on all
OUT 4, AX ; traffic lights.
MOV AL, 100b ; Turn on the third
OUT 7, AL ; magnet of the stepper-motor.
CZSOPA
unchanged
POP
REG
SREG
memory
Example:
MOV AX, 1234h
PUSH AX
POP DX ; DX = 1234h
RET
CZSOPA
unchanged
POPA
No
operands
Pop all general purpose registers DI, SI, BP, SP, BX, DX,
CX, AX from the stack.
SP value is ignored, it is Popped but not set to SP register).
75
MPI
POP DI
POP SI
POP BP
POP xx (SP value ignored)
POP BX
POP DX
POP CX
POP AX
CZSOPA
unchanged
No
operands
CZSOPA
popped
PUSH
REG
SREG
memory
immediate
Algorithm:
SP = SP - 2
SS:[SP] (top of the stack) = operand
Example:
MOV AX, 1234h
PUSH AX
76
MPI
Push all general purpose registers AX, CX, DX, BX, SP,
BP, SI, DI in the stack.
Original value of SP register (before PUSHA) is used.
Note: this instruction works only on 80186 CPU and later!
Algorithm:
PUSHA
No
operands
PUSH AX
PUSH CX
PUSH DX
PUSH BX
PUSH SP
PUSH BP
PUSH SI
PUSH DI
CZSOPA
unchanged
No
operands
SP = SP - 2
SS:[SP] (top of the stack) = flags
CZSOPA
unchanged
RCL
memory,
immediate
REG,
immediate
77
MPI
memory,
CL
REG, CL
code only for this instruction (the same principle works for
all other shift/rotate instructions).
Algorithm:
shift all bits left, the bit that goes off is set to CF
and previous value of CF is inserted to the rightmost position.
Example:
STC
; set carry (CF=1).
MOV AL, 1Ch
; AL = 00011100b
RCL AL, 1
; AL = 00111001b, CF=0.
RET
CO
r r
OF=0 if first operand keeps original sign.
Rotate operand1 right through Carry Flag. The number of
rotates is set by operand2.
Algorithm:
RCR
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
shift all bits right, the bit that goes off is set to CF
and previous value of CF is inserted to the left-most
position.
Example:
STC
; set carry (CF=1).
MOV AL, 1Ch
; AL = 00011100b
RCR AL, 1
; AL = 10001110b, CF=0.
RET
CO
r r
OF=0 if first operand keeps original sign.
Repeat following MOVSB, MOVSW, LODSB, LODSW,
STOSB, STOSW instructions CX times.
REP
chain
instruction
Algorithm:
check_cx:
78
MPI
else
Z
r
REPE
chain
instruction
else
Example:
see cmpsb.asm in c:\emu8086\examples\.
Z
r
79
MPI
REPNE
chain
instruction
else
Z
r
chain
instruction
if CX <> 0 then
80
MPI
else
Z
r
REPZ
chain
instruction
else
Z
r
No
operands
or even
immediate
Algorithm:
81
MPI
Example:
ORG 100h ; for COM file.
CALL p1
ADD AX, 1
RET
; return to OS.
p1 PROC ; procedure declaration.
MOV AX, 1234h
RET ; return to caller.
p1 ENDP
CZSOPA
unchanged
RETF
No
operands
or even
immediate
CZSOPA
unchanged
ROL
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
Algorithm:
shift all bits left, the bit that goes off is set to CF
and the same bit is inserted to the right-most
position.
Example:
MOV AL, 1Ch
; AL = 00011100b
ROL AL, 1
; AL = 00111000b, CF=0.
RET
CO
82
MPI
ROR
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
shift all bits right, the bit that goes off is set to CF
and the same bit is inserted to the left-most
position.
Example:
MOV AL, 1Ch
; AL = 00011100b
ROR AL, 1
; AL = 00001110b, CF=0.
RET
CO
r r
OF=0 if first operand keeps original sign.
Store AH registers into low 8 bits of Flags register.
Algorithm:
flags register = AH
SAHF
No
operands
AH bit: 7 6 5 4 3 2 1 0
[SF] [ZF] [0] [AF] [0] [PF] [1] [CF]
bits 1, 3, 5 are reserved.
CZSOPA
r r r r r r
SAL
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
Shift all bits left, the bit that goes off is set to CF.
Zero bit is inserted to the right-most position.
Example:
MOV AL, 0E0h
83
; AL = 11100000b
MPI
; AL = 11000000b, CF=1.
r r
OF=0 if first operand keeps original sign.
Shift Arithmetic operand1 Right. The number of shifts is
set by operand2.
Algorithm:
SAR
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
Shift all bits right, the bit that goes off is set to CF.
The sign bit that is inserted to the left-most position
has the same value as before shift.
Example:
MOV AL, 0E0h
; AL = 11100000b
SAR AL, 1
; AL = 11110000b, CF=0.
MOV BL, 4Ch
; BL = 01001100b
SAR BL, 1
; BL = 00100110b, CF=0.
RET
CO
r r
OF=0 if first operand keeps original sign.
Subtract with Borrow.
Algorithm:
SBB
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
84
MPI
SCASB
No
operands
ES:[DI] - AL
set flags according to result:
OF, SF, ZF, AF, PF, CF
if DF = 0 then
o DI = DI + 1
else
DI = DI - 1
CZSOPA
r r r r r r
SCASW
No
operands
ES:[DI] - AX
set flags according to result:
OF, SF, ZF, AF, PF, CF
if DF = 0 then
o DI = DI + 2
else
DI = DI - 2
CZSOPA
r r r r r r
SHL
memory,
immediate
REG,
immediate
memory,
CL
Shift all bits left, the bit that goes off is set to CF.
85
MPI
REG, CL
Example:
MOV AL, 11100000b
SHL AL, 1
; AL = 11000000b, CF=1.
RET
CO
r r
OF=0 if first operand keeps original sign.
Shift operand1 Right. The number of shifts is set by
operand2.
Algorithm:
SHR
memory,
immediate
REG,
immediate
memory,
CL
REG, CL
Shift all bits right, the bit that goes off is set to CF.
Zero bit is inserted to the left-most position.
Example:
MOV AL, 00000111b
SHR AL, 1
; AL = 00000011b, CF=1.
RET
CO
r r
OF=0 if first operand keeps original sign.
Set Carry flag.
Algorithm:
STC
No
operands
CF = 1
C
1
STD
No
operands
86
MPI
No
operands
IF = 1
I
1
ES:[DI] = AL
if DF = 0 then
o DI = DI + 1
else
DI = DI - 1
STOSB
No
operands
Example:
ORG 100h
LEA DI, a1
MOV AL, 12h
MOV CX, 5
REP STOSB
RET
a1 DB 5 dup(0)
CZSOPA
87
MPI
ES:[DI] = AX
if DF = 0 then
o DI = DI + 2
else
DI = DI - 2
STOSW
No
operands
Example:
ORG 100h
LEA DI, a1
MOV AX, 1234h
MOV CX, 5
REP STOSW
RET
a1 DW 5 dup(0)
CZSOPA
unchanged
Subtract.
SUB
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
Algorithm:
operand1 = operand1 - operand2
Example:
MOV AL, 5
SUB AL, 1
; AL = 4
RET
CZSOPA
r r r r r r
88
MPI
TEST
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0
Example:
MOV AL, 00000101b
TEST AL, 1
; ZF = 0.
TEST AL, 10b
; ZF = 1.
RET
CZSOP
0 r r 0 r
XCHG
REG,
memory
memory,
REG
REG, REG
Example:
MOV AL, 5
MOV AH, 2
XCHG AL, AH ; AL = 2, AH = 5
XCHG AL, AH ; AL = 5, AH = 2
RET
CZSOPA
unchanged
XLATB
No
operands
89
MPI
XOR
REG,
memory
memory,
REG
REG, REG
memory,
immediate
REG,
immediate
1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
Example:
MOV AL, 00000111b
XOR AL, 00000010b ; AL = 00000101b
RET
CZSOPA
0 r r 0 r ?
90
MPI
ARRAY=PTR
DD
25629261
LES DI, ARRAY-PTR
The Low word of this double word 9261 is copied to DI, 2562 - ES.
91
MPI
92
MPI
The 8086 can read a word from memory in one bus cycle if word is at even
address, two bus cycles, if word is at Odd address. A NOP instruction is
inserted in the location incremented over.
Ex:
Average
EVEN
Record
Data ends
Data Segment
DB
DW
DUP
(?)
100
DUP
(0)
EXTRN: External
This is used to tell the assembler that the names or labels following the
directive are in some other assembly module.
Ex: For calling a procedure which is in a program module assembled at a
different time, you must tell the assembler that the procedure is external.
The assembler will then put the information in the object code file so that the
linker can connect the two modules together.
1. For Variables type (should be specified)
Ex: EXTRN DIVISOR: BYTE
2. for constant ABS
(Defined with EQU in another module)
2. For a Label -+ near/far
GLOBAL:
Declare symbols as PUBLIC or Extern.
The PUBLIC directive is used to tell the assembler that a specified name r label will be
accessed from other modules.
Ex: PUBLIC DIVISOR, DIVIDEND
93
MPI
far/near
byte/word
94
MPI
Operators:
PTR:
The PTR operator is used to assign a specific type to a variable or to a label.
Ex:
1. INC [BX]
It will not know whether to increment byte/word. INC BYTE PTR [BX]
2. Array of words:
WORDS DW 437AH, OB927H, 7C41 H for accessing a byte in the array
MOV AL, BYTE DTR WORDS
3. for Jump Instructions:
JMP [BX]
JMP BYTE PTR [BX]
95
MPI
Short
Label
The short operator saves 1 byte of memory by telling that it needs to reserve only 1
byte for this particular jump.
1 byte
TYPE:
It tells the assembler to det. The type of a specified variable.
TYPE
For
byte
Word - 2
Double Word-> 4
Ex: MOV AL, TYPE Array
-1
Length:
(Not implemented in MASM)
No. of elements in some named data item.
Ex: MOV C , Length String 1
It produces the no, of bytes in the string if declared as bytes.
96
MPI
Procedure is a part of code that can be called from your program in order to make
some specific task.
Procedures make program more structural and easier to understand. Generally
procedure returns to the same point from where it was called.
The syntax for procedure declaration:
Name
PROC
;
;
here
of
goes
the
the
procedure
code
...
RET
name ENDP
Name - is the procedure name, the same name should be in the top and the
bottom; this is used to check correct closing of procedures.
Probably, you already know that RET instruction is used to return to operating
system.
The same instruction is used to return from procedure (actually operating system
sees your program as a special procedure).
PROC and ENDP are compiler directives, so they are not assembled into any real
machine code. Compiler just remembers the address of procedure.
CALL instruction is used to call a procedure.
Here is an example:
ORG 100h
CALL m1
MOV AX, 2
RET
97
MPI
; return to caller.
ENDP
END
The above example calls procedure m1, does MOV BX, 5, and returns to the next
instruction after CALL: MOV AX, 2.
There are several ways to pass parameters to procedure, the easiest way to pass
parameters is by using registers, here is another example of a procedure that
receives two parameters in AL and BL registers, multiplies these parameters and
returns the result in AX register:
ORG 100h
MOV AL, 1
MOV BL, 2
CALL
CALL
CALL
CALL
m2
m2
m2
m2
RET
m2 PROC
MUL BL
RET
m2 ENDP
; AX = AL * BL.
; return to caller.
END
98
MPI
In the above example value of AL register is update every time the procedure is
called, BL register stays unchanged, so this algorithm calculates 2 in power of 4,
so final result in AX register is 16 (or 10h). Here goes another example,
that uses a procedure to print a Hello World! message:
ORG 100h
LEA SI, msg
CALL print_me
RET
;
==========================================================
; this procedure prints a string, the string should be null
; terminated (have zero in the end),
; the string address should be in SI register:
print_me PROC
next_char:
CMP b.[SI], 0 ; check for zero to stop
JE stop
;
MOV AL, [SI]
99
MPI
END
"b." - prefix before [SI] means that we need to compare bytes, not words. When you need
to compare words add "w." prefix instead. When one of the compared operands is a
register it's not required because compiler knows the size of each register.
1.8.2) Macros:
Macros are just like procedures, but not really. Macros look like procedures, but they
exist only until your code is compiled, after compilation all macros are replaced with
real instructions.
If you declared a macro and never used it in your code, compiler will simply ignore it.
Emu8086.inc is a good example of how macros can be used; this file contains several
macros to make coding easier for you.
Macro definition:
Name MACRO [parameters...]
<instructions>
ENDM
Unlike procedures, macros should be defined above the code that uses it, for example:
My Macro
MOV AX, p1
MOV BX, p2
MOV CX, p3
ENDM
ORG 100h
100
MPI
The
above
code
MOV
MOV
MOV
MOV
MOV
MOV
is
AX,
BX,
CX,
AX,
BX,
CX,
expanded
into:
00001h
00002h
00003h
00004h
00005h
DX
101
MPI
Macros are expanded directly in code; therefore if there are labels inside the macro
definition you may get "Duplicate declaration" error when macro is used for twice or
more.
To avoid such problem, use LOCAL directive followed by names of variables, labels
or procedure names. For example:
Mymacro2 MACRO
LOCAL label1, label2
CMP AX, 2
JE label1
CMP AX, 3
JE label2
label1:
INC AX
label2:
ADD AX, 2
ENDM
ORG 100h
MyMacro2
MyMacro2
RET
If you plan to use your macros in several programs, it may be a good idea to place all
macros in a separate file. Place that file in Inc folder and use INCLUDE file-name
directive to use macros.
102
MPI