0% found this document useful (0 votes)
80 views

Instruction 8086 Senthil

a

Uploaded by

Soumitra Bhowmik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
80 views

Instruction 8086 Senthil

a

Uploaded by

Soumitra Bhowmik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

CHAPTER 14

ADDRESSING MODES,
INSTRUCTION SET, AND
PROGRAMMING OF 8086

14.1 ADDRESSING MODES IN 8086


There are different addressing modes in the 8086. The addressing mode indicates
the way in which the operand or data for an instruction is accessed and the way
in which the microprocessor calculates the branch address for the jump, call, and
return instructions. We can classify the addressing modes in the 8086 under five
categories:
(i) Register addressing mode
(ii) Immediate addressing mode
(iii) Data memory addressing modes
(iv) Program memory addressing modes
(v) Stack memory addressing mode
Let us see each addressing mode in detail.

14.1. 1 Register Addressing Mode


In this addressing mode, the data present in the register is moved or manipulated
and the result is stored in the register.

Example:
(a) MOV AL, BL ; Move the content of BL to AL.
(b) MOV CX, BX ; Move the content of BX to CX.
(c) ADD CL, BL ; Add the contents of CL and BL and store the
result in CL.
(d) ADC BX, DX ; Add the contents of BX , the carry flag, and
DX, and store the result in BX.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 4 33

14.1. 2 Immediate Addressing Mode


In this mode, the destination can be either a memory location or a register. The
data can be 8 bits or 16 bits wide and is directly given in the instruction.
Example:
(a) MOV AL, 50H ; Move the data 50H to AL.
(b) MOV BX, 23A0H ; Move the data 23A0H to BX.
(c) MOV [SI], 43C0H ; Move the data 43C0H to the memory at [SI].

In the last example, [SI] represents the memory location in the data segment at
the offset address specified by the SI register.

14.1. 3 Data Memory Addressing Modes


The term effective address (EA) represents the offset address of the data within a
segment, which is obtained by different methods, depending upon the addressing
mode that is used in the instruction. Let us assume that the various registers in
the 8086 have the following values (Table 14.1) stored in them, throughout the
discussion of data memory addressing modes.
Table 14.1 Values stored in different registers of the 8086

Register CS DS SS ES BX BP SI DI

Stored value 1000H 3000H 4000H 6000H 2000H 1000H 1000H 3OOOH

The different data memory addressing modes are as follows:


(i) Direct addressing: In this mode, the 16-bit offset address of the data within the
segment is directly given in the instruction.
Example:
(a) MOV AL, [1000H]
In this instruction, the effective address is 1000H. Since the destination is an 8-
bit register (i.e., AL), a byte is taken from the memory at the address given by
DS x 10H + EA (= 31000H) and stored in AL.
(b)MOV BX, [2000H]
EA = 2000H in this instruction. Since the destination is a 16-bit register (i.e., BX),
a word is taken from the memory address DS x 10H + EA (= 32OOOH) and stored
in BX. (Note: Since a word contains two bytes, the bytes present at the memory
addresses 32000H and 32001H are moved to BL and BH, respectively.)
(ii) Base addressing: In this mode, EA is the content of the BX or BP register.
When the BX register is present in the instruction, data is taken from the data
segment and when BP is present, data is taken from the stack segment.

Example:
(a)MOV CL, [BX]
EA = (BX) = 2000H
Memory address = DS x 10 4- (BX) = 32OOOH. The byte from the memory address
32OOOH is read and stored in CL.
434 MICROPROCESSORS AND MICROCONTROLLERS

(b)MOV DX, [BP]


EA = (BP) = 1OOOH
Memory address = SS x 10 + (BP) = 41000H. The word from the memory address
41000H is read and stored in DX.
(iii) Base relative addressing: In this mode, EA is obtained by adding the content of
the base register with an 8-bit or 16-bit displacement. The displacement is a signed
number with negative values represented in 2’s complement form. The 16-bit
displacement can have values from -32768 to +32767 and the 8-bit displacement
can have values from -128 to +127.
Example:
(a) MOV AX, [BX + 5]
EA = (BX) + 5
Memory address = DS x 10H + (BX) + 5
= 30000H + 2000H + 5 = 32005H
The word from the memory address 32005H is read and stored in AX.
(b)MOV CH,[BX - 100H]
EA = (BX) - 100H
Memory address = DS x 10H + (BX) - 100H
= 30000H + 2000H - 100H = 31F00H
The byte from the memory address 31F00H is read and stored in CH.
(iv) Index addressing: In this mode, EA is the content of the SI or DI register,
which is specified in the instruction. The data is taken from the data segment.

Example:
(a)MOV BL, [SI]
EA = (SI) = 1000H
Memory address = DS x 10H + SI
= 30000H + 1000H = 31000H
A byte from the memory address 31000H is read and stored in BL.
(b)MOV CX, [DI]
EA = (DI) = 3000H
Memory address = DS x 10H + (DI)
= 30000H + 3000H = 33000H
A word from the memory address 33OOOH is read and stored in CX.
(v) Index relative addressing: This mode is the same as the base relative addressing
mode, except that instead of the BP or BX register, the SI or DI register is used.
Example:
(a)MOV BX, [SI - 100H]
EA = (SI) - 100H
Memory address = DS x 10H + (SI) - 100H
= 30000H + 1000H - 100H = 30F00H
A word from the memory address 30F00H is read and stored in BX.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 435

(b)MOV CL, [DI + 10H]


EA = (DI) + 1OH
Memory address = DS x 1OH + (DI) + 1OH
= 3OOOOH + 3OOOH + 1OH = 33O1OH
A byte from the memory address 3301 OH is read and stored in CL.
(vi) Base plus index addressing: In this mode, EA is obtained by adding the content
of a base register and an index register.
Example:
MOV AX, [BX + SI]
EA = (BX) + (SI)
Memory address = DS x 10H + (BX) + (SI)
= 30000H + 2000H + 1000H = 33000H
A word from the memory address 33OOOH is taken and stored in AX.
Base relative, index relative, and base plus index addressing modes are used to
access a byte or word type data one by one, from a table or an array of data stored
in the data segment.
(vii) Base relative plus index addressing: In this mode, EA is obtained by adding
the content of a base register, an index, and a displacement.
Example:
(a) MOV CX, [BX + SI + BOH]
EA = (BX) + (SI) + 50H
Memory address = DS x 10H + (BX) + (SI) + 50H
= 30000H + 2000H + 1000H + 50H
= 33050H
A word from the memory address 33050H is read and stored in CX.

Base relative plus index addressing is used to access a byte or a word in a particular
record of a specific file in the memory. An application program may process many
files stored in the data segment. Each file contains many records and a record
contains a few bytes or words of data. In base relative plus index addressing, the
base register may be used to hold the offset address of a particular file in the data
segment; the index register may be used to hold the offset address of a particular
record within that file; the relative value is used to indicate the offset address of
particular byte or word within that record.

14.1.4 Program Memory Addressing Modes


Program memory addressing modes are used with the JMP and CALL instructions
and consist of three distinct forms—direct, relative, and indirect.
(i) Direct addressing: Direct program memory addressing stores both the segment
and the offset address where the control has to be transferred with the opcode, as
shown in Fig. 14.1.
This instruction is equivalent to JMP 32000H. When it is executed, the 16-bit
offset value 2000H is loaded in the IP register and the 16-bit segment value 3000H
is loaded in CS. When the microprocessor calculates the memory address from
436 MICROPROCESSORS AND MICROCONTROLLERS

EAH OOH 20H OOH 30H


(Opcode) (IP—Lower-order byte) (IP—Higher-order byte) (CS—Lower-order byte) (CS—Higher-order byte)
mini11.1. i.ipt::.-'~~xr;Tij:t~r;g-rn; juiwi'IUiiimf™
Fig. 14.1 Format of JMP instruction (direct addressing)

where it has to fetch an instruction using the relation CS x 10H + IP, the address
32000H is obtained using the given CS and IP values.
This type of jump is known as intersegment jump, using which the
microprocessor can jump to any memory location within the memory system (i.e.,
within 1 MB). It is also known as far jump. The inter-segment or FAR CALL
instruction also uses direct program memory addressing. While using the assembler
to develop the 8086 program, the assembler directive FAR PTR is sometimes used
to indicate the inter-segment jump instruction.
Example:
(a) JMP FAR PTR COMPUTE
(b) JMP FAR PTR SIMULATE
In these examples, COMPUTE and SIMULATE are the labels of memory
locations that are present in code segments other than the ones in which these
instructions are present.
(ii) Relative addressing: The term relative here means relative to the instruction
pointer (IP). Relative JMP and CALL instructions contain either an 8-bit or a
16-bit signed displacement, which is added to the current instruction pointer.
Based on the new value of IP thus obtained, the address of the next instruction to
be executed is calculated using the relation CS x 10H + IP.
The 8-bit or 16-bit signed displacement allows a forward or a reverse memory
reference, depending on the sign of the displacement. If the displacement is positive,
PC is incremented by the displacement value and if it is negative, PC is decremented
by the magnitude of the displacement value. A one-byte displacement is used in the
short jump and call instructions, and a two-byte displacement is used in the near
jump and call instructions. Both types are considered intrasegmentjumps, since the
program control is transferred anywhere within the cunent code segment.
An 8-bit displacement has a jump range between +127 and -128 bytes from the
next instruction, while a 16-bit displacement has a jump range between -32,768
and +32,767 bytes from the instruction following the jump instruction in the
program. The opcode of the relative short jump and near jump instructions are
EBH and E9H, respectively.
While using an assembler to develop the 8086 program, the assembler
directives SHORT and NEAR PTR are used to indicate the short jump and near
jump instructions, respectively.
Example:
(a) JMP SHORT OVER
(b) JMP NEAR PTR FIND
In these examples, OVER and FIND are the labels of memory locations that
are present in the same code segment in which these instructions are present.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 437

(iii) Indirect addressing: The indirect jump or CALL instructions use a 16-bit
register (AX, BX, CX, DX, SP, BP, SI, or DI), a relative register ([BP], [BX],
[DI], or [SI]), or a relative register with displacement. The opcode of the indirect
jump instruction is FFH. It can be either an inter-segment indirect jump or an
intra-segment indirect jump.
If a 16-bit register holds the jump address in an indirect JMP instruction, the
operation is a near jump. If the CX register contains 2000H and the JMP CX
instruction present in a code segment is executed, the microprocessor jumps to the
offset address 2000H in the current code segment to take the next instruction for
execution (this is done by loading the IP with the content of CX, without changing
the content of CS).
When the instruction JMP [DI] is executed, the microprocessor first reads a
word in the current data segment from the offset address specified by DI and
places that word in the IP register. Now, with this new value of IP, the 8086
calculates the address of the memory location to which it has to jump, using the
relation CS x 10H + IP.
Example:
Let us assume that the registers DS, DI, and CS have the values 1000H, 2000H,
and 3000H, respectively. When JMP [DI], present at the offset address 1500H
in the code segment 3000H is executed, the microprocessor reads a word from
the address given by DS x 10H + DI (= 12000H) in the memory, and loads
it in the instruction pointer (IP). Let us assume that the word that is stored
in the address 12000H is 4000H. Hence, the program counter will be loaded
with the value 4000H. Now, the microprocessor fetches the next instruction for
execution from the address given by CS x 10H + IP (= 3000H x 10H + 4000H
= 34000H).

14.1.5 Stack Memory Addressing Mode


The stack is used to hold data temporarily during program execution and also store
the return address for procedures and interrupt service routines. The stack memory
is a last-in, first-out (LIFO) memory. Data are placed into the stack using the
PUSH instruction and taken out using the POP instruction. The CALL instruction
uses the stack to hold the return address for procedures and the RET instruction is
used to remove the return address from the stack.
The stack segment is maintained by two registers—the stack pointer (SP) and
the stack segment (SS) register. Data is pushed into or popped from the stack as
words (16-bit data), since bytes (8-bit data) cannot be used with the PUSH and
POP instructions. Whenever a word of data is pushed into the stack, the higher-
order eight bits of the word are placed in the memory location specified by SP - 1
(i.e., at the address SS x 10H + SP - 1) and the lower-order eight bits of the word
are placed in the memory location specified by SP - 2 in the current stack segment
(i.e., at the address SS x 10H + SP - 2). SP is then decremented by 2. The data
pushed into the stack may be the content of a 16-bit register, a segment register, or
a 16-bit data in the memory.
438 MICROPROCESSORS AND MICROCONTROLLERS

Since SP gets decremented for every push operation, the stack segment is said
to be growing downwards, as for successive push operations, data are stored in the
lower memory addresses in the stack segment. Due to this, SP is initialized with
the highest offset address, according to the user’s requirement, at the beginning of
the program.
Example:
(a) PUSH AX ; Push the content of AX into the stack.
(b)PUSH DS ; Push the content of DS into the stack.
(c) PUSH [BX] ; Push the content of the memory location at
the offset address specified by BX in the
current data segment, into the stack.
The PUSHF instruction is used to push the flag register’s content into the
stack.
Whenever a word is popped from the stack, the lower-order eight bits of the
word are removed from the memory location specified by SP and the higher-order
eight bits of the word are removed from the memory location specified by SP + 1
in the current stack segment. SP is then incremented by two.
Example:
(a) POP BX : Pop the content of BX from the stack.
(b) POP ES ; Pop the content of ES from the stack.
(c) POP [BP] ; Pop the content of the memory 1 ocation at
the offset address specified by BP in the
current stack segment, from the stack.
The POPF instruction is used to pop a word stored in the stack and move it to
the flag register.

14.2 SEGMENT OVERRIDE PREFIX


The segment override prefix, which can be added to almost any instruction in
any memory related addressing mode, allows the programmer to deviate from the
default segment and offset register mechanism. The segment override prefix is
an additional byte that appears in at the beginning of an instruction, to select an
alternative segment register. The JMP and CALL instructions cannot be prefixed
with the segment override prefix, since they use only the code segment (CS)
register for address generation.
Example:
The MOV AX, [BP] instruction accesses data within the stack segment by default,
since BP is the offset register for the stack segment. However, if the programmer
wants to get data from the data segment using BP as the offset register in this
instruction, the instruction should be modified as MOV AX, DS: [BP].
Table 14.2 shows the instructions that address memory segments other than the
default ones.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 4 39

Table 14.2 Instructions that include the segment override prefix

Instruction Default segment Accessed segment

MOV BX, ES:[BP] SS ES


MOV BX, SS:[DI] DS SS
MOV CX, ES:[BX] DS ES
MOV CX, ES:[SI] DS ES
MOV AX, CS:[BX] DS CS

14.3 INSTRUCTION SET OF 8086


The instructions of the 8086 are classified as data transfer, arithmetic, logical,
flag manipulation, control transfer, shift/rotate, string, and machine control
instructions.

14.3.1 Data Transfer Instructions


The data transfer instructions include MOV, PUSH, POP, XCHG, XLAT, IN,
OUT, LEA, LDS, LES, LSS, LAHF, and SAHF. These instructions are discussed
here in detail:
(i) MOV: The MOV instruction copies a word or byte of data from a specified
source to a specified destination. The destination can be a register or a memory
location. The source can be a register, a memory location, or an immediate number.
The general format of the MOV instruction is MOV destination, source.
Example:
(a) MOV BL, 50H ; Move immediate data 50H to BL.
(b)MOV CX, [BX] ; Copy the word from the memory at [BX] to CX.
(c)MOV AX, CX ; Copy the contents of CX to AX.
Note: [BX] indicates the memory location at the offset address specified by BX in
the data segment.

(ii) PUSH: The PUSH instruction is used to store the word in a register or a
memory location into the stack, as explained in the stack addressing mode. SP is
decremented by two after the execution of PUSH.

Example:
(a)PUSH CX : PUSH the content of CX into the stack.
(b)PUSH DS ; PUSH the content of DS into the stack.
(c)PUSH [BX] ; PUSH the word in the memory at [BX] into
the stack.

(iii) POP: The POP instruction copies the top word from the stack to a destination
specified in the instruction. The destination can be a general-purpose register, a
segment register, or a memory location. After the word is copied to the specified
destination, SP is incremented by two.
440 MICROPROCESSORS AND MICROCONTROLLERS

Example:
(a) POP BX ; Pop the content of BX from the stack.
(b)POP DS : Pop the content of DS from the stack.
(c) POP [SI] : Pop a word from the stack and store it in
the memory at [SI],
Note: [SI] indicates the memory location in the data segment at the offset address
specified by SL
(iv) XCHG: The XCHG instruction exchanges the contents of a register with the
contents of a memory location. It cannot exchange the contents of two memory
locations directly. The source and destination must both be either words or bytes.
The segment registers cannot be used in this instruction.
Example:
(a) XCHG AL, BL : Exchanges the content of AL and BL.
(b)XCHG CX, BX : Exchanges the content of CX and BX.
(c) XCHG AX, [BX] ; Exchanges the content of AXwith the content
of the memory at [BX].

(v) XLAT: The XLAT instruction is used to translate a byte in AL from one code
to another code. The instruction replaces a byte in the AL register with a byte in
the memory at [BX], which is one of the data items present in a look-up table.
Before XLAT is executed, the look-up table containing the desired codes must
be put in the data segment and the offset address of the starting location of the
look-up table is stored in BX. The code byte to be translated is put in AL. When
XLAT is executed now, it adds the content of the AL with BX to find the offset
address of the data in the look-up table. Further, the byte in that offset address will
get copied to AL.
(vi) IN: The IN instruction copies data from a port to the AL or AX register. If an
8-bit port is read, the data is stored in AL and if a 16-bit port is read, the data is
stored in AX. The IN instruction has two formats—fixed port and variable port.
In the fixed port type IN instruction, the 8-bit address of a port is specified
directly in the instruction. With this form, any one of 256 possible ports can be
addressed.
Example:
IN AL, 80H : Input a byte from the port with address 80H to AL.
IN AX, 40H ; Input a word from the port with address 40H to AX.
For the variable port type IN instruction, the port address is loaded into the DX
register before the IN instruction. Since DX is a 16-bit register, the port address
can be any number between 0000H and FFFFH. Hence, we will be able to address
up to 65,536 ports in this mode. The following example shows a part of a program
having the IN instruction. The operations done when the instructions are executed
are given in the corresponding comment fields.
Example:
MOV DX, 0FE50H ; Initialize DX with the port address of FE50H.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 441

IN AL, DX ; Input a byte from the 8-bit port with port


address FE50H into AL.
IN AX, DX ; Input a word from the 16-bit port with port
address FE50H into AX.
The drawback of the fixed port type IN instruction is that the port address
cannot be changed once the program is stored in the ROM. The variable port type
IN instruction has the advantage that the port address can be computed in the
program during execution, and by loading it in DX, the corresponding port can be
accessed using the IN instruction.
(vii) OUT: The OUT instruction transfers a byte from AL or a word from AX
to the specified port. Similar to the IN instruction, the OUT instruction has two
forms—fixed port and variable port.
Examples for fixed port OUT instruction:
(a)OUT 48H, AL ; Sends the content of AL to the port with
address 48H.
(b)OUT OFOH, AX ; Sends the content of AX to the port with
address FOH.

Examples for variable port OUT instruction:


The following example shows a part of a program having the OUT instruction.
MOV DX, 1234H ; Load the port address 1234H in DX.
OUT DX, AL ; Send the content of AL to the port with address
1234H.
OUT DX, AX ; Send the content of AX to the port with address
1234H.

(viii) LEA (load effective address): The general format of the LEA instruction is
LEA register, source. This instruction determines the offset address of the variable
or memory location called the source and puts this offset address in the indicated
16-bit register.
Example:
(a) LEA BX, COST ; Load BX with the offset address of COST in the
data segment, where COST is the name assigned
to a memory location in the data segment.
(b)LEA CX, [BX] [SI] ; Load CX with the value equal to (BX) + (SI),
where (BX) and (SI) represent the content of
BX and SI, respectively.

(ix) LDS: This instruction loads the register and DS with words from the memory.
The general form of this instruction is LDS register, memory address of first
word.
The LDS instruction copies a word from the memory location specified in the
instruction into the register, and then copies a word from the next memory location
into the DS register. LDS is useful in initializing the SI and DS registers at the start
of a string before using one of the string instructions.
442 MICROPROCESSORS AND MICROCONTROLLERS

Example:
LDS SI, E2000HJ ; Copy the content of the memory at the
offset address 2000H in the data segment to
the lower-order byte of SI, and the content
of 2001H to the higher-order byte of SI. Copy
the content at the offset address 2002H in
the data segment to the lower-order byte of
DS and the content of 2003H to the higher-
order byte of DS.

(x) LES and LSS: The LES and LSS instructions are similar to the LDS instruction,
except that instead of the DS register, the ES and SS registers, respectively, are
loaded, along with the register specified in the instruction.
(xi) LAHF: This instruction copies the lower-order byte of the flag register into
AH.
(xii) SAHF: This instruction stores the content of AH in the lower-order byte of
the flag register.
Except the SAHF and POPF instructions, no other data transfer instruction
affects the flag register.

14.3.2 Arithmetic Instructions


The arithmetic instructions in the 8086 are used to perform addition, addition
with carry, subtraction, subtraction with borrow, increment, decrement, negation
(changing sign), comparison, multiplication, division, decimal-adjust after
addition, decimal-adjust after subtraction, and processing of ASCII data. Let us
now discuss each instruction in detail.
(i) ADD: The general format of the ADD instruction is ADD destination, source.
The data from the source and destination are added and the result is placed in
the destination. The source may be an immediate number, a register, or a memory
location. The destination can be a register or a memory location. However, the
source and destination cannot both be memory locations. The data from the source
and destination must be of the same type (either bytes or words).

Example:
(a) ADD BL, 80H : Add the immediate data 80H to BL.
(b)ADD CX, 12B0H ; Add the immediate data 12B0H to CX.
(c) ADD AX, CX ; Add the content of AX and CX and store the
result in AX.
(d)ADD AL, [BX] ; Add the content of AL and the byte from the
memory at [BX] and store the result in AL.
(e) ADD CX, [SI] ; Add the content of CX and the word from the
memory at [SI] and store the result in CX.
(f) ADD [BX] , DL ; Add the content of DL with the byte from the
memory at [BX] and store the result in the
memory at [BX].
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 443

The flags AF, CF, OF, PF, SF, and ZF are affected by the execution of the
ADD instruction.
(ii) ADC: This instruction adds the data in the source and destination with the
content of the carry flag and stores the result in the destination. The general format
of this instruction is ADC destination, source.
All the rules specified for ADD are applicable to the ADC instruction.
(iii) SUB: The general form of the subtract (SUB) instruction is SUB destination,
source. It subtracts the number in the source from the number in the destination
and stores the result in the destination. Like the ADD instruction, the source may
be an immediate number, a register, or a memory location. The destination can be
a register or a memory location. However, the source and destination cannot both
be memory locations. The data from the source and destination must be of the
same type (either bytes or words).
For subtraction, the carry flag (CF) functions as the borrow flag. If the result is
negative after subtraction, CF is set. Otherwise, it is reset. The flags AF, CF, OF,
PF, SF, and ZF are affected by the SUB instruction.
Example:
(a) SUB AL, BL Subtract BL from AL and store the result i n
AL.
(b)SUB CX, BX ; Subtract BX from CX and store the result i n
CX.
(c) SUB BX, [DI] ; Subtract thei word in the memory at [DI]
from BX and store the result in BX.
(d)SUB [BP] , DL ; Subtract DL from the byte in the memory at
[BP] and store the result in the memory at
[BP],

(iv) SBB: Subtract with borrow—The general form of this instruction is SBB
destination, source. The SBB instruction subtracts the content of the source
and the carry flag from the content of the destination and stores the result in the
destination. The rules for the source and the destination are same as that for the
SUB instruction. AF, CF, OF, PF, SF, and ZF are affected by this instruction.
(v) INC: The increment (INC) instruction adds 1 to the content of a specified
register or a memory location. The data incremented may be a byte or word. While
the carry flag is not affected by this instruction, the flags AF, OF, PF, SF, and ZF
are affected.

Example:
(a)INC CL : Increment the content of CL by 1.
(b)INC AX : Increment the content of AX by 1.
(c) INC BYTE PTR [BX] ; Increment the byte in the memory at [BX] by 1.
(d)INC WORD PTR [SI] ; Increment the word in the memory at [SI] by 1.
In these examples, the terms BYTE PTR and WORD PTR are assembler
directives, which are used to specify the type of data (byte or word) to be
incremented in the memory.
444 MICROPROCESSORS AND MICROCONTROLLERS

(vi) DEC: The decrement (DEC) instruction subtracts 1 from the content of a specified
register or memory location. The data decremented may be a byte or a word. CF is
not affected, but AF, OF, PF, SF, and ZF flags are affected by this instruction.
(vii) NEG: The negate (NEG) instruction replaces the byte or word in the specified
register or memory location by its 2’s complement (i.e., changes the sign of the
data). The CF, AF, SF, PF, ZF, and OF flags are affected by this instruction.
Example:
(a)NEG AL ; Take 2’s complement of the data in AL and
store it in AL.
(b)NEG CX ; Take 2’s complement of the data in CX and
store it in CX.
(c) NEG BYTE PTR [BX] ; Take 2’s complement of the byte in the memory
at [BX] and store the result in the same
pl ace.
(d)NEG WORD PTR [SI] ; Take 2’s complement of the word in the memory
at [SI] and store the result in the same place.

(viii) CMP: The general form of the compare (CMP) instruction is CMP
destination, source. This instruction compares a byte or word in the source with a
byte or word in the destination and affects only the flags, according to the result.
The content of the source and destination are not affected by the execution of this
instruction. The comparison is done by subtracting the content of the source from
that of the destination. The AF, OF, SF, ZF, PF, and CF flags are affected by the
instruction. The rules for the source and destination are the same as those for the
SUB instruction.
Example:
After the instruction CMP AX, DX is executed, the status of CF, ZF, and SF will
be as follows:
CF ZF SF
IfAX = DX 0 1 0
IfAX>DX 0 0 0
IfAX<DX 1 0 1
(ix) MUL: The multiply (MUL) instruction is used for multiplying two unsigned
bytes or words. The general form of the MUL instruction is MUL source. The
source can be a byte or a word from a register or memory location, which is
considered as the multiplier. The multiplicand is taken by default from AL and AX
for byte and word type data, respectively. The result of multiplication is stored in
AX and DX-AX (i.e., the most significant word of the result in DX and the least
significant word of the result in AX) for byte and word type data, respectively.
(Note: Multiplying two 8-bit data gives a 16-bit result and multiplying two 16-bit
data gives a 32-bit result.)

Example:
(a)MUL CH : Multiply AL and CH and store the result in
AX.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 445

(b)MUL BX ; Multiply AX and BX and store the result in


DX-AX.
(c)MUL BYTE PTR [BX] ; Multiply AL with the byte in the memory at
[BX] and store the result in DX-AX.
If the most significant byte of the 16-bit result is OOH or the most significant
word of a 32-bit result is OOOOH, both CF and OF will be 0. Checking these flags
allows us to decide whether the leading Os in the result have to be discarded or
not. The AF, PF, SF, and ZF flags are undefined (i.e., a random number is stored
in these bits) after the execution of the MUL instruction.
(x) IMUL: The IMUL instruction is used for multiplying the signed byte or word
in a register or memory location with AL or AX, and store the result in AX or
DX-AX, respectively. If the magnitude of the result does not require all the bits of
the destination, the unused bits are filled with copies of the sign bit.
If the upper byte of a 16-bit result or the upper word of a 32-bit result contains
only copies of the sign bit (all Os or all Is), CF and OF will both be 0. Otherwise,
both will be 1. AF, PF, SF, and ZF are undefined after IMUL.
To multiply a signed byte by a signed word, the byte is moved into a word
location and the upper byte of the word is filled with copies of the sign bit. If the
byte is moved into AL, using the CBW (convert byte to word) instruction, the sign
bit in AL is extended into all the bits of AH. Thus, AX contains the 16-bit sign-
extended word.
Example:
(a) IMUL BL : Multiply AL with BL and store the
result in AX.
(b)IMUL AX : Multiply AX and AX and store the
result in DX-AX.
(c) IMUL BYTE PTR [BX] ; Multiply AL with the byte from the
memory at [BX] and store the result in
AX.
(d) IMUL WORD PTR [SI] ; Multiply AX with the word from the
memory at [SI] and store the result in
DX-AX.

(xi) DIV: The divide (DIV) instruction is used for dividing unsigned data. The
general form of the DIV instruction is DIV source, where ‘source’ is the divisor.
It can be a byte or word in a register or memory location. The dividend is taken by
default from AX and DX-AX for byte and word type data division, respectively.
Table 14.3 shows the complete details of the DIV instruction.

Table 14.3 Details of DIV instruction

Dividend (bits) Divisor (bits) Quotient (bits) Remainder (bits)


AX (16) Source (8) AL (8) AH (8)

DX-AX (32) Source (16) AX (16) DX(16)


446 MICROPROCESSORS AND MICROCONTROLLERS

If an attempt is made to divide by 0 or if the quotient is too large to fit in AL or AX


(i.e., if the result is greater than FFH in 8-bit division or FFFFH in 16-bit division),
the 8086 automatically generates a type 0 interrupt. All flags are undefined after a
DIV instruction.
Example:
(a)DIV DL ; Divide the word in AX by the byte in DL.
The quotient is stored in AL and the remainder
in AH.
(b)DIV CX ; Divide the double word (32 bits) in DX-AX by
the word in CX. The quotient is stored in AX
and the remainder in DX.
(c) DIV BYTE PTR [BX] ; Divide the word in AX by the byte from the
memory at [BX]. The quotient is stored in AL
and the remainder in AH.
(xii) IDIV: The IDIV instruction is used for dividing signed data. The general form
and the rules for the IDIV instruction are same as those for the DIV instruction.
The quotient is a signed number and the sign of the remainder is the same as the
sign of the dividend.
To divide a signed byte by a signed byte, the dividend byte is put in AL and
using the CBW (convert byte to word) instruction, the sign bit of the data in AL
is extended to AH. Thus, the byte in AL is converted to a signed word in AX. To
divide a signed word by a signed word, the dividend byte is put in AX and using
the CWD (convert word to double word) instruction, the sign bit of the data in AX
is extended to DX. Thus, the word in AX is converted to a signed double word in
DX-AX.
If an attempt is made to divide by 0 or if the quotient is too large or too small
to fit in AL and AX for 8- and 16-bit division, respectively (i.e., either the result is
greater than the decimal value +127 in 8-bit division or the decimal value +32,767
in 16-bit division, or the result is less than the decimal value -128 in 8-bit division
or the decimal value -32,767 in 16-bit division), the 8086 automatically generates
a type 0 interrupt. All flags are undefined after a DIV instruction.
(xiii) DAA: Decimal adjust AL after BCD addition—This instruction is used to
get the result of addition of two packed BCD numbers (in a packed BCD number,
two decimal digits are represented as eight bits) as a BCD number. The result of
addition must be in AL for DAA to work correctly. If the lower nibble (four bits)
in AL is greater than 9 after addition or if the AF flag is set by the addition, the
DAA instruction adds 6 to the lower nibble in AL. If the result in the upper nibble
of AL is now greater than 9 or if the carry flag is set by the addition, the DAA
instruction adds 60H to AL.
Example:
(a) Let AL = 01011000 = 58 BCD
CL = 00110101 =35 BCD
Consider the execution of the following instructions:
ADD AL, CL ; AL = 10001101 = 8DH and AF = 0 after execution
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 447

DAA : Add 0110 (decimal 6) to AL, since lower nibble in AL


is greater than 9
; AL = 10010011 = 93 BCD and CF = 0
Therefore, the result of addition is 93 BCD.
(b)Let AL = 10001000 = 88 BCD
CL = 01001001 =49 BCD
Consider the execution of the following instructions:
ADD AL, CL ; AL = 11010001 and AF = 1 after execution
DAA ; Add 0110 (decimal 6) to AL
: AL = 11010111 = D7H
; Upper nibble 1101 > 9. So add 60H (0110 0000) to AL.
; AL = 0011 0111 = 37 BCD and CF = 1
The final result is 137 BCD, taking into account the carry generated. The DAA
instruction affects AF, CF, PF, and ZF. OF is undefined after the DAA instruction
is executed.
(xiv) DAS: Decimal adjust after BCD subtraction—DAS is used to get the result
in packed BCD form after subtracting two packed BCD numbers. The result of
the subtraction must be in AL for DAS to work correctly. If the lower nibble in
AL after a subtraction is greater than 9 or if the AF is set by subtraction, the DAS
instruction subtracts 6 from the lower nibble of AL. If the result in the upper
nibble is now greater than 9 or if the carry flag is set, the DAS instruction subtracts
60H from AL.
Example:
(a) Let AL = 86 BCD = 10000110
CH = 57 BCD = 01010111
Consider the execution of the following instructions:
SUB AL, CH ; AL = 00101111 = 2FH and CF = 0 after execution
DAS ; Lower nibble of the result is 1111. So DAS subtracts
06H from AL to make AL = 00101001 = 29 BCD and CF =
0 to indicate that there is no borrow.
The result is 29 BCD.
b) Let AL = 49 BCD = 01001001
CH = 72 BCD = 01110010
Consider the execution of the following instructions:
SUB AL, CH ; AL = 1101 0111 = D7H and CF = 1 since result is
negati ve
DAS ; Subtract 0110 0000 (60H) from AL because upper nibble
in AL is greater than 9. This makes AL = 01110111 =
77 BCD and CF = 1, indicating that a borrow is
needed.
The answer is 77 BCD as 149 BCD - 72 BCD = 77 BCD. The value 149 BCD
is mentioned here, considering the borrow that is generated after the subtraction.
There are four arithmetic instructions that are used to perform operations
on unpacked BCD numbers. In an unpacked BCD number, one decimal digit is
448 MICROPROCESSORS AND MICROCONTROLLERS

represented as an 8-bit number in which the upper four bits are always zero. For
example, the decimal digit 3 is represented as 03H in unpacked BCD form.
(xv) AAA: The AAA (ASCII adjust after addition) instruction must always follow
the addition of two unpacked BCD operands in AL. When AAA is executed, the
content of AL is changed to a valid unpacked BCD number; the upper four bits of
AL are cleared. CF is set and AH is incremented if a decimal carry-out from AL
is generated.
Example:
Let AL = 05 (decimal) = 00000101
BH = 06 (decimal) = 00000110
AH = OOH
Consider the execution of the following instructions:
ADD AL, BH ; AL = 11 (decimal) and CF = 0
AAA : AL = 01 and AH = 01 and CF = 1
Addition of 5 and 6 gives a decimal result of 11, which is equal to 0101H in
unpacked BCD form. It is stored in AX. When this result is to be sent to the printer,
the ASCII code of each decimal digit is easily found by adding 30H to each byte.
(xvi) AAS: ASCII adjust after subtraction—This instruction always follows the
subtraction of one unpacked BCD operand from another in AL. It changes the
content of AL to a valid unpacked BCD number and clears the top four bits of AL.
CF is set and AH is decremented if a decimal borrow occurs.
Example:
(a) Let AL = 09 BCD = 00001001
CL = 05 BCD = 00000101
AH = OOH
Consider the execution of the following instructions:
SUB AL, CL ; AL = 04 BCD
AAS ; AL = 04 BCD and CF = 0
; AH = OOH

(b)Let AL = 05 BCD
CL = 09 BCD
AH = OOH
Consider the execution of the following instructions:
SUB AL, CL ; AL = -4 BCD (in 2’s complement form AL = FCH) and
CF = 1
AAS ; AL = 04 BCD
: CF = 1 indicating that a borrow is needed and
AH = FFH = 2’s complement of -1
AAA and AAS affect the AF and CF flags and OF, PF, SF, and ZF are left
undefined. Another salient feature of these two instructions is that it is possible
to take input data in the ASCII form of the unpacked decimal number, obtain
the result as an unpacked decimal number, and then convert it to ASCII form by
adding 30H to it.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 449

(xvii) AAD: ASCII-adjust before the division instruction modifies the dividend in
AH and AL, to prepare for the division of two valid unpacked BCD operands. After
the execution of AAD, AH is cleared and AL contains the binary equivalent of the
original unpacked two-digit numbers. Initially, AH contains the most significant
unpacked digit and AL contains the least significant unpacked digit.
Example:
To perform the operation 32 (decimal)/08 (decimal)
Let AH = 03H ; Upper decimal digit in the dividend
AL = 02H ; Lower decimal digit in the dividend
CL = 08H ; Divisor
Consider the execution of the following instructions:
AAD ; AX = 0020H (binary equivalent of the decimal value
32 in 16-bit form)
DIV CL ; Divide AX by CL. AL contains the quotient and AH the
remainder.
AAD affects the PF, SF, and ZF flags. AF, CF, and OF are undefined after
execution of AAD.

(xviii) AAM: The AAM (ASCII adjust AX after multiplication) instruction corrects
the value obtained by multiplication of two valid unpacked decimal numbers. The
higher-order digit is placed in AH and the lower-order digit in AL.
Example:
Let AL = 05 (decimal)
CL = 09 (decimal)
Consider the execution of the following instructions:
MUL CH ; AX = 002DH = 45 (decimal)
AAM ; AH = 04 and AL = 05 (unpacked BCD form of the decimal
number 45)
OR AX, 3030H ; To get the ASCII code of the result In AH and AL
(Note: This instruction is used only when the result
is needed in ASCII form.)
AAM affects the same flags as AAD.

14.3.3 Logical Instructions


The logical instructions in the 8086 include AND, OR, XOR, NOT, and TEST.
Let us now discuss each instruction in detail.
(i) AND: The AND instruction performs a logical AND operation between
the corresponding bits in the source and destination and stores the result in the
destination. The source and the destination can be either bytes or words. The
general form of the AND instruction is AND destination, source.
The rules for the destination and source for the AND instruction are the same
as those for the ADD instruction. CF and OF are both 0, and PF, SF, and ZF are
updated after the AND instruction is executed. AF is undefined. PF is affected
only when the AND operation is performed on an 8-bit operand.
450 MICROPROCESSORS AND MICROCONTROLLERS

(ii) OR: The OR instruction performs a logical OR operation between


the corresponding bits in the source and destination and stores the result in the
destination. The source and the destination can be either bytes or words. The
general form of the OR instruction is OR destination, source.
The rules for the source and destination and the way flags are affected are the
same as the AND instruction.
(iii) XOR: The XOR instruction performs a logical XOR operation between
the corresponding bits in the source and destination and stores the result in the
destination. The source and the destination can be either bytes or words. The
general form of the XOR instruction is XOR destination, source.
The rules for the source and destination and the way flags are affected are the
same as the AND instruction.
(iv) NOT: The NOT instruction inverts each bit (i.e., performs l’s complement)
of the byte or word at a specified destination. The destination can be a register or
a memory location. The NOT instruction does not affect any flags.
Example:
(a) NOT AL : Take l’s complement of AL.
(b)NOT BX ; Take l’s complement of BX.
(c) NOT LSI] ; Take l’s complement of the data in the memory
at LSI].

(v) TEST: This instruction ANDs the content of a source byte or word with the
content of the specified destination byte or word. The flags are updated, but
neither operand is changed. The TEST instruction is often used to set flags before
a conditional jump instruction. The general form of TEST instruction is TEST
destination, source. The rules for the source and destination and the way flags are
affected are the same as the AND instruction.

Example:
Let AL = 0111 1111 =7FH
TEST AL, 80H ; AL = 7FH (unchanged)
ZF = 1 since (AL) AND (80H) = OOH; SF = 0; PF = 1

14.3.4 Flag Manipulation Instructions


The 8086 has a few instructions exclusively for performing operations on the flags
in the flag register. They are used to set or clear specific flags in the flag register,
to push or pop the flag register content into or from the stack, and to transfer the
lower-order byte of the flag register to the AH register and vice versa. Table 14.4
indicates the function of the different flag manipulation instructions in the 8086.

Table 14.4 Flag manipulation instructions

Mnemonics Function

LAHF Load the lower-order byte of the flag register in AH


SAHF Store AH in the lower-order byte of the flag register
(Contd)
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 451

Table 14.4 Flag manipulation instructions (Contd)

Mnemonics Function
PUSHF Push the flag register’s content onto the stack
POPF Pop the top word of the stack onto the flag register
CMC Complement the carry flag (CF = complement of CF)
CLC Clear the carry flag (CF = 0)
STC Set the carry flag (CF = 1)
CLD Clear the direction flag (DF = 0)
STD Set the direction flag (DF = 1)
CLI Clear the interrupt flag (IF = 0)
STI Set the interrupt flag (IF = 1)

14.3.5 Control Transfer Instructions


The control transfer instructions of the 8086 are used to call a subroutine, return
from a subroutine, and branch conditionally or unconditionally in a program. In
conditional branching, there are two categories depending on whether unsigned or
signed data is involved. The terms ‘above’ and ‘below’ are used when referring
to the magnitude of unsigned numbers. The binary number 10000000 (= 128 in
decimal form) is above the binary number 01000000 (= 64 in decimal form). The
terms ‘greater’ and ‘lesser’ are used when referring to the relationship between
two signed numbers. ‘Greater’ means more positive. The signed binary number
00001111 (= +15 in decimal form) is greater than the signed binary number
10000001 (= -127 in decimal form). The control transfer instructions of the 8086
are given in Table 14.5.
Table 14.5 Control transfer instructions

Mnemonics Description
Unconditional transfers

JMP addr Jump unconditionally to addr


CALL addr Call the procedure or subroutine starting at addr
RET Return from the procedure or subroutine
Conditional transfers

J A addr Jump if above to addr (jump if CF = ZF = 0)


JAE addr Jump if above or equal to addr (jump if CF = 0)
JB addr Jump if below to addr (jump if CF = 1)
JBE addr Jump if below or equal to addr (jump if CF = 1 or ZF = 1)

JC addr Jump if carry to addr (jump if CF = 1)


JCXZ addr Jump if CX = 0 to addr

JE addr Jump if equal to addr (jump if ZF = 1)


(Contd)
452 MICROPROCESSORS AND MICROCONTROLLERS

Table 14.5 Control transfer instructions (Contd)

Mnemonics Description

JG addr Jump if greater to addr (Jump if ZF = 0 and SF = OF)


JGE addr Jump if greater or equal to addr (Jump if SF = OF)
JL addr Jump if lesser to addr (Jump if SF OF)
JLE addr Jump if lesser or equal to addr (Jump if ZF = 1 or
SF # OF)
JNA addr Jump if not above to addr (Jump if CF = 1 or ZF = 1)
JNAE addr Jump if not above or equal to addr (Jump if CF = 1)
JNB addr Jump if not below to addr (Jump if CF = 0)
JNBE addr Jump if not below or equal to addr (Jump if CF = ZF = 0)
JNC addr -, z Jjjjnp if no carry to addr (Jump if CF = 0)
JNE addr Jump if not equal to addr (jump if ZF = 0)
JNG addr Jump if not greater to addr (jump if ZF = 1 or SF OF)
JNGE addr Jump if not greater or equal to addr (jump if SF OF)
JNL addr Jump if not lesser to addr (Jump if SF = OF)
JNLE addr Jump if not lesser or equal to addr (Jump if ZF = 0 and
SF = OF)
JNO addr Jump if no overflow to addr (Jump if OF = 0)
JNP addr Jump if no parity to addr (Jump if PF = 0)
JNS addr Jump if no sign to addr (jump if SF = 0)
JNZ addr Jump if no zero to addr (jump if ZF = 0)
JO addr Jump if overflow to addr (jump if OF =1)
JP addr Jump if parity to addr (jump if PF = 1)
JPE addr Jump if parity is even to addr (jump if PF = 1)
JPO addr Jump if parity is odd to addr (jump if PF = 0)
JS addr Jump if sign to addr (jump if SF = 1)
JZ addr Jump if zero to addr (jump if ZF = 1)

In this table, ‘addr’ is the target address in the memory, to which the 8086 has
to jump, if the condition is satisfied while executing conditional jump instructions,
‘addr’ is also the target address to which the 8086 has to jump while executing
unconditional jump instructions. In the CALL instruction, ‘addr’ indicates the
address where the subroutine is located. In the case of conditional jump instructions,
the target address must be located at a relative address, which is in the range of
+127 bytes to -128 bytes from the instruction following the conditional jump
instruction.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 4 53

Some of the conditional jump instructions have identical effects as follows:


JE—JZ JNE—JNZ JL—JNGE JNL—JGE
JG—JNLE JNG—JLE JB—JNAE JNB—JAE
JA—JNBE JNA—JBE JP—JPE JNP—JPO
There are a few instructions in the 8086 that are used to implement loops.
These are given in Table 14.6.
Table 14.6 Loop instructions

Mnemonics Description
LOOP addr Decrement CX. Go to addr if CX # 0.
LOOPE addr Loop while equal (Decrement CX. Go to addr if CX # 0 and
ZF= 1.)
LOOPZ addr Same as LOOPE
LOOPNE addr Loop while not equal (Decrement CX. Go to addr if CX # 0 and
ZF = 0.)
LOOPNZ addr Same as LOOPNE

In this table, ‘addr’ is the target address, which must be located at a relative
address in the range of+127 bytes to -128 bytes from the instruction following the
LOOP instruction.
The use of the LOOP instruction in a program is explained here with an
example:
MOV CX, 100
AGAIN : MOV AL, BL

LOOP AGAIN ; Decrement CX and if CX * 0, go to AGAIN.


In this example, the loop starting from the address AGAIN is repeated 100
times, since CX is initialized to 100.
Finally, the software interrupt-related instructions (given in Table 14.7) can
also be used to cause the 8086 to jump to another place in the memory and execute
the interrupt service routine for a particular interrupt. The IRET instruction is used
to return the control from the interrupt service routine to the main program.
Table 14.7 Interrupt-related instructions

Mnemonics Description

INT n Software interrupt instruction where n is the interrupt type, n can be


any number between OOH and FFH. This instruction causes the 8086
to execute the interrupt service routine (ISR) of interrupt type n.
INTO This instruction interrupts the 8086 if there is an overflow (i.e.,
OF = 1).
IRET This instruction returns the control from the interrupt service routine to
the main program.

The 8086 interrupts are discussed in detail in Chapter 15.


454 MICROPROCESSORS AND MICROCONTROLLERS

14.3.6 Shift/Rotate Instructions


The shift/rotate instructions perform logical left-shift and right-shift, and arithmetic
left-shift and right-shift operations. The arithmetic left-shift (SAL) and logical
left-shift (SHL) have the same function, but the former is used on signed data,
whereas the latter is used on unsigned data.
(i) SAL/SHL: The general format of the SAL/SHL instruction is SAL/SHL
destination, count. The destination can be a register or a memory location and a
byte or a word. This instruction shifts each bit in the destination a specified number
of bit positions to the left. As a bit is shifted out of the LSB position, a 0 is placed
in the LSB position. The MSB is shifted into the carry flag (CF) as follows:
CF <------ MSB <-------- LSB <------0
If the number of shifts to be done is 1, it can be directly specified in the
instruction, with a count value equal to 1. For shifts of more than one bit position,
the desired number of shifts is loaded into the CL register and CL is placed in the
count position of the instruction. CF, SF, and ZF are affected according to the
result. PF has meaning only when AL is used as the destination. The SAL and
SHL instructions can be used to multiply a signed number and unsigned number,
respectively, by a power of 2. Shifting a number left by one bit and two bits
multiplies the number by two and four, respectively, and so on.
Example:
(a) SAL AX, 1 ; Shift left the content of AX by one
bit.
(b)SAL BL, 1 ; Shift left the content of BL by one
bi t.
(c)SAL BYTE PTR [SI], 1 ; Shift left the byte content of the
memory at [SI] by one bit.
(d)SAL WORD PTR [BX], 1 ; Shift left the word content of the
memory at [BX] by one bit.
(e)MOV CL, 05
SAL AX, CL : Shift left the content of AX by five
bits.
(f) MOV CL, 03
SAL BYTE PTR [SI], CL ; Shift left the byte content of the
memory at [SI] by three bits.

(ii) SAR: The general format of the SAR instruction is SAR destination, count.
The destination can be a register or a memory location and a byte or a word. This
instruction shifts each bit in the destination a specified number of bit positions to
the right. As a bit is shifted out of the MSB position, a copy of the old MSB is put
in the MSB position (i.e., the sign bit is copied into the MSB). The LSB will be
shifted into the carry flag (CF) as follows:
MSB------► MSB-------- > LSB ----- > CF
The rules for the count value in the instruction are the same as those for the SAL
instruction. CF, SF, and ZF are affected according to the result. PF has meaning
only when AL is used as the destination.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 455

(iii) SHR: The general format of the SHR instruction is SHR destination, count.
The destination can be a register or a memory location and a byte or a word. This
instruction shifts each bit in the destination a specified number of bit positions
to the right. As a bit is shifted out of the MSB position, a 0 is placed in the MSB
position. The LSB is shifted into the carry flag (CF) as follows:
0----- > MSB-------- > LSB ----- > CF
The rules for the count value in the instruction are same as those for the SHL
instruction. CF, SF, and ZF are affected according to the result. PF has meaning
only when an 8-bit destination is used.
(iv) ROR: This instruction rotates all the bits of the specified byte or word by
a specified number of bit positions to the right. The operation done when ROR is
executed is as follows:

CF MSB---------- > LSB

The general format of the ROR instruction is ROR destination, count. The data
bit moved out of the LSB is copied into CF. ROR affects only CF and OF. In the
single-bit rotate operation, if the sign bit (i.e., the MSB) changes after the execution
of ROR, OF is set. This is applicable only for the single-bit rotate operation. ROR
is used to swap nibbles in a byte and to swap bytes in a word. It can also be used
to rotate a bit in a byte/word into CF, where it can be checked and acted upon by
the JC and JNC instructions. CF contains the bit most recently rotated out of the
LSB, in the case of a multiple bit rotate operation. The rules for the count value
are same as those for the shift instruction.

Example:
(a) ROR CH, 1 ; Rotate right the byte in CH by one bit
posi ti on.
(b)ROR BX, CL ; Rotate right the word in BX by the
number of bit positions given by CL.
(c) ROR BYTE PTR [SI], 1 ; Rotate right the byte in the memory at
offset [SI] by one bit position.
(d) ROR WORD PTR [BX], CL ; Rotate right the word in the memory at
offset [BX] by the number of bit
positions given by CL.

(v) ROL: ROL rotates all the bits in a byte or word in the destination to the left, by
one or more bit positions, using CL, as follows:

CF<------MSB <--------- LSB


I t
The data bit moved out of the MSB is copied into CF. ROL affects only CF
and OF. In the single-bit rotate operation, if the sign bit (i.e., the MSB) changes
after the execution of ROL, OF is set. This is applicable only for the single-bit
456 MICROPROCESSORS AND MICROCONTROLLERS

rotate operation. ROL is used to swap nibbles in a byte or swap bytes in a word.
It can also be used to rotate a bit in a byte/word into CF, where it can be checked
and acted upon by the JC and JNC instructions. CF contains the bit most recently
rotated out of the LSB, in the case of the multiple bit rotate operation.
(vi) RCR: RCR rotates the byte or word in the destination right, through the carry
flag (CF), either by one bit position or by the number of bit positions given by CL,
as follows:

CF----- > MSB * LSB

The flags affected are the same as those affected during the execution of
ROR.
(vii) RCL: RCL rotates the byte or word in the destination left through the carry
flag (CF), either by one bit position or by the number of bit positions given by CL,
as follows:

CF <----- MSB <--------- LSB


I____________ f
The flags affected are the same as those affected during the execution of
ROL.

14.3.7 String Instructions


The 8086 string manipulation instructions are given in Table 14.8. The string
instructions operate on elements of strings, bytes, or words. The register SI
contains the offset address of an element (byte or word) in the source string,
which is present in the data segment. The register DI contains the offset address
of an element (byte or word) in the destination string, which is present in the extra
segment. The source string is in the data segment at the offset address given by
SI; the destination string is in the extra segment at the offset address given by
DI. After each string operation, SI and/or DI are automatically incremented or
decremented by 1 or 2 (for byte or word operation), according to the D flag in the
flag register. If D = 0, SI and/or DI are automatically incremented and if D = 1, SI
and/or DI are automatically decremented.

Table 14.8 String instructions in the 8086

Mnemonics Function

MOVSB Move the string byte from DS:[SI] to ES:[DI].


MOVSW Move the string word from DS:[SI] to ES:[DI].
CMPSB Compare string bytes (done by subtracting the byte at ES: [DI]
from the byte at DS: [SI]). Only flags are affected; the content
of the bytes compared is unaffected.
(Contd)
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 457

Table 14.8 String instructions in the 8086 (Contd)

Mnemonics Function
CMPSW Compare string words (done by subtracting the word at
ES: [DI] from the word at DS: [SI]). Only flags are affected;
the content of the words compared is unaffected.
LODSB Load the string byte at DS:[SI] into AL.
LODSW Load the string word at DS:[SI] into AX.
STOSB Store the string byte in AL at ES:[DI].
STOSW Store the string word in AX at ES:[DI],
SCASB Compare string bytes (done by subtracting the byte at ES: [DI]
from the byte at AL). Only flags are affected; the content of the
bytes compared is unaffected.
SCASW Compare string words (done by subtracting the word at ES:
[DI] from the byte at AX). Only flags are affected; the content
of the words compared is unaffected.
REP Decrement CX and repeat the following string operation if
CX # 0.
REPE or REPZ Decrement CX and repeat the following string operation if
CX # 0andZF= I.
REPNE or REPNZ Decrement CX and repeat the following string operation if
CX 0 and ZF = 0.

The REP (repeat) prefix placed before a string instruction causes the string
instruction to be executed CX times.
Example:
(a)MOV CX, 32H ; Load 32H (= decimal 50) in CX.
(b)REP MOVSW ; Execute MOVSW instruction 50 times.
Execution of these two instructions causes the moving of a string having 50
words from the data segment to the extra segment.

14.3.8 Machine or Processor Control Instructions


The machine/processor control instructions in the 8086 include HLT, LOCK,
NOP, ESC, and WAIT. Let us discuss each instruction in detail.
(i) HLT: The halt instruction stops the execution of all instructions and places
the processor in the halt state. An interrupt or a Reset signal causes the
processor to resume execution from the halt state.
(ii) LOCK: The lock instruction provides the processor an exclusive hold on
the use of the system bus. It activates an external locking signal (LOCK)
of the processor and is placed as a prefix to the instruction for which a
lock is to be asserted. The lock functions only with the XCHG, ADD, OR,
ADC, SBB, AND, SUB, XOR, NOT, NEG, INC, and DEC instructions,
458 MICROPROCESSORS AND MICROCONTROLLERS

when they involve a memory operand. An undefined opcode trap interrupt


is generated, if a LOCK prefix is used with any instruction not listed here.
(iii) NOP: No operation—This instruction is used to insert a delay in software
delay programs.
(iv) ESC: This instruction is used to pass instructions to a coprocessor such as
the 8087, which shares the address and data bus with an 8086. Instructions
for the coprocessor are represented by a 6-bit code embedded in the escape
instruction.
As the 8086 fetches instruction bytes from the memory, the coprocessor
catches these bytes from the data bus and puts them in a queue. However,
the coprocessor treats all the normal 8086 instructions as NOP instructions.
When the 8086 fetches an ESC instruction, the coprocessor decodes the
instruction and carries out the action specified by the 6-bit code specified in
the instruction.
(v) WAIT: When this instruction is executed, the 8086 checks the status of its
TEST input pin and if the TEST input is high, it enters an idle condition
during which it does not do any processing. The 8086 remains in this
state until the 8086’s TEST input pin is made low or an interrupt signal
is received on the INTR or NMI pins. If a valid interrupt occurs while
the 8086 is in this idle state, it returns to the idle state after the interrupt
service routine is executed. The WAIT instruction does not affect flags. It
is used to synchronize the 8086 with external hardware such as the 8087
coprocessor.

14.4 8086 ASSEMBLY LANGUAGE PROGRAMMING


A few assembly language programming examples, similar to the assembly
language programming of the 8085, are given in this section. These programs
can be converted into machine language programs and executed in an 8086-based
system, either by manually finding the opcode for each instruction or by using an
assembler. As finding the opcode of each instruction of the 8086 manually is time
consuming, the line assembler or assembler is normally used. The line assembler
converts each mnemonic of an instruction immediately into an opcode as it is
entered in the system and this type of assembler is used in microprocessor trainer
kits. The line assembler is stored in any one of the ROM type memories in the
trainer kit. The assembler needs a personal computer for generating the opcodes
of an assembly language program. The generated opcodes can be downloaded
to the microprocessor-based system such as the microprocessor trainer kit or the
microprocessor-based prototype hardware through the serial or parallel port of the
computer.
There are many assemblers such as MASM (Microsoft Macro Assembler),
TASM (Turbo Assembler), and DOS Assembler, which are used to convert the
8086 assembly language program into machine language program. While using
these assemblers, the assembly language program is written using assembler
directives. Assembler directives are commands to the assembler to indicate the
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 459

size of a variable (either byte or word), number of bytes or words to be reserved in


the memory, value of a constant, name of a segment, etc., in a program. Assembler
directives are not converted directly into opcode, but are used to generate the
proper opcode of an instruction. The use of Microsoft’s assembler is discussed in
this section.

14.4.1 Writing 8086 Programs using Line Assembler


While writing 8086 programs using the line assembler, assembler directives are
not used. The segment address and offset address of the data are directly mentioned
in the instructions. The following examples illustrate this concept.
Example 14.1:
Write a program to add a word type data located at the offset address 0800H (least
significant byte) and 0801H (most significant byte) in the segment address 3000H
to another word type data located at the offset address 0700H (least significant
byte) and 0701H (most significant byte) in the same segment. Store the result at the
offset address 0900H and 0901H in the same segment. Store the carry generated in
the addition in the same segment at the offset address 0902H.
Solution:
MOV AX, 3000H
MOV OS, AX ; Initialize DS with the value 3000H.
MOV AX, [800H] ; Move the first data word to AX.
ADD AX, T700H] ; Add AX with the second data word.
MOV E900HJ, AX ; Store AX at the offset addresses
900H and 901H.
JC CARRY ; If carry = 1, jump to CARRY.
MOV E902H] , OOH ; If there is no carry, store OOH at
the offset address 902H.
JMP END; Jump to END.
CARRY: MOV [902H], 01H ; Store 01H at the offset address 902H
END: HLT ; Stop.

Note:
(i) To initialize a segment register with a value, the value is first loaded in one of
the general-purpose registers such as AX or BX. It is then moved to the segment
register. In this example, AX is used to load 3000H into DS.
(ii) Sometimes, instead of using the HLT instruction at the end, the software
interrupt instruction (INT) may be used to return the control to the monitor program
after executing the program.
Example 14.2:
Write a program to subtract the byte content of the memory location 3000H: 4000H
from the byte content of the memory location 4000H: 5000H and store the result at
the location 2000H: 3000H. Assume that the input data and the result lie between
-128 and +127, and that the negative numbers are represented in 2’s complement
form. (Note: 3000H: 4000H represents the segment address of 3000H and the
offset address 4000H in that segment).
460 MICROPROCESSORS AND MICROCONTROLLERS

Solution:
MOV BX, 3000H
MOV DS, BX ; Initialize DS with the segment address
3000H.
MOV CL, [4000H] ; Get the subtrahend from the offset address
4000H.
MOV BX, 4000H
MOV DS, BX ; Initialize DS with the segment address
4000H.
MOV AL, L5000H] ; Get the minuend at the offset address 5000H
to AL.
SUB AL, CL : AL <- AL - CL
MOV BX, 2000H
MOV DS, BX ; Initialize DS with the segment address
2000H.
MOV [3000H], AL ; Store AL at the offset address 3000H.
HLT : Stop.
Note: After the execution of the program, if the result is positive, its MSB and
carry are 0. If the result is negative, it is represented in 2’s complement form; its
MSB and carry are 1.
Example 14.3:
Write a program to move a word string 200 bytes (i.e., 100 words) long from the
offset address 1000H to the offset address 3000H in the segment 5000H.
Solution:
Using the REP prefix with the MOVSW instruction, the program size can be
reduced in comparison with a program that uses the MOV instruction for the same
task.
MOV AX, 5000H
MOV DS, AX ; Initialize DS with the segment address 5000H.
MOV ES, AX ; Initialize ES with the segment address 5000H.
MOV SI, 1000H ; Initialize SI with the offset address of the
source (i.e., 1000H).
MOV DI, 3000H ; Initialize DI with the offset address of the
destination (i.e., 3000H).
MOV CX, 100 ; Initialize CX with the numberof words in the string
(decimal value of 100 or 64H).
CLD ; Clear the D flag for auto-increment mode.
REP MOVSW ; Execute MOVSW instruction CX times.
HLT : Stop.
Note:
(i) The MOVSB instruction can be used in this program instead of MOVSW, but
CX must be loaded with the value 200.
(ii) As D is 0, every time MOVSW is executed, the SI and DI registers are
incremented by 2, to point the next word in the string.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 461

Example 14.4:
Write a program to find the smallest word in an array of 100 words stored
sequentially in the memory, starting at the offset address 1000H in the segment
address 5000H. Store the result at the offset address 2000H in the same segment.
Solution:
MOV CX, 99 ; Initialize CX with the number of
comparisons (= 100 - 1).
MOV AX, 5000H
MOV OS, AX : Initialize DS with the segment address
5000H.
MOV SI, 1000H ; Initialize SI with the offset address
1000H.
MOV AX, [SI] : Move the first word to AX.
START: INC SI
INC SI : Increment SI twice to point the next
word.
CMP AX, [SI] ; Compare the next word with the word in AX.
JC REPEAT ; If AX is smaller, jump to REPEAT.
MOV AX, [SI] ; Replace the word in AX with the smaller
word.
REPEAT: LOOP START ; Repeat the operation from START.
MOV [2000H], AX : Store the smallest number in AX at the
offset address 2000H.
HLT ; Stop.

Examples 14.5:
Write a program to find the number of positive and negative data items in an array
of 100 bytes of data stored from the memory location 3000H: 4000H. Store the
result in the offset addresses 1000H and 1001H in the same segment. Assume that
the negative numbers are represented in 2’s complement form.
(Note: The basic principle used here is that the MSB for a positive number is 0 and
that for a negative number is 1.)
Solution:
MOV AX, 3000H
MOV DS, AX ; Initialize DS with 3000H.
MOV CX, 100 ; Move the number of data items to CX.
MOV BX, 4000H ; Move the starting offset address of the
array to BX.
MOV DH, OOH ; Initialize DH with OOH to store the number of
positive data items.
MOV DL, OOH ; Initialize DL with OOH to store the number of
negative data items.
L2: MOV AL, [BX] ; Move a byte data from the array to AL.
ROL AL, 01 ; Rotate AL left by one bit. Now the MSB in AL
goes to the carry flag and also to the LSB of
AL.
462 MICROPROCESSORS AND MICROCONTROLLERS

JC NEG : If the carry f1 a9 is 1, the data is negative.


So jump to NEG.
INC DH ; If the carry flag is 0, the data is positive.
So increment DH.
JMP LI ; Jump to LI.
NEG: INC DL ; Increment DL.
LI: INC BX ; Increment BX to point to the next data.
LOOP L2 ; Repeat the process from L2 to check all the
data items in the array.
MOV [1000H], DH ; Store the content of DH (the number of positive
data items) at the offset address 1000H.
MOV [1001H] , DL : Store the content of DL (the number of negative
data items) at the offset address 1001H.
HLT ; Stop.

Example 14.6:
Write a program to find the seven-segment code of a digit between 0 and 9 or a
character between A and F. Assume that the seven-segment code of the characters
is stored in the memory starting at the address 2000H: 1000H. The result must be
stored at the offset address 2000H in the same segment.
Solution:
MOV AX, 2000H
MOV DS, AX ; Initialize DS with the value 2000H.
MOV BX, 1000H : Initialize BX with the starting offset address
of the table containing the seven - segment
codes.
MOV AL, 03 ; Load the number (here ‘3’) whose seven - segment
code is to be found in AL.
XLAT ; Using XLAT instruction, move the seven­
segment code of 03 to AL.
MOV [2000H], AL ; Store the result at the offset address
2000H.
HLT ; Stop.

Memory Address
Seven-segment code of 0 2000H: 1OOOH
Seven-segment code of 1 2000H: 1001H
Seven-segment code of 2 2000H: 1002H

Seven-segment code of F 2000H: 100FH


ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 463

Note: When the XLAT instruction is executed in this example, the content of BX
(= 1000H) is added to the content of AL (= 03H) to form an offset address (=
1003H) and the data in that offset address (seven-segment code of 03H) is moved
to AL. This technique is called look-up table technique.
Example 14.7:
Write a program to convert the 8-bit packed BCD number stored in the memory
location 3000H : 2000H into a binary number and store it in the offset address
2001H in the same segment.
Solution:
MOV AX, 3000H
MOV DS, AX ; Initialize DS with 3000H.
MOV AL, E2000HJ ; Move the 8-bit BCD number to AL.
MOV BL, AL ; Store a copy of the BCD number in BL.
AND AL, OFOH ; Mask the lower-order nibble in AL.
MOV CL, 04
ROR AL, CL ; Rotate AL right four times, to get the upper
nibble of the BCD number.
MOV BH, OAH ; Move OAH to BH.
MUL BH ; Multiply AL and BH, and store the result in
AL.
AND BL, OFH ; Mask the upper nibble in BL.
ADD AL, BL ; Add the contents of AL and BL.
MOV [2001H], AL ; Store the result in AL at the offset address
2001H.
HLT ; Stop.

Note:
(i) When the most significant digit of a hexadecimal data is any one of the digits
between A and F, it is preceded by 0, while writing in the program.
(ii) The binary number corresponding to an 8-bit packed BCD number is obtained
by multiplying the decimal value 10 (= OAH) with the upper digit of the BCD
number and adding the result with the lower digit of the BCD number. Since the
maximum 8-bit BCD number is 99 and the corresponding binary number is 63H
(= 9 x OAH + 9), the result in this program is also 8 bits. The result in AH is ignored
in the MUL BH instruction in this program, as AH = OOH after multiplication.
Example 14.8:
Write a program to convert the given 8-bit binary number into ASCII codes. The 8-
bit binary number is present in the memory location 2000H: 5000H and the result
is to be stored at the offset addresses 1000H and 1001H in the same segment.

Solution:
MOV AX, 2000H
MOV DS, AX : Initialize DS with 2000H.
MOV AL, [5000H] ; Move the binary data to AL.
MOV BL, AL ; Save a ropy of AL in BL.
464 MICROPROCESSORS AND MICROCONTROLLERS

ANL AL, OFOH Mask the lower nibble in AL.


MOV CL, 04
ROR AL, CL Rotate AL right four times, to get the upper
nibble.
CALL ASCII Call the subroutine ASCII.
MOV E1000H], AL Store the result in AL in the memory.
MOV AL, BL Move the binary data again to AL.
ANL AL, OFH Mask the upper nibble in AL.
CALL ASCII Call the subroutine ASCII.
MOV E1001H], AL Store the result in AL in the memory.
JMP LI Jump to LI.
ASCII: CMP AL, OAH Compare AL with the value OAH.
JC L2 If AL is lesser than OAH, go to L2.
ADD AL, 07H Add 07H witb'AL.
L2: ADD AL, 30H Add 30H with AL.
RET Return to the main program.
LI: HLT Stop.

Note: The ASCII code of the 8-bit binary number, say F8H, is obtained by first
splitting the binary number into two digits, F and 8, and then finding the ASCII
codes of F and 8 separately. The ASCII code of a digit between 0 and 9 is obtained
by adding 30H to the digit and the ASCII code of a digit between A and F is
obtained by adding 37H to the digit. The ASCII codes of F and 8 are 46H and
38H, respectively.
Example 14.9:
Write a program to add the two BCD data 29H and 98H and store the result in
BCD form in the memory locations 2000H: 3000H and 2000H: 3001H.
Solution:
MOV AL, 29H ; Move the first BCD data to AL.
ADD AL, 98H ; Add the second BCD data with AL.
DAA ; Decimal-adjust AL to get the result in
BCD form.
MOV BX, 2000H
MOV DS, BX ; Initialize DS with 2000H.
MOV E3000H], AL; Store the content of AL, which is the lower
byte of the result in the memory.
JC LI ; If the carry flag is 1, go to LI.
MOV E3001HJ, OOH ; Store OOH in the memory, since the carry is
0.
JMP L2 ; Go to L2.
LI: MOV E3001H], 01H Store 01H in memory, since the carry is 1.
L2: HLT ; Stop.

Example 14.10:
Write a program to convert the 8-bit binary number FFH into a BCD number. The
result is to be stored at memory locations 3000H: 2000H and 3000H: 2OO1H.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 465

Solution:
MOV AX, OOFFH : Move the data FFH to AX, with the upper byte
as OOH.
MOV BL, 100 ; Store the decimal value 100 (or 64H) in BL.
DIV BL ; Divide AX by BL to find the number of hundreds
in the binary number.
MOV DL, AL ; Move the quotient in AL (number of hundreds)
to DL.
MOV AL, AH ; Move the remainder in AH to AL.
MOV AH, 00 ; Clear AH.
MOV BL, 10 ; Store the decimal value 10 (or OAH) in BL.
DIV BL ; Divide AX by BL to find the number of tens in
the binary number. AH has the remainder, which
is the number of ones in the binary number.
MOV CL, 04
ROR AL, CL ; Rotate content of AL right by 4 bits to
place number of tens in upper nibble of AL.
OR AL, AH ; Perform OR operation on AL and AH to
concatenate the number of tens and ones.
MOV BX, 3000H
MOV DS, BX : Initialize DS with 3000H.
MOV L2000H], DL ; Move the value of DL to the memory.
MOV E2001H], AL : Move the value of AL to the memory.
HLT ; Stop.

Note: The binary number FFH when converted to BCD gives the result 255, as
there are two hundreds, five tens, and five ones in it. In this program, 02H is stored
in the offset address 2000H and 55H is stored in the offset address 2001H in the
data segment.

14.4.2 8086 Assembler Directives


An assembler is a program that is used to convert an assembly language program
into an equivalent machine language program. The assembler finds the address of
each label and substitutes the value of each constant and variable in the assembly
language program during the assembly process, to generate the machine language
code. While performing these operations, the assembler may find syntax errors.
They are reported to the programmer at the end of the assembly process. The
logical and other programming errors are not found by the assembler.
For completing these tasks, an assembler needs some commands from the
programmer—the required storage class for a particular constant or a variable
such as byte, word, or double word, the logical name of the segments such as
CODE, STACK, or DATA, the type of procedures or routines such as FAR,
NEAR, PUBLIC, or EXTRN, the end of a segment, etc. These types of commands
are given to the assembler using predefined alphabetical strings called assembler
directives, which help the assembler to correctly generate the machine codes for
the assembly language program.
466 MICROPROCESSORS AND MICROCONTROLLERS

In addition, there are a few operators that perform the addition or subtraction
operation on constants or labels. The assembler directives commonly used in
Microsoft Macro Assembler or Turbo Assembler are as follows:
Assembler Directives for Variable and Constant Definition
The assember directives for variable and constant definition are as follows:
(i) DB, DW, DD, DQ, and DT: The directives DB (define byte), DW (define word),
DD (define double word), DQ (define quad word), and DT (define ten bytes) are
used to reserve one byte, one word (i.e., 2 bytes), one double word (i.e., 2 words),
one quad word (i.e., 4 words), and ten bytes in the memory, respectively, for
storing constants, variables, or strings.
Example:
(a) DATA1 DB 20H ; Reserve one byte for storing
DATA1 and assign the value 20H
to it.
(b) ARRAY1 DB 10H, 20H, 30H ; Reserve three bytes for storing
ARRAY1 and initialize it with
the values 10H, 20H, and 30H.
(c) CITY DB “MADURAI” ; Store the ASCII code of the
characters specified within
double quotes in the array or
list named CITY.
(d) DATA2 DW 1020H ; Reserve one word for storing
DATA2 and assign the value
1020H to it.
(e) ARRAY2 DW 1030H, 2000H,
3000H, 4000H : Reserve four words for storing
ARRAY2 and initialize them with
the specified values.
(f) DATA3 DD 1234ABCDH ; Initialize DATA3 as a double
word with 123ABCDH.
(g) DATA4 DQ 1234ABCD5678EFBBH ; Initialize DATA4 as a quad word
with 1234ABCD5678EFBBH.
(h) DATA5 DT 123456789ABCDEFl2345H; Initialize DATA5 as a series
of 10 bytes having the value
123456789ABCDE Fl2345H.
The directive DUP (duplicate) is used to reserve a series of bytes, words,
double words, or ten bytes and is used with DB, DW, DD, and DT, respectively.
The reserved area can be either filled with a specific value or left uninitialized.

Example:
(a) Array DB 20 DUP (0) ; Reserves 20 .bytes in the memory
for the array named ARRAY and
initializes all the elements
of the array to 0 (due to the
presence of 0 within the bracket
near the DUP directive).
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 467

(b) ARRAY1 DB 25 DUP (?) ; Reserves 25 bytes in the memory


for the array named ARRAY1 and
keeps all the elements of array
uninitialized (due to the
question mark present within
the bracket near the DUP
di recti ve).
(c) ARRAY2 DB 50 DUP (64H) ; Reserves 50 bytes in the memory
for the array named ARRAY2 and
initializes all the elements
of the array to 64H.

(ii) EQU: The directive EQU (equivalent) is used to assign a value to a data
name.
Example:
(a) NUMBER EQU 50H ; Assign the value 50H to NUMBER.
(b) NAME EQU “RAMESH” ; Assign the string “RAMESH” to NAME.

Assembler Directives Related to Code (program) Location


The assember directives related to code location are as follows:
(i) ORG: The ORG (origin) directive directs the assembler to start the memory
allocation for a particular segment (data, code, or stack) from the declared address
in the ORG statement. While starting the assembly process for a memory segment,
the assembler initializes a location counter (LC) to keep track of the allotted
offset addresses for the segment. When the ORG directive is not mentioned at the
beginning of the segment, LC is initialized with the offset address OOOOH. When
the ORG directive is mentioned at the beginning of the segment, LC is initialized
with the offset address specified in the ORG directive.
Example:
ORG 100H
When this directive is placed at the beginning of the code segment, the location
counter is initialized with 01 OOH and the first instruction is stored from the offset
address 01 OOH within the code segment. If it is placed in the data segment, the
next data storage starts from the offset address 01 OOH within the data segment.
(ii) EVEN: The EVEN directive updates the location counter to the next even
address, if the current location counter content is not an even number.
Example:
EVEN
ARRAY2 DW 20 DUP (0)
These statements in a segment declare an array named ARRAY2 having 20
words, starting at an even address. The advantage of storing an array of words
starting at an even address is that the 8086 takes just one memory read/write cycle
to read/write the entire word, if the word is stored starting at an even address.
Otherwise, the 8086 takes two memory read/write cycles to read/write the word.
468 MICROPROCESSORS AND MICROCONTROLLERS

Example:
The EVEN directive can also be used at the beginning of a procedure, so that the
instructions in it can be fetched quickly by the 8086 during execution.
EVEN
RESULT PROC NEAR
; instructions in the RESULT procedure

RESULT ENDP
Here the procedure RESULT, which is of type NEAR, is stored starting at an
even address in the code segment. The ENDP directive indicates the end of the
RESULT procedure.
(iii) LENGTH: This directive is used to determine the length of an array or string
in bytes.
Example:
MOV CX, LENGTH ARRAY
CX is loaded with the number of bytes in the ARRAY.
(iv) OFFSET: This operator is used to determine the offset of a data item in a
segment containing it.
Example:
MOV BX, OFFSET TABLE
If the data item named TABLE is present in the data segment, this statement places
the offset address of TABLE, in the BX register.
(v) LABEL: The LABEL directive is used to assign a name to the current value
in the location counter. It is used to specify the destination of the branch-related
instructions such as jump and call. When LABEL is used to specify the destination,
it is necessary to specify whether it is NEAR or FAR. When the destination is in
the same segment, the label is specified as NEAR and when the destination is in
another segment, it is specified as FAR.

Example:
REPEAT LABEL NEAR
CALCULATE LABEL FAR
LABEL can also be used to specify a data item. When it is used to specify a
data item, the type of the data item must be specified. The data may have the type
—byte or word.
Example:
A stack segment having 100 words of data is defined using the following
statements:
STACK SEGMENT
DW 100 DUP (0)
STACK_T0P LABEL WORD ; reserve 100 words for stack
STACK ENDS
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 469

The second statement reserves 100 words in the stack segment and fills them
with 0. The third statement assigns the name STACK_TOP to the location present
just after the hundredth word. The offset address of this label can then be assigned
to the stack pointer in the code segment using the following statement:
MOV SP, OFFSET STACK_TOP
Assembler Directives for Segment Declaration
The assember directives for segment declaration are as follows:
(i) SEGMENT and ENDS: The SEGMENT and ENDS directives indicate the start
and end of a segment, respectively. In some cases, the segment may be assigned a
type such as PUBLIC (i.e., it can be used by other modules of the program while
linking) or GLOBAL (i.e., it can be accessed by any other module).
Large assembly language programs are usually developed as separate assembly
modules. Each assembly module is individually assembled, tested, and debugged.
When all the assembly modules are working correctly, their object code files are
linked together to form the complete program. For the modules to link together
correctly, any segment, label, or variable name referred to in other modules must be
declared PUBLIC in the module in which it is defined. For example, the statement
DATA1 SEGMENT WORD PUBLIC makes the segment named DATA1
available to other assembly modules. Here, the term WORD is used to inform
the linker to locate the segment in the first available even address. Similarly, the
statement PUBLIC XI, X2 makes the two variables XI and X2 available to other
assembly modules. If an instruction in an assembly module refers to a variable or
label which is present in another assembly module, the assembler must be told that
it is external, using the EXTRN directive.
The GLOBAL directive can be used in place of the PUBLIC or EXTRN
directive. For a symbol or name defined in the current assembly module, the
GLOBAL directive is used to make that symbol or name available to other
assembly modules. For example, the statement GLOBAL MULTIPLIER makes
the variable MULTIPLIER public so that it can be accessed from other assembly
modules. The statement GLOBAL MULTIPLIER: WORD informs the assembler
that MULTIPLIER is a variable of type ‘word’, which is in another assembly
module.
Example:
CODEI SEGMENT
; instructions of CODE 1 segment

CODEI ENDS
This example indicates the declaration of a code segment named CODEI.
(ii) ASSUME: The ASSUME directive is used to inform the assembler, the name of
the logical segments to be assumed for different segments used in the program.
Example:
ASSUME CS: CODEI , DS: DATA1
470 MICROPROCESSORS AND MICROCONTROLLERS

This statement informs the assembler that the segment address where the logical
segments CODEI and DATA1 are loaded in memory during execution is to be
stored in the CS and DS registers, respectively.
(iii) GROUP: This directive is used to form a logical group of segments with a
similar purpose. The assembler passes information to the linker/loader to form
the code, such that the group declared segments or operands lie within a 64 KB
memory segment. All such segments can be addressed using the same segment
address.
Example:
PROGRAMI GROUP CODEI. DATA1, STACK1
This statement directs the loader/linker to prepare an executable (EXE) file such
that the CODEI, DATA1, and STACK 1 segments lie within a 64 KB memory
segment that is named PROGRAM 1. Now, for the ASSUME statement, we can use
the label PROGRAMI rather than CODEI, DATA1, and STACK1, as follows:
ASSUME CS: PROGRAMI, DS: PROGRAMI, SS: PROGRAMI
(iv) SEG: The segment operator is used to decide the segment address of the label,
variable, or procedure and substitute the segment address in place of the SEG
label.
Example:
MOV AX, SEG ARRAY1 ; Load the segment address in which ARRAY1 is
present, in AX.
MOV DS, AX ; Move the content of AX to DS.
Assembler Directives for Declaring Procedures
The assember directives for declaring procedures are as follows:
(i) PROC: The PROC directive indicates the start of a named procedure. The
NEAR and FAR directives specify the type of the procedure.
Example:
SQUARE_R00T PROC NEAR
This statement indicates the beginning of a procedure named SQUARE_ROOT,
which is to be called by a program located in the same segment. The FAR directive
is used for the procedures to be called by the programs present in code segments
other than the one in which this procedure is present. For example, SALARY
PROC FAR indicates the beginning of a FAR type procedure named SALARY.
(ii) ENDP: The ENDP directive is used to indicate the end of a procedure. To
mark the end of a particular procedure, the name of the procedure may appear as
a prefix with the directive ENDP.
Example:
SALARY PROC NEAR
: code of SALARY procedure

SALARY ENDP
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 471

(iii) EXTRN and PUBLIC: The directive EXTRN (external) informs the assembler
that the procedures, label/labels, and names declared after this directive has/have
already been defined in some other segments and in the segments where they
actually appear, they must be declared public, using the PUBLIC directive.
Example:
M0DULE1 SEGMENT
PUBLIC SQUARE-ROOT
SQUARE-ROOT PROC FAR
; code of SQUARE-ROOT procedure

SQUARE-ROOT ENDP
M0DULE1 ENDS

M0DULE2 SEGMENT
EXTRN SQUARE-ROOT FAR
; code of M0DULE2

CALL SQUARE-ROOT

M0DULE2 ENDS
If one wants to call the procedure named SQUARE_ROOT appearing in
MODULE 1 from MODULE2, it must be declared public using the statement
PUBLIC SQUARE-ROOT in MODULE1 and it must be declared external using
the statement EXTRN SQUARE-ROOT in MODULE2. If a jump or call address
is external, it must be represented as NEAR or FAR. If data are defined as external,
their size must be represented as BYTE, WORD, or DWORD.
Other Assembler Directives
(i) PTR: The PTR (pointer) operator is used to declare the type of a label, variable,
or memory operand. The operator PTR is prefixed by either BYTE or WORD. If
the prefix is BYTE, the particular label, variable, or memory operand is treated as
an 8-bit quantity, while if the prefix is WORD, it is treated as a 16-bit quantity.
Example:
(a) INC BYTE PTR LSI] ; Increment the byte contents of the
memory location addressed by SI.
(b) INC WORD PTR LBX] ; Increment the word contents of the
memory location addressed by BX.
The PTR directive is also used to declare a label either as FAR or NEAR type.
The FAR PTR directive indicates to the assembler that the label following FAR
PTR is not available within the same segment and the address of the label is of size
32 bits (2 bytes offset, followed by 2 bytes segment address).
Example:
(a) JMP FAR PTR DIVIDE
472 MICROPROCESSORS AND MICROCONTROLLERS

(b) CALL FAR PTR CONVERT


where DIVIDE and CONVERT are the names of a label and procedure,
respectively.
The NEAR PTR directive indicates that the label following NEAR PTR is in
the same segment and needs only 16 bits (2 bytes offset) to address it.
(ii) GLOBAL: The labels, variables, constants, or procedures declared GLOBAL
may be used by the other modules of the program.
Example:
The following statement declares the procedure ROOT as a GLOBAL label.
ROOT PROC GLOBAL

Example:
The following statement declares the variables DATA1, DATA2, and ARRAY1
as GLOBAL variables.
GLOBAL DATA1, DATA2, ARRAY1

(iii) LOCAL: The label, variables, constants, or procedures declared LOCAL in


a module are to be used only by that particular module. After some time, some
other module may declare a particular data type LOCAL, which was previously
declared as LOCAL by another module or modules. Thus, the same label may serve
different purposes for different modules of a program. With a single declaration
statement, a number of variables can be declared LOCAL as follows:
LOCAL DATA1, DATA2, ARRAY1, Al, A2

(iv) NAME: The NAME directive is used to assign a name to an assembly language
program module. The module may now be referred to by its declared name. The
names, if selected properly, may indicate the function of the different modules,
and hence help in good documentation.
(v) SHORT: The SHORT operator indicates to the assembler that only one byte is
required to code the displacement for a jump (i.e., the displacement is within -128
to +127 bytes from the address of the byte present next to the JMP opcode). This
method of specifying the jump address saves memory. Otherwise, the assembler
may reserve 2 bytes for the displacement in the jump instructions.
Example:
JMP SHORT MULTIPLY
where MULTIPLY is a label.
(vi) TYPE: The TYPE operator directs the assembler to decide the data type of
the specified label and replaces the TYPE label with the decided data type. For the
word type variable, the data type is 2. For the double word type, it is 4, and for the
byte type, it i® 1.
Example:
If DATA 1 is an array having word type data, the instruction MOV BX, TYPE DATA1
moves the value 0002H to BX.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 473

(vii) MACRO and ENDM: Suppose a number of instructions occur repeatedly


in the main program, the program listing becomes lengthy. In such a situation,
a macro definition, i.e., a label, is assigned with the repeatedly appearing string
of instructions. The process of assigning a label or macro name to the repeatedly
appearing string of instructions is called macro definition. The macro name is then
used throughout the main program to refer to that string of instructions.
The difference between a macro and a subroutine is that in the macro, the
complete code of the instructions in the macro is inserted at each place where the
macro name appears. Hence, the length of the EXE file is larger and the macro
does not utilize the service of the stack. However, a subroutine is present only in
one place in a program and the control of execution is transferred to the subroutine
by calling that subroutine whenever necessary. Hence, the length of the EXE file
is smaller while using subroutines. A subroutine uses the stack for storing the
return address when it is called. The drawback with subroutines is the overhead
time needed to push the return address into the stack, while calling the subroutine,
and to retrieve the same from the stack, while returning from the subroutine to the
main program.
Defining a MACRO A MACRO can be defined anywhere in a program, using
the directives MACRO and ENDM. The label prior to the MACRO is the macro
name, which is used in the main program wherever needed. The ENDM directive
marks the end of the instructions or statements assigned to the macro name.
Example:
CALCULATE MACRO
MOV AX, [BX]
ADD AX. [BX + 2]
MOV [SI], AX
ENDM
In this example, CALCULATE is the macro name and the macro is used to add
two successive data in the memory, whose offset address is present in BX and the
result is stored in the memory at the offset address present in SL In the program,
which uses the above macro definition, wherever the instructions defined in the
above macro are repeating, we can simply use the macro name (CALCULATE)
instead of those instructions and this is called macro reference. When that program
is assembled using the assembler, the assembler replaces each macro reference by
the corresponding string of instructions defined in the macro and finds the opcode
of each instruction. This is called macro expansion.
Passing parameters to a MACRO Using parameters in a macro definition, the
programmer specifies the parameters of the macro that are likely to be changed
each time the macro is called. The macro given here (CALCULATE) can be
modified to calculate the result for different sets of data and store it in different
memory locations as follows:
CALCULATE MACRO OPERAND, RESULT
MOV BX, OFFSET OPERAND
MOV AX, [BX]
474 MICROPROCESSORS AND MICROCONTROLLERS

ADD AX, [BX + 2]


MOV SI, OFFSET RESULT
MOV [SIL AX
ENDM
The parameters OPERAND and RESULT can be replaced by OPERAND 1,
RESULT 1 and OPERAND2, RESULT2 while calling the macro, as follows:

CALCULATE OPERAND1, RESULT1

CALCULATE OPERAND2, RESULT2

14.4.3 Writing Assembly Language Programs using MASM


MASM (Microsoft Macro Assembler) is one of the assemblers commonly used
along with the LINK (linker) program to structure the machine codes generated by
MASM in the form of an executable (EXE) file. The MASM reads the assembly
language program, which is called source program and produces an object file as
output. The LINK program accepts the object file produced by MASM along with
library files if needed, and produces an EXE file.
While writing a program for MASM, the program listing is first typed using
a text editor in the computer, such as Norton’s Editor (NE) and Turbo C editor.
After the program editing is done, it is saved with the extension .ASM. For
example, MSI.ASM is a valid file name that can be assigned to an assembly
language program. The programmers have to ensure that all the files—the editor,
MASM.EXE (MASM assembler), and LINK.EXE (linker)—are available in the
same directory. After editing, the assembling of the program has to be done using
MASM. If all the above mentioned software is present in the root directory of the
C drive in the computer, to assemble the file MSI.ASM, the programmer has to
type the following at the DOS prompt in the computer:
C:\ > MASM MSI.ASM or C:\ > MASM MSI
After entering this command, the assembler asks for the names of the following
types of files, which it generates after the assembly process:
Object file name [.OBJ]:
List file name [NUL.LST]:
Cross reference [NUL.CRF]:
The programmer can type a name against every file name and press the enter
key after each name. If no name is entered against the file name before pressing
the enter key, all the three files will have the same name as the source file. The
.OBJ (object) file contains the machine codes of the program that is assembled.
The .LST (list) file contains the total offset map of the source file, including labels,
opcodes, offset addresses, memory allotment for different labels, and directives.
The cross reference (.CRF) file is used for debugging the source program, as it
contains information such as size of the file in bytes, list of labels, number of
labels, and routines to be called in the source program.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 4 75

After the cross reference file name is entered, the assembly process starts. If the
program contains syntax errors, they are displayed using the error code number
and the corresponding line numbers at which the errors have occurred. Once
these errors are corrected by the programmer, the assembly process is completed
successfully.
The DOS linking program LINK.EXE is used to link the different object
modules of a source program and the function library routines to produce an
integrated executable code for the source program. The linker is invoked using the
following command:
C :\> LINK MSI.OBJ
After entering this command, the linker asks for the name of the following
files:
Run file [.EXE]:
List files [NUL.MAP]:
Libraries [LIB]:
If no file names are entered for these files, by default, the source file name is
considered. The optional input ‘Libraries’ expects the name of a special library (if
any) from which the functions were used by the source program. The output of the
linker program is an executable file with either the file name entered by the user or
the default file name, and .EXE extension. The executable file name can be entered
at the DOS prompt to execute the file as follows:
C :\> MSI.EXE
In the advanced version of MASM, both assembling and linking are combined
under a single menu-invocable compile function.
DEBUG.com is a DOS utility program that is used for debuggihg and
troubleshooting 8086 assembly language programs. The DEBUG utility enables
us to have control over the hardware resources and the memory in the computer
(PC) up to a certain extent, as the PC uses one of the INTEL processors (80486,
Pentium, etc.) as the CPU. DEBUG enables us to use the PC as a low-level 8086
microprocessor kit. Typing the DEBUG command at the DOS prompt and pressing
the enter key invokes the debugging facility. A (dash) appears DEBUG is
successfully invoked, as follows:
C :\> DEBUG

Now, by typing ‘R’ at the line and pressing the enter key, we can see
the content of the different registers and flags present in the CPU of the PC, as
follows:
-R
AX = 0000H BX = 0005H CX = OOODH DX = SOOOH
SP = 8500H BP = 9800H SI = 2000H DI = 7000H
DS = SOOOH ES = 3000H SS = 4000H CS = 2000H
IP = 2000H FLAGS = 0024H

7'he remaining DEBUG commands can be referred to from any book that
discusses assembly language programming in personal computers. In this section,
476 MICROPROCESSORS AND MICROCONTROLLERS

a few examples for writing 8086 assembly language programs while using an
assembler are given.
Example 14.11:
Write a program to add two 8-bit data (FOH and 50H) in the 8086 and to store the
result in the memory, when the assembler is used.
Solution:
ASSUME CS: CODE, DS: DATA
DATA SEGMENT ; Beginning of data segment
0PER1 DB FOH ; First operand
0PER2 DB 50H ; Second operand
RESULT DB 01 DUP (?) : A byte of memory is reserved for the
result.
CARRY DB 01 DUP (?) A byte is reserved for storing the
ca rry.
DATA ENDS End of data segment.

CODE SEGMENT Beginning of code segment


START : MOV AX, DATA Initialize AX with the segment address
of DS.
MOV DS, AX Move the content of AX to DS.
MOV BX, OFFSET 0PER1 Move the offset address of 0PER1 to BX.
MOV AL, [BX] Move the first operand to AL.
ADD AL, [BX + 1] Add the second operand to AL.
MOV SI , OFFSET RESULT Store the offset address of RESULT
in SI.
MOV LSI] , AL Store the content of AL in the location
RESULT.
INC SI Increment SI to point to the location
of the carry.
JC CAR If carry = 1, jump to CAR.
MOV [SI] , OOH Store OOH in the location CARRY.
JMP LOCI Jump to LOCI.
CAR: MOV [SI] , 01H Store 01H in the location CARRY.
LOCI: MOV AH, 4CH
INT 2IH Return to DOS prompt.
CODE ENDS End of code segment.
END START Program ends.
In this program, the instructions MOV AH, 4CH, and INT 2IH at the end of the
program are used for returning to the DOS prompt after executing the program in
the computer. Instead of these two instructions, if one writes the HLT instruction,
the computer hangs after executing the program, as the CPU goes to the halt state
and the user is unable to examine the result.
Another method to write the code segment for this program is as follows:
CODE SEGMENT ; Beginning of code segment
START: MOV AX, DATA ; Initialize AX with the segment address of DS.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 477

MOV DS, AX : Move the content of AX to DS.


MOV AL, 0PER1 : Move the fi rst operand to A.
MOV BL, 0PER2 : Move the second operand t o B.
ADD AL, BL : Add BL to AL.
MOV RESULT, AL; Store AL in the location RESULT
JC CAR ; If carry = 1, jump to CAR.
MOV CARRY, OOH: Store OOH in the location CARRY.
JMP LOCI : Jump to LOCI.
CAR: MOV CARRY, 01H; Store 01H in the location CARRY.
LOCI: MOV AH, 4CH
INT 21H : Return to the DOS prompt.
CODE ENDS : End of code segment.
END START ; Program ends.
Note: In the second method, instead of OPER2, OPER1 + 1 can be used, and
instead of CARRY, RESULT + 1 can be used, since OPER2 is assigned the
memory location next to that of OPER1 and CARRY is assigned the memory
location next to that of RESULT, as defined in the data segment.
Example 14.12:
Write a program to find the smallest word in the given array having fifty word
type data.
Solution:
ASSUME CS: CODE, DS: DATA
DATA SEGMENT
ARRAY DW 2500H, 1600H, 0032H... : Initialize the ARRAY with 50 words
COUNT EQU 32H : Count is assigned to the value 32H
(= 50).
SMALLEST DW DUP (?) ; Reserve one word to store the smallest
word.

DATA ENDS
CODE SEGMENT
START: MOV AX, DATA
MOV DS, AX
MOV SI, OFFSET ARRAY : Move the offset of the array to SI.
MOV CL, COUNT : Load COUNT in CL.
DEC CL : Decrement CL as the number of
comparisons is one less than the
count.
MOV AX, ESI] : Move the first word to AX.
AGAIN: ADD SI, 02 : Add 2 to SI to get the next word.
MOV BX, [SI] : Move the next word to BX.
CMP AX, BX : Compare the word in AX with BX.
JC NEXT : If AX i s sma11, go to NEXT.
MOV AX, BX : Move the small word in BX to AX.
478 MICROPROCESSORS AND MICROCONTROLLERS

NEXT : LOOP AGAIN ; Repeat the loop CL times.


MOV SMALLEST, AX ; Store AX In the location SMALLEST
MOV AH, 4CH
INT 21H ; Return to the DOS prompt.
CODE ENDS ; End of code segment.
END START : Program ends.

Example 14.13:
Write a program to find the number of even and odd data bytes present in the given
array having one hundred byte type data.
Solution:
ASSUME CS: CODE, DS: DATA
DATA SEGMENT
ARRAY DB 40H, 31H, 23H, 52H... ; Enter all the data items of ARRAY
here.
COUNT EQU 64H ; Initialize COUNT with the value 100.
EVEN_NOS DB OOH ; Reserve a byte for storing the number
of even data items.
ODD_NOS DB OOH : Reserve a byte for storing the number
of odd data items.
DATA ENDS
CODE SEGMENT
START: MOV AX, DATA
MOV DS, AX
MOV BL, OOH ; Initialize BL with OOH, to store
the number of even data items.
MOV DL, OOH ; Initialize DL with OOH, to store the
number of odd data items.
MOV CL, COUNT ; Initialize CL with COUNT.
MOV SI, OFFSET ARRAY ; Move the offset address of ARRAY to
the SI register.
AGAIN: MOV AL, [SI] ; Move one byte from ARRAY to AL.
RCR AL, 1 ; Rotate AL right through the carry
by 1 bit.
JC ODD ; If carry = 1, the number is odd. So go
to ODD.
INC BL ; Otherwise, the number is even and
hence increment BL.
JMP LI ; Jump to LI.
ODD: INC DL ; Increment DL by 1 as the number is
odd.
LI: INC SI ; Increment SI to point to the next
data.
LOOP AGAIN ; Go to AGAIN, CL times.
MOV EVEN-NOS, BL ; Store the content of BL in EVEN_NOS.
ADDRESSING MODES, INSTRUCTION SET, AND PROGRAMMING OF 8086 479

MOV ODD_NOS, DL ; Store the content of DL In ODD_NOS.


MOV AH, 4CH
INT 21H ; Return to the DOS prompt.
CODE ENDS : End of code segment.
END START ; Program ends.

Example 14.14:
Write a program to arrange the given array having ten word type data in ascending
order.
Solution:
ASSUME CS: CODE, DS: DATA
DATA SEGMENT
ARRAY DW 1234H , 4050H, 0035H... ; Enter all the data items of ARRAY
here.
COUNT EQU OAH
DATA ENDS
CODE SEGMENT
START: MOV AX, DATA
MOV DS, AX
MOV CL, COUNT ; Load the number of data items in
CL.
DEC CL ; Decrement CL as the number of
passes is one less than the
number of data.
NEXT_PASS: MOV BL, CL ; Initialize BL with the number of
comparisons to be done in each
pass.
MOV SI, OFFSET ARRAY : Move the offset address of ARRAY to
the SI register.
COMPARE: MOV AX, [SI] ; Move one data item to AX.
ADD SI, 02H ; Add 02 to SI to point to the next
data.
CMP AX, [SI] ; Compare the next data with the
content of AX.
JC LI ; If the first data item is lesser
than the second, go to Ll.
XCHG AX, [SI] ; Otherwise, exchange the data in
AX and the memory.
SUB SI, 02H ; Subtract 02 from SI to point to
the previous memory location.
MOV [SI], AX ; Store the content of AX (smaller
data) in the memory.
ADD SI, 02 ; Increment SI by 2 to compare the
next data with AX.
Ll; DEC BL : Decrement the number of comparisons
in BL by 1.
480 MICROPROCESSORS AND MICROCONTROLLERS

JNZ COMPARE ; If BL is not 0, go to COMPARE for the


next comparison.
LOOP NEXT_PASS ; If BL is 0, go to NEXT_PASS.
MOV AH, 4CH
INT 21H ; Return to the DOS prompt.
CODE ENDS ; End of code segment.
END START ; Program ends.

The algorithm used here is explained with the following simple example. Let
us consider arranging four words stored in an array in ascending order. Since there
are 4 (= N) words, 3 (= N - 1) passes have to be done. In the first pass, 3 (= N - 1)
comparisons are made and the highest number is brought to the end of the array. In
the second pass, 2 (= N - 2) comparisons are made since only the top three words
of the array need to be compared and in the third pass, only one comparison is
needed to compare the first two data in the array.
Let us assume that the data in the array is as follows:
3200H
4F35H
2350H
1FC2H
The comparisons done in each pass and the exchange of data for arranging
them in ascending order are shown here:
PASS I:
3200H <— 3200H 3200H 3200H
4F35H । 4F35H <-। 2350H 2350H
2350H 2350H <- 4F35H <-] 1FC2H
1FC2H 1FC2H 1FC2H 4F35H

PASS II:
3200H 2350H 2350H
2350H 3200H <-1 1FC2H
1FC2H 1FC2H ' 3200H
4F35H 4F35H 4F35H

PASS III:
2350H IFC2H
1FC2H 2350H
3200H 3200H
4 F35H 4F35H

Sorted array

You might also like