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

Manual

1. The document discusses assembly language programming using MASM. It provides steps to assemble, link, and debug programs using MASM, LINK, and CodeView. 2. It describes different addressing modes for byte transfer operations in assembly language including immediate, direct, indirect, and base-plus-index addressing. Programs are provided as examples for each addressing mode. 3. Creating a batch file is recommended to automate the multi-step assembly, linking, and debugging process for faster iteration when making changes to assembly code.

Uploaded by

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

Manual

1. The document discusses assembly language programming using MASM. It provides steps to assemble, link, and debug programs using MASM, LINK, and CodeView. 2. It describes different addressing modes for byte transfer operations in assembly language including immediate, direct, indirect, and base-plus-index addressing. Programs are provided as examples for each addressing mode. 3. Creating a batch file is recommended to automate the multi-step assembly, linking, and debugging process for faster iteration when making changes to assembly code.

Uploaded by

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

Microprocessor Lab (10ECL68)

Introduction
1. MASM Overview
MASM, standing for Microsoft Macro Assembler, is a standard assembly tool used for 8086
assembly language programming. First, the assembly language code written using any text
editor such as DOS Edit, or Windows Notepad, is saved as an ASM file (.asm). An object file
(.obj) is generated from the ASM file using MASM. This object file is then fed to a linker to
obtain an executable (.exe) file which may then be tested and debugged using Microsoft
CodeView. Any logical errors found in the program must be fixed and the program
reassembled.

2. Getting Started
1. Create a directory for you use. It would be a good practice to stick to this directory to
save all your 8086 programs throughout the course of your laboratory for this
subject.

2. Place a shortcut to ‘Command Prompt’ inside this directory. Right-click on the


shortcut, choose ‘Properties’, and delete whatever is in the “Start in:” field. Apply the
changes and close the Properties box. This little trick will force Command Prompt to
start with the current directory as the current working directory every time it is
opened. Trust me; this will save you a lot of trouble.

3. Also place a copy MASM.exe, LINK.exe, and CV.exe in this directory.

4. Open Notepad and type out your program. Save it with a ‘.asm’ extension.

5. Open Command Prompt and type:


> masm/zi <filename>.asm;
where <filename> must be substituted with the filename of your program. Note that
filenames longer than 8 characters will pose problems. Also, if you skip the
semicolon at the end, you will be given the option to create some additional files
such as .LST and .CRF files, which you wouldn’t have any need for.

This step will create a .OBJ file of the same filename if your program is error-free,
otherwise it will generate a report of all the syntax errors. These errors must be
fixed in the ASM file, and Step 5 repeated.

6. Once the object file is ready, type:


> link/co <filename>.obj;
This invokes Microsoft Overlay Linker and creates an executable file (.EXE) also of
the same filename. As with Step 5, skipping the semicolon here will allow you to
create additional files (.MAP and .LIB) that are unnecessary right now.

7. Finally, type
Dept. of ECE, GAT Page 1
Microprocessor Lab (10ECL68)
> cv/p <filename>.exe (no semicolon this time)
to open up Microsoft CodeView which allows you to test and debug your program.
The various commands usable in CodeView are listed in Section 0.4.

If you’re wondering what “/zi” and “/co” are, they are switches which generate symbolic
information for CodeView. If you skip them, you won’t be able to see the source code for
your program in CodeView.

To see the full list of switches that can be used with MASM and Linker, type the following
commands at the command prompt:
> masm /help
> link /help

The “/p” you’re using with CV displays a page of information in the CodeView window
having 18 lines. If you wish to see a larger window with more lines of code at once, you may
use “cv/43” (43 lines) or “cv/50” (50 lines) instead of “cv/p”.

3. Create a Batch File


One more thing – every time you make changes to the ASM file, you will have to repeat steps
5, 6 and 7. Isn’t there a shorter and quicker way of doing it? Yes there is – you could use a
DOS “batch” file (.BAT) to execute a set of routines for you. This is how you do it:

1. Open Notepad and type the following:

masm/zi %1.asm;
link/co %1.obj;
cv/p %1.exe

Note that the first two lines end in a semicolon, but not the last line.

2. Save it with the name “compile.bat”. You may use any other filename, but with the
extension .BAT. This file should be in your working directory.

3. The next time you wish to assemble your program (.asm file), simply type the
following at the command prompt.
> compile <filename>
Here, the filename is to be typed without any extension, and you must use the exact
name of the batch file you created earlier (in this case, “compile”).
Doing this will invoke the commands within the batch file – your program will be
automatically assembled, linked and CodeView will be opened if there are no errors.
Syntax errors, if any, will be reported in the assembly stage.

4. Code View Commands


Dept. of ECE, GAT Page 2
Microprocessor Lab (10ECL68)
The following are some of the commands that may be used inside CodeView:

Program Execution Commands

Command Shortcut Key Function Example

g F5 Execute Program >g


l (none) Restart Program >l
Single-step Execution (used when
t F8 debugging to watch register >t
contents)
Execute in slow-motion until a key >e
e (none)
is pressed
F2 To view the content of registers
q (none) Quits form CodeView

1. Data Transfer Operations

1.1. Byte Transfer Using Various Addressing Modes


Dept. of ECE, GAT Page 3
Microprocessor Lab (10ECL68)
(a) Byte Transfer using Immediate Addressing Mode

Immediate addressing refers to transfer of immediate data (byte/word) to a register or


memory location. The following program transfers the byte 11H to both register AL and
memory location ‘mem’ using immediate addressing.

(b) Byte Transfer using Direct Addressing Mode

Direct addressing refers to transfer of data (byte/word) between a register and memory
location. Memory-to-memory transfer is not supported by any instruction except MOVS.
The following program moves a byte 11H from memory location ‘mem1’ to register AL,
and then from AL to another memory location ‘mem2’ using direct addressing.

Program 1.1 (a) Byte Transfer Using Program 1.1 (b) Byte Transfer Using
Immediate Addressing Direct Addressing
.model small .model small
.data .data
mem DB ? mem1 DB 11H
.code mem2 DB ?
mov AX,@data .code
mov DS,AX mov AX,@data
mov AL,11H mov DS,AX
mov mem,11H mov AL,mem1
mov AH,4CH mov mem2,AL
int 21H mov AH,4CH
end int 21H
end
Result:
Before Execution: mem = Result:
After Execution: mem = Before Execution: mem2 =
After Execution: mem2 =

(c) Byte Transfer using Indirect Addressing Mode

Indirect addressing refers to transfer of data (byte/word) between a register and memory
location that is addressed by an index or base register. The index registers are SI and DI,
Dept. of ECE, GAT Page 4
Microprocessor Lab (10ECL68)
and the base registers are BX and BP. It may be recalled that memory-to-memory transfer
is not supported. The following program transfers data from ‘src’ (addressed by SI) to AL,
and then from AL to ‘dest’ (addressed by DI).

(d) Byte Transfer using Base-plus-Index Addressing Mode

Base-plus-Index addressing transfers data (byte/word) between a register and memory


location that is addressed by a base register plus an index register.

Program 1.1 (c) Byte Transfer Using Program 1.1 (d) Byte Transfer Using
Indirect Addressing Mode Base-plus-Index Addressing Mode
.model small .model small
.data .data
src DB 11H array DB 11H,22H,33H,44H,55H
dest DB ? dest DB ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov SI,OFFSET src mov BX,OFFSET array
mov DI,OFFSET dest mov SI,4
mov AL,[SI] mov AL,[BX+SI]
mov [DI],AL mov BX,OFFSET dest
mov AH,4CH mov DI,0
int 21H mov [BX+DI],AL
end mov AH,4CH
int 21H
Result: end

Result:

1.2. Block Transfer without Overlap


Our objective now is to transfer (copy) a block of data from one section of memory to
another section, such that the replicated block of data does not overlap the already existing
block of data. In the following programs 1.2(a) and (b), memory location ‘array’ has N

Dept. of ECE, GAT Page 5


Microprocessor Lab (10ECL68)
elements, stored at locations array[0] till array[N-1]. Thus locations array[N] onwards
refer to vacant locations. Both programs transfer (copy) the first N array elements to the
next N locations (from [N] to [2N-1]) without overlapping the existing elements. In the
programs below, we’ve renamed N as ‘len’, where ‘len’ is the length of the array. Refer to the
figure on the next page to get a clear picture of what’s happening.

(a) Block Transfer (without Overlap) using Index Addressing Mode

Here, index registers SI and DI are used to directly address array[0] (source) and array[N]
(destination). A loop is run N times, and in each iteration, 1 byte of data is copied form [SI]
to [DI], and then SI and DI are incremented.

(b) Block Transfer (without Overlap) using Register-relative Addressing

The program 1.2(a) above has been redone here, but this time using register-relative
addressing mode (memory is addressed relative to a register i.e. the register holds the
displacement only). The index registers SI and DI simply hold the displacements
rather than the complete addresses of the source and destination respectively, and memory
is addressed using these registers as array indexes.

Figure showing Block Transfer without Overlap

Program 1.2 (a) Block Transfer (without Program 1.2 (b) Block Transfer (without
Overlap) using Index Addressing Mode Overlap) using Register-relative
Addressing Mode
.model small .model small
.data .data

Dept. of ECE, GAT Page 6


Microprocessor Lab (10ECL68)
array DB 11H,22H,33H,44H array DB 11H,22H,33H,44H,55H
len DW $-array len DW $-array
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov CX,len mov CX,len
mov SI,OFFSET array mov SI,0
mov DI,SI mov DI,len
add DI,CX back: mov AL,array[SI]
back: mov AL,[SI] mov array[DI],AL
mov [DI],AL inc SI
inc SI inc DI
inc DI loop back
loop back mov AH,4CH
mov AH,4CH int 21H
int 21H end
end

Result: Result:
Before Execution: array = Before Execution: array =
After Execution: array = After Execution: array =

1.3. Block Transfer with Overlap


Let’s say we want to transfer a block of data such that it overlaps the last two elements of
the source data. As in the previous case, we have an array of N elements stored at locations
array[0] till array[N–1]. If we’re to overwrite the last two elements, that would mean that
the 0th element would have be copied to the N th location minus two, i.e. to the [N–2]th
location. Similarly the last ([N-1]th) element would go to the [2N-3]th location. In the figure
below, we’ve renamed N as ‘len’, the length of the array.

Figure showing Block Transfer overlapping last two elements


1.4. Block Exchange
The program below shows how the contents of two arrays ‘array1’ and ‘array2’ can be
exchanged. Register SI holds the displacement of the elements to be swapped, and the
swapping is done using temporary registers AL and BL.

Dept. of ECE, GAT Page 7


Microprocessor Lab (10ECL68)

Figure showing Block Interchange

2. Arithmetic Operations
2.1. Addition of Multiprecision Numbers
8086 performs arithmetic on 8/16-bit numbers only, but can be forced to do the same on
higher bit numbers, called multiprecision numbers, using appropriate programs.

Dept. of ECE, GAT Page 8


Microprocessor Lab (10ECL68)

AIM: Program to add two 48-bit numbers.

Our objective is to add two 48-bit numbers: 104563F25AC3H and F9032985F4DCH. The
expected sum is 109488D784F9FH. We may achieve this using one of the two methods
described below:

(a). Byte-wise addition


Each of the given multibyte numbers is split into bytes (8-bits). Thus, the operation
performed will be:

10 45 63 F2 5A C3 H
+ F9 03 29 85 F4 DC H
-------------------------------------
01 09 48 8D 78 4F 9F H
 Addition is performed using an 8-bit register, such as AL.
 Carry after each addition is propagated through the use of ADC (add with carry).

(b). Word-wise addition


When 8086 is capable of 16-bit addition, we might as well split the given multibyte
numbers into words (16-bits) instead of bytes. Thus, the operation performed will be more
efficient.

1045 63F2 5AC3 H


+ F903 2985 F4DC H
-------------------------------------
0001 0948 8D78 4F9F H
 Addition is performed using a 16-bit register, such as AX.
 Carry after each addition is propagated through the use of ADC (add with carry).
 SI needs to incremented twice, because we need to store two bytes in memory after
each addition operation. However, we cannot use “add SI, 02H”, because this would
destroy the carry from array addition. Instead, we use “inc SI” twice.

Program 2.1(a) Byte-Wise Addition of Program 2.1(b) Word-Wise Addition of


Multiprecision Numbers Multiprecision Numbers
.model small .model small
.data .data
array1 DB 0C3H,5AH,0F2H,63H, array1 DW 5AC3H,63F2H,1045H
45H,10H array2 DW 0F4DCH,2985H,0F903H
array2 DB 0DCH,0F4H,85H,29H, len DW 03H
Dept. of ECE, GAT Page 9
Microprocessor Lab (10ECL68)
03H,0F9H res DW ?
len DW 06H .code
res DB ? mov AX,@data
.code mov DS,AX
mov AX,@data mov CX,len
mov DS,AX mov SI,00H
mov CX,len mov AX,00H
mov SI,00H clc
mov AL,00H L1: mov AX,array1[SI]
clc adc AX,array2[SI]
L1: mov AL,array1[SI] mov res[SI],AX
adc AL,array2[SI] inc SI
mov res[SI],AL inc SI
inc SI loop L1
loop L1 jnc exit
jnc exit mov res[SI],01H
mov res[SI],01H exit: mov AH,4CH
exit: mov AH,4CH int 21H
int 21H end
end
Result:
Result:

2.2. Multiplication
8086 can perform both 8-bit and 16-bit multiplication. The product generated is always
double-sized, i.e. 8-bit multiplication generates a 16-bit product, while 16-bit multiplication
generates a 32-bit product.

8-bit multiplication
 The multiplier (8-bit) is held in AL
 The multiplicand (8-bit) may be held in any register or memory location
 The product generated is 16-bit, and held in AX

16-bit multiplication
 The multiplier (16-bit) is held in AX
 The multiplicand (16-bit) may be held in any register or memory location
 The product generated is 32-bit, and held in DX, AX
 DX holds the higher word while AX holds the lower word of the product

Dept. of ECE, GAT Page 10


Microprocessor Lab (10ECL68)
8-bit and 16-bit multiplications may be carried out on unsigned numbers using the MUL
instruction, and on signed numbers using the IMUL instruction.

(a) 8-bit Unsigned Multiplication


Our objective is to multiply two 8-bit numbers: C2H and 7BH. Their unsigned values are
194 and 123 respectively; thus when multiplied, the expected product is 194 x 123 = 23862
= 5D36H.
Please note that the product generated is 16-bit and the range of 16-bit unsigned numbers
is 0 to 65535.

(b) 8-bit Signed Multiplication


Our objective is to multiply the same two 8-bit numbers: C2H and 7BH, but this time using
the instruction IMUL, instead of MUL. The signed values of the above numbers are –62 and
+123 respectively; thus when multiplied, the expected product is –62 x +123 = –7626 =
E236H.
Please note that the product generated is 16-bit and the range of 16-bit signed numbers is –
32768 to +32767.

Program 2.2(a) 8-bit Unsigned Program 2.2(b) 8 bit Signed Multiplication


Multiplication
.model small .model small
.data .data
mpl DB 0C2H mpl DB 0C2H
mpd DB 7BH mpd DB 7BH
res DW ? res DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AL,mpl mov AL,mpl
mul mpd imul mpd
mov res,AX mov res,AX
mov AH,4CH mov AH,4CH
int 21H int 21H
end end
Result: res = AX = 5D36H Result: res = AX =

(c) 16-bit Unsigned Multiplication

Our objective is to multiply two 16-bit numbers: 2A58H and FB6DH, but this time using
the instruction IMUL. Their unsigned values are 10840 and 64365 respectively; thus when
multiplied, the expected product is 10840 x 64365 = 697716600 = 29964F78H.

Dept. of ECE, GAT Page 11


Microprocessor Lab (10ECL68)
Please note that the product generated is 32-bit and the range of 32-bit unsigned numbers
is –231 to 231–1.

(d) 16-bit Signed Multiplication

Our objective is to multiply the same two 16-bit numbers: 2A58H and FB6DH. Their signed
values are +10840 and –1171 respectively; thus when multiplied, the expected product is
+10840 x –1171 = –12693640 = FF3E4F78H.
Please note that the product generated is 32-bit and the range of 32-bit signed numbers is 0
to 232–1.

Program 2.2(c) 16-bit Unsigned Program 2.2(d) 16-bit Signed


Multiplication Multiplication
.model small .model small
.data .data
mpl DW 2A58H mpl DW 2A58H
mpd DW 0FB6DH mpd DW 0FB6DH
res DW ? res DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AX,mpl mov AX,mpl
mul mpd imul mpd
mov res[0],AX mov res[0],AX
mov res[2],DX mov res[2],DX
mov AH,4CH mov AH,4CH
int 21H int 21H
end end

Result: res = DX,AX = Result: res = DX,AX =

2.3. Division
As with multiplication, division is possible on both 8-bit and 16-bit signed and unsigned
numbers. In any division operation, the dividend must be double sized i.e. in 8-bit division
the dividend must be 16-bit, while in 16-bit division, the dividend must be 32-bit.

8-bit division
 Divisor is 8-bit, and may be in any 8-bit register or memory location.
 Dividend must be 16-bit, and should be loaded into AX.
 If dividend is 8-bit, it can be loaded into AL, and AH must be filled depending on
whether the number is signed or unsigned.

Dept. of ECE, GAT Page 12


Microprocessor Lab (10ECL68)
 If the number is unsigned, AH must be cleared to 00H.
 If the number is signed, AH must be filled with the sign bits of AL (sign-
extension). The instruction CBW (convert byte to word) must be used to do
this.
 After division, the remainder is found in AH, and the quotient in AL.

Program 2.3 (a) 8-bit Unsigned Division Program 2.3(b) 8-bit Signed Division
.model small .model small
.data .data
divd DW 0A132H divd DW 3ABH
divs DB 64H divs DB 0D3H
res DW ? res DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AL,divs mov AL,divs
mov AH,0 cbw
mov BX,AX mov BX,AX
mov AX,divd mov AX,divd
div BX cwd
mov res[0],AX idiv BX
mov res[2],DX mov res[0],AX
mov AH,4CH mov res[2],DX
int 21H mov AH,4CH
end int 21H
end
Result:
Result:

16-bit division
 Divisor is 16-bit, and may be in any 16-bit register or memory location.
 Dividend must be 32-bit, and should be loaded into DX, AX – DX must contain the
higher word.
 If dividend is 16-bit, it can be loaded into AX, and DX must be filled depending on
whether the number is signed or unsigned.
Dept. of ECE, GAT Page 13
Microprocessor Lab (10ECL68)
 If the number is unsigned, DX must be cleared to 0000H.
 If the number is signed, DX must be filled with the sign bits of AX (sign-
extension). The instruction CWD (convert word to double word) must be
used to do this.
 After division, the remainder is found in DX, and the quotient in AX.

Program 2.3 (c) 16-bit Unsigned Division Program 2.3 (d) 16-bit Signed Division
.model small .model small
.data .data
divd DW 0D0A5H divd DW 0D0A5H
divs DW 56H divs DW 56H
res DW ? res DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AX,divd mov AX,divd
mov DX,0 cwd
div divs idiv divs
mov res[0],AX mov res[0],AX
mov res[2],DX mov res[2],DX
mov AH,4CH mov AH,4CH
int 21H int 21H
end end

Result: Result:

Dept. of ECE, GAT Page 14


Microprocessor Lab (10ECL68)

3. BCD and ASCII Arithmetic


3.1. BCD Arithmetic
What is BCD?
The numbers we tend to use in our everyday lives are all in base 10. However, a digital
system understands only binary, and hexadecimal is only a convenient representation of
binary. Binary coded decimal, or BCD, is an attempt to disguise hexadecimal numbers so
that they appear as decimal numbers to the human. In essence, a BCD number is a
hexadecimal number written without the use of the hex digits A-F. All BCD arithmetic is
actually done on hexadecimal numbers with the results so adjusted that it seems to be
decimal.

(a) DAA (Decimal Adjust after Addition)


The DAA instruction follows the ADD or ADC instruction to adjust the sum into a BCD
result. Suppose that DX and BX each contain 4-digit packed BCD numbers. The following
program shows how BCD numbers in DX and BX are added and the result stored in CX.

(b) DAS (Decimal Adjust after Subtraction)


The DAS instruction functions in quite the same way as DAA, except that it follows a
subtraction (SUB or SBB) instead of addition.
The following program is same as that of 3.1(a) except that it subtracts instead of adds DX
and BX. The main difference in these programs is that the DAA instruction changes to DAS
and the ADD and ADC instructions change to SUB and SBB respectively.

Program 3.1 (a) BCD Addition and DAA Program 3.1 (b) BCD Subtraction and DAS
.model small .model small
.code .code
mov BX,3099H mov BX,3099H
mov DX,1028H mov DX,1028H
mov AL,BL mov AL,BL
add AL,DL sub AL,DL
daa das
mov CL,AL mov CL,AL
mov AL,BH mov AL,BH
adc AL,DH sbb AL,DH
daa das
mov CH,AL mov CH,AL
mov AH,4CH mov AH,4CH
int 21H int 21H
end end

Result: Result:
Sum: CX=4127H (1028H+3099H=4127H) Difference: CX=071H (3099H–1028H =2071H)

Dept. of ECE, GAT Page 15


Microprocessor Lab (10ECL68)

3.2. ASCII Arithmetic


What is ASCII?
ASCII stands for American Standard Code for Information Interchange. It was
developed as a means of communication between an input device (e.g. keyboard) and the
system, as well as between the system and an output device such as the monitor.
Any and every key on the keyboard has an equivalent ASCII code. For example, the ASCII
code of ‘A’ is 41H. What this means is that whenever you press ‘A’ on your keyboard, the
input to the system is the hexadecimal number 41H. Also, if 41H outputted, then the
character ‘A’ will be displayed on the screen. It must be noted that the ASCII codes for ‘a’ and
‘A’ are different. In a similar manner, whenever the system directs an output of 41H towards
the computer screen, you will see an ‘A’ on the display. As far as hexadecimal numbers are
concerned, we’re only interested in the ASCII codes of digits 0-9 and A-F. These are listed in
the table below:

Hex Digit ASCII Code Hex Digit ASCII Code


0 30H A 41H
1 31H B 42H
2 32H C 43H
3 33H D 44H
4 34H E 45H
5 35H F 46H
6 36H
7 37H
8 38H
9 39H

Why ASCII?
You forget that a digital system understands only binary. Therefore, it is necessary that each
character be represented by a unique binary sequence. ASCII uses an 8-bit binary sequence
ranging from 00H to FFH to represent 256 characters, including invisible characters (e.g.
white space and carriage return) and other special characters, apart from the usual
alphabets (A-Z, a-z), digits (0-9) and punctuators (comma, full stop, apostrophe etc.) and
mathematical symbols (+ – * / % etc.).

What is ASCII arithmetic?


Okay. Let’s say you’d like to write a program that adds two user-inputted numbers and
outputs the sum. Supposing he enters 2 and 5, the sum that should be returned is 7. Now,
when he enters ‘2’, the system will receive the ASCII equivalent of 2, i.e. 32H. Similarly ‘5’
will be received as 35H. If you were to add them now, you’ll end up with 32H + 35H = 67H;
this is not what we had wanted. The correct approach would be to subtract 30H from both
32H and 35H, to be left with 02H and 05H. Now when added, 02H + 05H = 07H. Correct.
Next, we have to display ‘7’ on the screen. So, we again add 30H to 07H to make it 37H.
When 37H is output to the screen, the user will see its ASCII equivalent i.e. ‘7’.
Dept. of ECE, GAT Page 16
Microprocessor Lab (10ECL68)

ASCII Adjust functions in 8086


You saw in the above example how ASCII codes affected addition, how the inputs and
outputs had to be adjusted. Actually, the ASCII adjust procedures are different for addition,
subtraction, multiplication and division. Likewise, 8086 has 4 different ASCII adjust
functions to accomplish the same – AAA, AAS, AAM and AAD. These instructions use AX
register as source and destination.

(a) AAA (ASCII Adjust after Addition)


Addition of two 1-digit ASCII-coded numbers will not result in any useful data. For example,
addition of 31H and 39H results in 6AH. Actually, this ASCII addition (1 + 9) should
produce a 2-digit ASCII result equivalent to 10 decimal, which is 3130H in ASCII. If an AAA
instruction is executed after this addition, the AX register will contain 0100H. Although
this is not ASCII code, it can be converted to ASCII code by adding 3030H, which generates
3130H.

The AAA instruction works by producing the unpacked BCD result of the decimal sum in
the AX register. This instruction clears AH if the result is less than 10 decimal, and adds a 1
to AH if the result is greater than 10.

Difference between DAA and AAA


DAA and AAA are both adjustment functions used after addition. DAA is an 8-bit
instruction that works on AL register, while AAA is 16-bit and works on AX. But the main
difference between the two instructions is that DAA results in a packed BCD number while
AAA produces an unpacked BCD result. The following example will make it clearer:
06H + 08H = 0EH ––––––– DAA –––––––> 14H
36H + 38H = 6EH ––––––– AAA –––––––> 0104H –––––– ASCII ––––––> 3134H
Also, DAA uses BCD input data while AAA needs ASCII coded input. AAA’s output can be
made ASCII by the addition of 3030H.

(b) AAS (ASCII Adjust after Subtraction)


AAS is very much the same as AAA, but is used after subtraction.
If you were to subtract a larger number from a smaller number, the result will be in 100’s
complement form. For example, subtracting 85 from 67 will give you –18, expressed as 82
in 100’s complement (99 – 18 + 1 = 82). Thus the ASCII result will be 30303832H.

Dept. of ECE, GAT Page 17


Microprocessor Lab (10ECL68)

Program 3.2 (a) ASCII Addition and AAA Program 3.2 (b) ASCII Subtraction and AAS
.model small .model small
.data .data
num1 DB 05H,08H num1 DB 05H,08H
num2 DB 07H,06H num2 DB 07H,06H
ascii DW ? ascii DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AH,00H mov AH,00H
mov AL,num1 mov AL,num1
add AL,num2 sub AL,num2
aaa aas
mov DL,AL mov DL,AL
mov AL,num1+1 mov AL,num1+1
adc AL,num2+1 sbb AL,num2+1
aaa aas
mov DH,AL mov DH,AL
mov AX,00H add DX,3030H
adc AX,3030H mov AX,00H
add DX,3030H adc AX,3030H
mov ascii,DX mov ascii,DX
mov ascii+2,AX mov ascii+2,AX
mov AH,4CH mov AH,4CH
int 21H int 21H
end end

Result: Result:
Sum: Difference:

(c) AAM (ASCII Adjust after Multiplication)


The AAM instruction follows the multiplication instruction after multiplying two 1-digit
unpacked BCD numbers. In the following Program 3.2(c), 6 and 7 are multiplied to produce
the 002AH in the AX register, since 06H x 07H = 2AH. After adjusting the result with AAM,
AX contains 0402H – the unpacked BCD of 42. If 3030H is added to 0402H, it has an ASCII
result of 3432H.

Dept. of ECE, GAT Page 18


Microprocessor Lab (10ECL68)
Binary to Unpacked BCD using AAM

In the above program, AAM transformed the contents of AX register from 002AH to
0402H. The AAM instruction accomplished this conversion by dividing AX by 0AH, and
then storing the remainder in AL and quotient in AH.

In fact, the AAM instruction converts binary numbers to unpacked BCD. This works
only for binary numbers in the range 0000H to 0063H appearing in the AX register.

For example, if the AX register contains 0060H before AAM, it will contain 0906H after
execution of AAM. This is the unpacked BCD equivalent of 96 decimal (60H = 96). If 3030H
is added to 0906H, the result changes to ASCII code.

(d) AAD (ASCII Adjust before Division)


Unlike all other ASCII adjustment instructions, AAD appears before a division. The AAD
instruction requires that the AX register contain a 2-digit unpacked BCD number (not
ASCII) before executing. After adjusting the AX register with AAD, it may be divided by an
unpacked BCD number to generate a single digit result in AL and remainder in AH.

The following program illustrates how a 74 is divided by 9 to get a quotient of 8 and a


remainder of 2. AAD prepares 0704H for division by converting it to 004AH, which is the
hexadecimal equivalent of 74 decimal. 4AH can now be divided as usual to produce
quotient in AL and remainder in AH.

Unpacked BCD to Binary using AAD

In the above program, AAD transformed the contents of AX register from 0704H to 004AH.
The AAD instruction accomplished this conversion by multiplying AH by 0AH, and then
adding AL to it and storing the result back in AX.

So it may be seen that AAD is the exact opposite of AAM. The AAD instruction converts
unpacked BCD numbers to binary. This works only for BCD numbers 0 to 99 in unpacked
form (0000H to 0909H) appearing in the AX register.

For example, if the AX register contains 0906H before AAD, it will contain 0060H after
execution of AAD. This is the binary equivalent of 96 BCD (96 = 60H). This binary (hex)
number can now be used as dividend in a division operation.

Dept. of ECE, GAT Page 19


Microprocessor Lab (10ECL68)

Program 3.2 (c) ASCII Multiplication and Program 3.2 (d) ASCII Division and
AAM AAD
model small .model small
.data .data
num1 DB 06H divd DW 0704H
num2 DB 07H divs DB 09H
ascii DW ? ascii DW ?
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AH,00H mov AX,divd
mov AL,num1 aad
mul num2 div divs
aam add AX,3030H
add AX,3030H mov ascii,AX
mov ascii,AX mov AH,4CH
mov AH,4CH int 21H
int 21H end
end
Result: ascii = DX,AX = 3238H
Result: ascii = AX = 74 ÷ 9
=> Quotient=AX=8
Reminder=DX=2

Dept. of ECE, GAT Page 20


Microprocessor Lab (10ECL68)

4. Code Conversions

4.1. Binary to BCD Conversion


It is already clear what binary and BCD numbers are. Here, we see how they can be
interconverted. But before we do that, let us understand how to “unpack” and “repack”
numbers. For convenience, let us choose decimal (base 10) numbers.

By “unpacking”, we mean to separate out all the digits of the given number. For decimal
numbers, this is done by successively dividing by 10, and taking out the remainder after
each division. The process is continued till the quotient is zero. For example, the decimal
number 2805 (Two thousand eight hundred and five) can be unpacked as shown below:

START
1. 2805 ÷ 10 = 280, with remainder = 5 10 2805
2. 280 ÷ 10 = 28, with remainder = 0 10 280 – 5
3. 28 ÷ 10 = 2, with remainder = 8 10 28 – 0
4. 2 ÷ 10 = 0, with remainder = 2 10 2 – 8
STOP 0 – 2

Thus, after unpacking, we are left with individual digits 2, 8, 0, and 5.


Next, we must also be able to put back the digits together and regain the original
number. This process is called “repacking”. This involves simple multiplication of the
digits with their weights and summing them up. In this case, the weights are powers of 10
since we’re dealing with decimal numbers. 2805 can be put together from its digits as:
2 × 103 + 8 × 102 + 0 × 101 + 5 × 100
= 2 × 1000 + 8 × 100 + 0 × 10 + 5 × 1
= 2805

Similarly, hexadecimal numbers are unpacked by successive division by 10H (= 16


decimal), and repacked by multiplication by powers of 10H.
With unpacking and repacking understood, we can study binary and BCD inter-conversion.

16-bit Binary to BCD conversion


The given binary number is converted to its BCD equivalent by unpacking using 0AH and
then repacking the digits using powers of 10H.

For example, the binary number 17EDH is converted to 6125 BCD (17ED16 = 612510) as
shown below:
First, the binary number is unpacked by successive division by 0AH.

START

Dept. of ECE, GAT Page 21


Microprocessor Lab (10ECL68)
1. 17EDH ÷ 0AH = 264H, with remainder = 5H 0AH 17EDH
2. 264H ÷ 0AH = 3DH, with remainder = 2H 0AH 264H – 5H
3. 3DH ÷ 0AH = 6H, with remainder = 1H 0AH 3DH – 2H
4. 6H ÷ 0AH = 0, with remainder = 6H 0AH 6H – 1H
STOP 0 – 6H

After unpacking, we’re left with the individual (hex) digits 6, 1, 2 and 5. These digits must
be multiplied by powers of 10H and summed up to give 6125H (=6125 BCD).

6H × (10H)3 + 1H × (10H)2 + 2H × (10H)1 + 5H × (10H)0


= 6H × (1000H) + 1H × (100H) + 2H × (10H) + 5H × (1H)
= 6000H + 100H + 20H + 5H
= 6125H

Thus we’ve converted 17ED into 6125 and accomplished binary to BCD conversion.

In the first half of the program, the given binary number, “bin” = 17EDH, is loaded onto AX
as dividend and is unpacked by successive division by 0AH. Each of the remainders is
pushed onto the stack, and division continues with the quotient in AX acting as the next
dividend. Note that it is important to clear DX in order to perform 16-bit division (refer
Section 2.5(d)). At the end of 4 divisions (count = 4), quotient is zero, and hence division is
stopped. At this point, the stack contains all the remainders, with the last remainder (most
significant digit) on top of the stack.

In the next half of the program, the remainders are popped out of the stack one by one and
multiplied by the corresponding power of 10H. The highest power of 10H required is 3,
which is one less than the count, and hence the statement “dec CX”. CX holds the current
power of 10H required, and exponentiation of 10H is achieved by repeated multiplication.
Note that the “loop” statement causes CX to go to zero, and hence CX must be reloaded with
“count – 1” for every iteration. During the last iteration, when CX = 0, no multiplication
with 10H is required – instead the last remainder must be directly added to the BCD result.
When count goes to zero, multiplication stops, and the final result is ready in the DI register
and is saved in the reserved memory location “bcd”.

Note that the input range of the above program is restricted between 0000H–270FH,
since 270F16 = 999910, which is the largest BCD number that can be represented in 16-bits.

8-bit Binary to BCD conversion


8-bit binary to BCD conversion is simple in that it involves only one division and
multiplication operation each. However, the principle of the conversion from binary to BCD
remains the same – divide by 0AH and multiply by 10H.
For example, to convert 61H to 97 BCD, it is first divided by 0AH. 61H ÷ 0AH = 9H, with
remainder = 7H. The quotient and remainder are found in AL and AH respectively. Next, AL

Dept. of ECE, GAT Page 22


Microprocessor Lab (10ECL68)
is multiplied with 10H. This makes AL = 90H. Note that it is important to save the
remainder in another register because multiplication destroys the contents of AH. Last, the
saved remainder is added to AL to get 97H, the required BCD.
Note that the input range of the above program is restricted between 00H–63H, since 6316
= 9910, which is the largest BCD number that can be represented in 8-bits.

Program 4.1 (a) 16-bit Binary to BCD Program 4.1 (b) 8-bit Binary to BCD
.model small .model small
.stack 64H .data
.data bin DB 61H
bin DW 17EDH bcd DB ?
bcd DW ? .code
count DW ? mov AX,@data
.code mov DS,AX
mov AX,@data mov AL,bin
mov DS,AX mov AH,0
mov AX,bin mov BL,0AH
mov count,0 div BL
mov BX,0AH mov CL,AH
unpack: mov DX,0 mov BL,10H
div BX mul BL
push DX add AL,CL
inc count mov bcd,AL
cmp AX,0 mov AH,4CH
jnz unpack int 21H
mov DI,0 end
mov BX,10H Result:
repack: mov CX,count
dec CX
pop AX
jcxz skip
repmul: mul BX
loop repmul
skip: add DI,AX
dec count
jnz repack
mov bcd,DI
mov AH,4CH
int 21H
end
Result:
4.2. BCD to Binary Conversion

Dept. of ECE, GAT Page 23


Microprocessor Lab (10ECL68)
If binary to BCD conversion has been understood, then the reverse shouldn’t be a problem
at all. In fact, we’ll be doing exactly the opposite now – unpacking using 10H and repacking
using powers of 0AH.

16-bit BCD to Binary conversion


The given BCD number is converted to its binary equivalent by unpacking using 10H and
then repacking the digits using powers of 0AH.

Earlier, we converted the binary number 17EDH to 6125 BCD (17ED16 = 612510). Now, let
us attempt the reverse:

First, the BCD number 6125 is unpacked by successive division by 10H.

START
1. 6125H ÷ 10H = 612H, with remainder = 5H 10H 6125H
2. 612H ÷ 10H = 61H, with remainder = 2H 10H 612H – 5H
3. 61H ÷ 10H = 6H, with remainder = 1H 10H 61H – 2H
4. 6H ÷ 10H = 0, with remainder = 6H 10H 6H – 1H
STOP 0 – 6H
After unpacking, we’re left with the individual (bcd) digits 6, 1, 2 and 5. These digits are
multiplied by powers of 0AH and summed up to give 17EDH.

6H × (0AH)3 + 1H × (0AH)2 + 2H × (0AH)1 + 5H × (0AH)0


= 6H × (03E8H) + 1H × (64H) + 2H × (0AH) + 5H × (1H)
= 1770H + 64H + 14H + 5H
= 17EDH

So we’ve successfully reversed the conversion, and obtained back 17ED from 6125 and
achieved BCD to binary conversion. Program 4.2(a) does the same.
This program is very much the same as 4.1(a) with two small changes – 0AH and 10H have
been swapped to perform reverse conversion, and the labels “bin” and “bcd” have been
interchanged as well.

8-bit BCD to Binary conversion


This is identical to 8-bit binary to BCD conversion, but with the roles of 0AH and 10H
interchanged. For example, to convert 97 BCD to 61H, it is first divided by 10H. 97H ÷ 10H
= 9H, with remainder = 7H. Next, 9H is multiplied with 0AH and added to 7H to obtain
61H (9H × 0AH + 7H = 61H).

Program 4.2 (a) 16-bit BCD to Binary Program 4.2 (b) 8-bit BCD to Binary
.model small .model small

Dept. of ECE, GAT Page 24


Microprocessor Lab (10ECL68)
.data .data
bcd DW 6125H bcd DB 97H
bin DW ? bin DB ?
count DW ? .code
.code mov AX,@data
mov AX,@data mov DS,AX
mov DS,AX mov AL,bcd
mov AX,bcd mov AH,0
mov count,0 mov BL,10H
mov BX,10H div BL
unpack: mov DX,0 mov CL,AH
div BX mov BL,0AH
push DX mul BL
inc count add AL,CL
cmp AX,0 mov bin,AL
jnz unpack mov AH,4CH
mov DI,0 int 21H
mov BX,0AH end
repack: mov CX,count
dec CX Result:
pop AX
jcxz skip
repmul: mul BX
loop repmul
skip: add DI,AX
dec count
jnz repack
mov bin,DI
mov AH,4CH
int 21H
end

Result:

Dept. of ECE, GAT Page 25


Microprocessor Lab (10ECL68)

5. Applied Arithmetic
5.1. Square of an 8-bit Unsigned Binary Number
Square of an 8-bit binary number may be directly calculated by multiplying the number
with itself. Of course, the resultant product will be double-width (16-bit) as is the case with
any multiplication on 8086.

5.2. Cube of an 8-bit Unsigned Binary Number


Cube of the given 8-bit binary number is calculated by directly multiplying the number with
itself, twice. The first multiplication will produce a double-width product (16-bit), while the
second one will further double the product size, resulting in a 32-bit cube number. For
example, (FFH)3 will give FD02FFH. (DX = 00FDH, AX = 02FFH).

To carry out signed squaring, we need to use IMUL in place of MUL. In that case, (FFH)2 will
result in 0001H, since (–1)2 = 1, where –1 is the signed value of FFH.

Program 5.1 Square of an 8-bit unsigned Program 5.2 Cube of an 8-bit unsigned
Binary number Binary number
.model small .model small
.data .data
num DB 0FFH num DB 0FFH
square DW ? cube DW 2 dup(0)
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AL,num mov AL,num
mul AL mov BL,AL
mov square,AX mul BL
mov AH,4CH mov BH,0
int 21H mul BX
end mov cube,AX
mov cube+2,DX
Result: square = AX = mov AH,4CH
int 21H
end

Result: cube = DX,AX =

Dept. of ECE, GAT Page 26


Microprocessor Lab (10ECL68)
5.3. Factorial
Factorial of the given binary number can be calculated by multiplying the number with the
accumulator (accumulator initially holding ‘1’) and decrementing it in every step until it
reaches 1. The only place we need to be careful is when the input is zero – the program
must output a ‘1’, not a ‘0’.

For the sake of simplicity, let us limit the size of our factorial to 16-bits. This means that the
highest input possible is 8, since the factorial of 9 is 362880 10 = 58980H, which exceeds 16-
bits.
Program 5.3 Factorial
.model small
.data
num DW 5H
fact DW ?
.code
mov AX,@data
mov DS,AX
mov AX,0001H
mov CX,num
jcxz skip
back: mul CX
loop back
skip: mov fact,AX

mov AH,4CH
int 21H
end

Result: fact = AX =
It should be understood that the LOOP instruction takes care of both decrementing CX and
jumping back. The statement “loop <label>” is a combination of “dec CX” and “jnz <label>”.

5.4. LCM – Least Common Multiple


LCM of two numbers is, as the name indicates, the least of the common multiples of the two
numbers. In other words, it is that smallest number that both the numbers can divide
wholly. It is obvious that this number cannot be smaller than the larger of the two numbers,
because no number can divide a number smaller than itself wholly. It can also be seen that
the LCM of two numbers cannot exceed the product of the two numbers. Conclusively, it
may be said that LCM of two numbers lies between the larger of the two numbers and the
product of the two numbers.
Larger number ≤ LCM ≤ Product of numbers

Dept. of ECE, GAT Page 27


Microprocessor Lab (10ECL68)
In the program later, we attempt to find the LCM of the given two numbers by dividing all
the multiples of one of the numbers by the other number until the remainder is zero. At this
point, whichever multiple was completely divisible by the other number would be the LCM.

For example, to find the LCM of 24 and 32, we will divide all the multiples of 24 by 32 until
the remainder is zero:

STEP OPERATION ZERO REMAINDER?


1 24 ÷ 32 No
2 48 ÷ 32 No
3 72 ÷ 32 No
4 96 ÷ 32 Yes
STOP LCM = 96

It is obvious that you’ll arrive at the same LCM even when you divide multiples of 32 by 24.
In fact, this will be quicker (3 steps instead of 4).

The program below performs the same operations as in the table above. First, one of the
two numbers is put into the accumulator AX and the other into BX. The accumulator is zero
extended into DX to be able to perform 16-bit division. Next, before division, AX and DX are
stored on the stack. Division then determines whether the remainder is zero or not. If it is,
the operation is stopped and the current stack contents are saved as the LCM. If not, the
saved contents from the stack are put back into AX and DX and num1 is added to AX to
produce the next multiple, and DX is incremented in case of a carry. The program then
loops back to the next division.

If you’re interested, you can improve the efficiency of the above program by adding code to
check for the larger of the two numbers num1 and num2. Whichever turns out to be larger
may then be loaded into AX. This will reduce the number of steps required to determine the
LCM, and the reduction will be especially drastic when one of the numbers is far greater
than the other.

5.5. GCD/HCF – Greatest Common Divisor/Highest Common Factor


GCD of two numbers is, as the name indicates, the highest of the common divisors (factors)
of the two numbers. This implies that the GCD is a number that can divide both those
numbers wholly. It can be seen that the GCD cannot exceed the smaller of the two numbers,
because if it does it will not be possible to divide the smaller number fully. Also, the worst
possible GCD is 1, knowing well that 1 is a common factor of all numbers. Thus, GCD of two
numbers lies between 1 and the smaller of the two numbers.
1 ≤ GCD ≤ Smaller number

GCD is also known as HCF – highest common factor.

Dept. of ECE, GAT Page 28


Microprocessor Lab (10ECL68)
One way to find the GCD would be to find all of the numbers in the above range that divide
both numbers fully, and the largest of those would be the GCD. Another way would be to list
all the factors of both numbers, and the highest of the common factors will be the GCD. But
these methods would be strenuous and unnecessarily lengthy. The quickest way of finding
the GCD of two numbers is by EUCLID’s method, described below:

Euclid’s method to find GCD


First, one of the numbers is divided by the other to produce a remainder. This remainder is
used as the divisor for the next division, while the current divisor becomes the dividend.
Quotients in each division are immaterial. The process is carried on until the remainder is
zero, at which point the current divisor becomes the GCD. For example, the GCD of 24 and
32 is found as shown below:

So, the GCD of 24 and 32 is 8.


The result of the above program is 8H = 8 decimal. See if you can figure out how it works
with help from the step diagram below:

Dept. of ECE, GAT Page 29


Microprocessor Lab (10ECL68)

Program 5.4 LCM of Two Numbers Program 5.5 GCD of Two Numbers
.model small .model small
.stack 64H .data
.data num1 DW 24D
num1 DW 24D num2 DW 32D
num2 DW 32D gcd DW ?
lcm DW 2 dup(0) .code
.code mov AX,@data
mov AX,@data mov DS,AX
mov DS,AX mov AX,num1
mov AX,num1 mov BX,num2
mov BX,num2 next: mov DX,0
mov DX,0 div BX
rpt: push AX cmp DX,0
push DX je exit
div BX mov AX,BX
cmp DX,00H mov BX,DX
je exit jmp next
pop DX exit: mov gcd,BX
pop AX mov AH,4CH
add AX, num1 int 21H
jnc skip end
inc DX
skip: jmp rpt Result: gcd = BX =
exit: pop lcm[2]
pop lcm
mov AH,4CH
int 21H
end

Result: lcm = DX,AX =

6. Bit Manipulation
Dept. of ECE, GAT Page 30
Microprocessor Lab (10ECL68)

Program 6.1 To Check if the given Byte of Program 6.2 To Check if the given Byte of
data is Even or Odd data is Positive or Negative
.model small .model small
.data .data
num DB 71H num DB 80H
res DB ? res DB 00H
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AL,num mov AL,num
ror AL,01H rol AL,01H
jnc even jnc exit
odd: mov res,0FFH minus:mov res,0FFH
jmp exit exit: mov AH, 4CH
even: mov res,00H int 21H
exit: mov AH,4CH end
int 21H
end Result: res =

Result: res =

6.3. Counting 1’s and 0’s


For example, for an input of 8421H = 10000100001000012, the above program should
result in ones = 0004H (i.e. four 1’s), and zeros = 000CH (i.e. twelve 0’s).

6.4. 2-out-of-5 Code Check


A given byte (8-bits) is a valid 2-out-of-5 code if:
(i) Its first three most significant bits are all 0’s.
(ii) There are exactly two 1’s among the remaining five bits.

To see if a given byte is a valid 2-out-of-5 code, we have to check if it satisfies the above two
conditions. To check if its first 3 bits contain 0’s, we mask the remaining bits by ‘and’ing
with 11100000 (E0H), and then check if the result is 00000000 (00H). This is done by the

Dept. of ECE, GAT Page 31


Microprocessor Lab (10ECL68)
instruction “test AL, 0E0H”, which is equivalent to “and AL, 0E0H” plus “cmp AL, 00H”. But
note that the TEST instruction does not affect the contents of AL, unlike AND. Next, the
number of 1’s in the remaining 5 bits is counted and compared with 2. If the given byte
passes both these tests, then it is declared as a valid 2/5 code.

For example, 00011000 (18H), 00001001 (09H), 00000110 (06H) etc. are valid 2/5
codes.

Program 6.3 To Count the number of 1’s Program 6.4 To Check if the given Byte of
and 0’s in the given Word of data data is a valid 2/5 code or not
.model small .model small
.data .data
num DW 8421H num DB 18H
ones DB 0 res DB 00H
zeros DB 0 .code
.code mov AX,@data
mov AX,@data mov DS,AX
mov DS,AX mov AL,num
mov AX,num test AL,0E0H
mov BX,00H jne exit
mov CX,16 mov CX,05H
back: ror AX,1 mov BL,00H
jnc zero back: ror AL,1
one: inc ones jnc skip
jmp skip inc BL
zero: inc zeros skip: loop back
skip: loop back cmp BL,02H
mov AH,4CH jne exit
int 21H mov res,0FFH
end exit: mov AH,4CH
int 21H
Result: ones = end
zeros =
Result: res =

6.5. Bitwise Palindrome Check

Dept. of ECE, GAT Page 32


Microprocessor Lab (10ECL68)
A binary number is a bitwise palindrome if reversing its bit sequence results in the original
bit sequence. Examples of binary palindromes (in 8-bits) are numbers such as 10000001
(81H), 01100110 (63H), 10011001 (99H), 01011010 (5AH), 11100111 (E7H) etc.

Basically, a byte will be a bitwise palindrome when its first and last bits, second and second-
last bits etc. are the same. This is checked using four TEST instructions. For example, “test
AL, 81H” masks all the bits of AL except the MSB and LSB. The result (which is stored in a
temporary register) is then checked for parity. For it to be a bitwise palindrome, the
unmasked bits must be equal, either both zeros (0××××××0) or both ones (1××××××1), i.e.
it must show even parity. If it shows odd parity, then it is of the form 0××××××1 or
1××××××0, in which case it fails to be a bitwise palindrome. Observe that the program
jumps to “no” if in any stage the unmasked bits exhibit odd parity. Only a byte which
succeeds all four tests is declared as a valid bitwise palindrome.

6.6. Nibblewise Palindrome Check


A binary number would be a nibblewise palindrome if by reversing its nibbles (4-bits), we
get back the original number. Since each hexadecimal digit represents a nibble, i.e. is 4-bit,
this also means that a nibblewise palindrome is a hexadecimal number whose digits when
reversed gives back the original number. For example, 14H, when reversed gives 41H – so it
is not a nibblewise palindrome. But 44H is. So are 99H, 3773H, 5005H, and 172271H. For
now, we’ll stick to 16-bit nibble wise palindromes. These will be hexadecimal numbers of
the form XYYXH.

In the above program, let us assume data input is of the form WXYZH. Now, for it to be a
nibblewise palindrome, W must be equal to Z, and X equal to Y. To be able to verify this, we
make 2 copies of the data, in AX and BX. We ‘and’ AX with 0F0FH to be left with 0X0ZH.
Next, we rotate BX by 4 bits (= 1 hex digit) to the left. Since rotation circulates the data, BX
becomes XYZWH. BX is then ‘and’ed with 0F0FH to give 0Y0WH. Then, by comparing AX
and BX, we’re seeing if 0X0ZH is equal to 0Y0WH, which will be true if and only if X=Y and
Z=W. Thus we’ll know if the given number is a nibblewise palindrome or not.

Program 6.5 To Check if the given Byte of Program 6.6 To Check if the given Word of

Dept. of ECE, GAT Page 33


Microprocessor Lab (10ECL68)
data is a bitwise palindrome data is a nibblewise palindrome
.model small .model small
.data .data
num DB 5AH num DW 8228H
msgyes DB 10,13,'Bitwise res DW 0
Palindrome $' .code
msgno DB 10,13,'Not a Bitwise mov AX,@data
Palindrome $' mov DS,AX
.code mov AX,num
mov AX,@data mov BX,num
mov DS,AX and AX,0F0FH
mov AL,num mov CX,4
test AL,81H back: rol BX,1
jpo no loop back
test AL,42H and BX,0F0FH
jpo no cmp AX,BX
test AL,24H jne exit
jpo no mov res,0FFFFH
test AL,18H exit: mov AH,4CH
jpo no int 21H
lea DX,msgyes end
jmp disp
no: lea DX,msg no Result: res =
disp: mov AH,09H
int 21H
mov AH,4CH
int 21H
end

Result:

7. Array Operations
Dept. of ECE, GAT Page 34
Microprocessor Lab (10ECL68)
7.1. Addition of N Numbers
We’ll be given an array of N numbers, are we’re required to sum up all its elements. This can
be done as in the two programs below. Program 7.1(a) shows how BCD numbers may be
added, while 7.1(b) does the same with HEX numbers.

(a) Addition of N BCD numbers


In the following program, the input array contains five BCD numbers – 21, 13, 35, 1 and 24.
The instruction ‘$-array’ returns the number of bytes contained in ‘array’, and this value is
stored in ‘len’ and used as a counter when summing up the numbers. The instruction DAA
is used after each addition operation to adjust the hex result to BCD. The expected sum of
the above numbers is 94. Note that since DAA works only with 8-bit, we’ve restricted the
sum in the above program to 8-bits, which means the maximum possible sum is 99 BCD. If
you were to add BCD numbers resulting in a sum more than 99, you’ll get an incorrect
result using the above program. However, the correct sum may be obtained by adding
suitable additional code to the same program.

(b) Addition of N Hexadecimal numbers


Now we’ll be adding five 16-bit hexadecimal numbers – 1231H, 4398H, 1742H, 6518H
and 2019H. Recall that the instruction ‘$-array’ returns the number of bytes contained in
‘array’, so now it’ll return 10. Previously, in program 7.1(a), the number of elements in
‘array’ was equal to the number of its bytes, so “len DW $-array” worked. However, now
the number of elements in ‘array’ is half the number of its bytes, so we’ll have to use “ len
DW ($-array)/2” instead. The rest of the program is identical to 7.1(a), except for the
absence of DAA, and the use of 16-bit accumulator instead of 8-bit.

Dept. of ECE, GAT Page 35


Microprocessor Lab (10ECL68)

Program 7.1(a) Addition of N BCD Program 7.1(b) Addition of N Hexadecimal


numbers numbers
.model small .model small
.data .data
array DB 21H,13H,35H,01H,24H array DW 123FH,4A98H,17C2H,
len DW $-array 6518H, 2019H
res DB ? len DW ($-array)/2
.code res DW ?
mov AX,@data .code
mov DS,AX mov AX,@data
mov CX,len mov DS,AX
mov SI,0 mov CX,len
mov AL,0 mov SI,0
clc mov AX,0
back: adc AL,array[SI] clc
daa back: adc AX,array[SI]
inc SI inc SI
loop back inc SI
mov res,AL loop back
mov AH,4CH mov res,AX
int 21H mov AH,4CH
end int 21H
end
Result: res = 94H Result: res =

7.2. Largest/Smallest Of N Numbers


Largest of N numbers in an array may be found using the following algorithm:

START
1. Assume the first element in the array to be the largest number. Save array[0] in
accumulator.
2. Set index to the second element, and counter to N–1.
3. Compare current array element with accumulator.
4. If accumulator is larger, skip step 5 and go to step 6.
5. Overwrite accumulator with current array element.
6. Increment array index and decrement counter.
7. If counter is not zero, go back to step 3.
8. Save the accumulator’s contents as the largest array element.
STOP
To find smallest of N numbers, just replace the instruction JNB with JB in the above
program.

Dept. of ECE, GAT Page 36


Microprocessor Lab (10ECL68)
7.3. Bubble Sort (Ascending/Descending Order)
Bubble sorting algorithm sorts the input array (having N elements) using nested loops. The
inner loop compares and swaps adjacent elements as necessary. N elements would require
N–1 comparisons, and thus each iteration of the outer loop must perform N–1 iterations of
the inner loop. The outer loop positions one array element into its rightful place in the
sorted array in each iteration. When N–1 elements are positioned correctly, the last element
is automatically placed correctly. Thus the outer array must also run N–1 times before the
array is fully sorted.
Say we need to sort the given array in ascending order. The worst case input to test this
would be an array in descending order. As an example, consider a 4-element input array
{21, 13, 5, 1}. The following table illustrates how this 4-element array is fully sorted in 3
passes each of the outer and inner loops:

Note that we’re using registers CX and DX to maintain the count values of the inner and
outer loops respectively. In this case, N = 4. Therefore we require N–1 = 3 iterations each of
the inner and outer loops.

DX and CX both start equal to 3. CX is decremented with each comparison, and when it
reaches 0, DX is decremented. When DX reaches 0, the sorting is completed.

Dept. of ECE, GAT Page 37


Microprocessor Lab (10ECL68)

Notice how at the end of each outer loop one element is positioned in its rightful place. For
example, at the end of the first outer loop, 21 is placed bottommost. By the end of the next
outer loop, 13 is placed above 21. Next 5 goes on top of 13. The last element, 1, is
automatically placed correctly. This is analogous to bubbles rising in a glass of a fizzy drink
– the largest bubbles rise first and take the topmost positions, followed by the medium-
sized ones, and lastly the smallest ones. This is why this sorting technique came to be called
“Bubble” sorting.
The bubble sort program for Descending sort may be obtained from the above program,
just by replacing the instruction JBE (jump if below or equal) with JAE (jump if above or
equal).

Program 7.2 Largest of N numbers Program 7.3 Bubble Sort (Ascending order)
.model small .model small
.data .data
array DB 13H,35H,01H,41H,24H array DB 21H,13H,05H,01H
len DW $-array len DW $-array
res DB ? .code
.code mov AX,@data
mov AX,@data mov DS,AX
mov DS,AX mov DX,len
mov AL,array[0] dec DX
mov SI,1 outloop: mov CX,len
mov CX,len dec CX
dec CX mov SI,OFFSET array
back: cmp AL,array[SI] inloop: mov AL,[SI]
jnb skip cmp AL,[SI+1]
mov AL,array[SI] jbe noswap
skip: inc SI xchg AL,[SI+1]
loop back mov [SI],AL
mov res,AL noswap: inc SI
mov AH,4CH loop inloop
int 21H dec DX
end jnz outloop
mov AH,4CH
Result: res = int 21H
end

Result: array =

Dept. of ECE, GAT Page 38


Microprocessor Lab (10ECL68)

8. String Operations
8.1. String Transfer
A ‘string’ refers to a continuous sequence of memory locations containing a long stream of
data – in other words, an array. Specifically, a string refers to an array of ASCII data. A string
may be declared either as a sequence of characters enclosed within single quotes (str DB
‘abcdef’), or as a byte sequence of equivalent ASCII characters (str DB 61H, 62H, 63H,
64H, 65H, 66H).

In the following program, our objective is to transfer (copy) the given string ‘str1’ to
another memory location ‘str2’. This could have been done as in Program 1.4, but now we
will be using the string-move function MOVS (MOVe String). More specifically, we will be
using MOVSB (MOVe String Byte), since ASCII characters here are stored as bytes.

First, the address of the data segment is copied to both DS and ES registers. The source and
destination pointers SI and DI are also initialized. Thus the source of the string transfer will
be DS:SI, while its destination will be ES:DI. The instruction CLD clears the direction flag,
i.e. DF = 0, thus setting the string transfer in ‘auto-increment’ mode. This means that SI
and DI will automatically incremented after each byte transfer. The instruction MOVSB
transfers only one byte from DS:SI to ES:DI. Therefore, it is prefixed with REPNZ so that it
may be repeated until CX = 0.

The statement ‘len DB $-str1’ must immediately follow the declaration of str1, otherwise
the value of ‘len’ will be incorrect.

8.2. String Scan


We will now use the 8086 string-scan function SCASB (SCAn String Byte) to search for a
given byte in the given string. The SCASB instruction compares the AL register with a byte
block of memory, present in the extra segment ES and addressed by DI. Like all string
instructions, SCASB uses the direction flag (DF) to select either auto-increment or auto-
decrement operation for DI. They also repeat when prefixed by a conditional repeat
instruction.

In the following program, the given string ‘str’ must be tested to see if any location contains
the byte defined by ‘key’. As seen here, the SCASB instruction has a REPNE (REPeat while
Not Equal) prefix. The REPNE prefix causes the SCASB instruction to repeat until either CX
register reaches 0, or until an equal condition if found in any of the comparisons. Note that
the prefix causes CX to decrement without affecting any of the flag bits.
The SCASB instruction and the comparisons it makes changes the makes changes the flag
bits. The zero flag is set when SCASB finds the search element in the given string.

Dept. of ECE, GAT Page 39


Microprocessor Lab (10ECL68)

Program 8.1 String Transfer Program 8.2 String Scan


.model small .model small
.data .data
str1 DB 'abcdef' str DB 'abcdef'
len DB $-str1 len DW $-str
str2 DB ? key DB ‘C’
.code res DW 0
mov AX,@data .code
mov DS,AX mov AX,@data
mov ES,AX mov DS,AX
mov SI,OFFSET str1 mov ES,AX
mov DI,OFFSET str2 mov DI,OFFSET str
cld mov AL,key
mov CX,len cld
repnz movsb mov CX,len
mov AH,4CH repne scasb
int 21H jne exit
end mov res,00FFH
exit: mov AH,4CH
Result: str2 = int 21H
end
Result: res =
8.3. String Reversal
We will now see how a given string can be reversed. The easiest and most straightforward
way of doing it is by swapping the first and last elements, second and second-last elements,
and so on, in the given string until half length.

If the length of the string is ‘len’, then the last element is obviously the (len–1)th element.
Two pointers, SI and DI, point to the first (0th)and last elements respectively. The contents
of their memory locations are exchanged, and then SI is incremented, while DI is
decremented. This process is continued until the pointers reach half length.
One thing you mustn’t fail to notice in the above program is the use of the assembler
directive EQU. Instead of the usual ‘len DW $-str’, here we’ve used ‘len EQU $-str’, because
DW defines variables, while EQU defines constants. To be able to assign the value (len/2)
to ‘halflen’, MASM needs ‘len’ to be a constant, not a variable. So ‘len DW $-str’ will not
work in this case, and instead we’d have to use ‘len EQU $-str’.

Dept. of ECE, GAT Page 40


Microprocessor Lab (10ECL68)

8.4. String Palindrome Check


The concept of checking if a string is a palindrome is very much the same as that of string
reversal, except that now we will just be comparing the first and last elements, second and
second-last elements, etc., of the string, instead of swapping them. In any palindrome, these
elements that are being compared will be equal. Thus, if any of the comparisons results in a
mismatch, the string is not a palindrome.

Program 8.3 String Reversal Program 8.4 String Palindrome Check


.model small .model small
.data .data
str DB 'abcdef' str DB 'malayalam'
len EQU $-str len EQU $-str
halflen DW len/2 halflen DW len/2
.code res DW 0
mov AX,@data .code
mov DS,AX mov AX,@data
mov SI,0 mov DS,AX
mov DI,len mov SI,0
dec DI mov DI,len
mov CX,halflen dec DI
back: mov AL,str[SI] mov CX,halflen
xchg AL,str[DI] back: mov AL,str[SI]
mov str[SI],AL cmp AL,str[DI]
inc SI jne exit
dec DI inc SI
loop back dec DI
mov AH,4CH loop back
int 21H mov res,00FFH
end exit: mov AH,4CH
int 21H
Result: end
Result:

Dept. of ECE, GAT Page 41


Microprocessor Lab (10ECL68)

9. Programs to Use DOS Interrupt INT 21H Function Calls


9.1) Program for reading a Character from keyboard.
.model small
.data
msg DB ?
.code
mov AX,@data
mov DS,AX
mov AH,01H
int 21H
mov msg,AL
mov AH,4CH
int 21H
end

Result:

9.2) Program to display a string on 9.3) Program to display a character on


console. console.
.model small .model small
.data .code
msg DB 'Microprocessor Lab $' mov AX,@data
.code mov DS,AX
mov AX,@data mov DL,‘a’
mov DS,AX mov AH,02H
mov DX, OFFSET msg int 21H
mov AH,09h mov AH,4CH
int 21h int 21H
mov AH,4CH end
int 21H
end Result:

Result:

Dept. of ECE, GAT Page 42


Microprocessor Lab (10ECL68)
9.4) 8086 ALP TO CREATE A NEW FILE 9.5) 8086 ALP TO DELETE A FILE
.model small .model small
.stack .stack
.data .data
filename DB 'c:\8086\create.txt',0 filename DB 'c:\8086\delete.txt',0
.code .code
mov AX,@data mov AX,@data
mov DS,AX mov DS,AX
mov AH,3CH mov AH,41H
mov CX,00H mov CX,00H
mov DX,OFFSET filename mov DX,OFFSET filename
int 21H int 21H
mov AH, 4CH mov AH, 4CH
int 21H int 21H
end end

Result: Result:

9.6) 8086 ALP TO WRITE INTO A FILE 9.7) 8086 ALP TO READ FROM A FILE

.model small .model small


.stack .stack
.data .data
filename DB 'c:\8086\create.txt',0 filename DB 'c:\8086\create.txt',0
buffer DB 'yeah!, its successful, we buffer DB 256 DUP(0)
have written into file$ ' .code
.code mov AX, @data
mov AX,@data mov DS,AX
mov DS,AX mov AX,3d02h
mov AH,3CH mov DX,OFFSET filename
mov CX,00H int 21H
mov DX,OFFSET filename mov BX,AX
int 21H mov AH,3FH
mov BX,AX mov CX,256
mov AH,40H mov DX,OFFSET buffer
mov CX,50 mov AH,09H
mov DX,OFFSET buffer int 21H
int 21H mov AH,4CH
mov AH,4CH int 21H
int 21H end
end
Result: Result:

PART-II: Interfacing Experiments


Dept. of ECE, GAT Page 43
Microprocessor Lab (10ECL68)

Experiments on interfacing 8086 with the following interfacing modules through DIO
(Digital Input/output – PCI bus compatible) card.

1. Stepper Motor interface

1) 1. Program to rotate the stepper motor in clock-wise and anti-clock wise direction
.model small rol al,01h
.code loop back1
mov dx,020e3h mov ah,4ch
mov al,80h int 21h
out dx,al delay proc
mov cx,400 push cx
mov al,88h mov bx,0ff0h
back: mov dx,020e0h l2: mov cx,099ffh
out dx,al l1: loop l1
call delay dec bx
ror al,01h jnz l2
loop back pop cx
mov cx,200 ret
mov al,88h delay endp
back1:mov dx,020e0h end
out dx,al
call delay Result:

Dept. of ECE, GAT Page 44


Microprocessor Lab (10ECL68)

2) 2. Logic control board interface


.model small in al,dx
.data mov cl,al
cwr equ 020e3h in al,dx
pc equ 020e2h xor al,cl
pb equ 020e1h or al,bl
pa equ 020e0h mov dx,pa
.code out dx,al
mov ax,@data mov ah,4ch
mov ds,ax int 21h
mov al,82h end
mov dx,cwr
out dx,al Result:
mov dx,pb
in al,dx
mov bl,al
in al,dx
and al,bl
mov bl,al

3. Seven Segment Display interface

Dept. of ECE, GAT Page 45


Microprocessor Lab (10ECL68)

Dept. of ECE, GAT Page 46


Microprocessor Lab (10ECL68)

3. Seven segment display interface


.model small disp proc
.data mov cx,04
pa equ 020e0h next_c: mov bl,08
pb equ 020e1h mov al,[si]
pc equ 020e2h next_b: rol al,01
cwr equ 020e3h mov dx,pb
m1 db 10,13,"press any key to exit $" out dx,al
m2 db 8ch, 0c7h,86h,89h push ax
m3 db 0b0h,0a4h,0f9h,0c0h mov al,00h
.code mov dx,pc
mov ax,@data out dx,al
mov ds,ax mov al,11h
mov al,80h mov dx,pc
mov dx,cwr out dx, al
out dx,al pop ax
lea dx,m1 dec bl
mov ah,09h jnz next_b
int 21h inc si
start: lea si,m2 loop next_c
call disp ret
call delay disp endp
lea si,m3
call disp delay proc
call delay push cx
push ax push dx
mov ah,0bh mov dx,0ffffh
int 21h up: mov cx,4fffh
or al,al here: loop here
jnz stop dec dx
jmp start jnz up
stop: mov ah,4ch pop dx
int 21h pop cx
ret
delay endp
end

Result:

Dept. of ECE, GAT Page 47


Microprocessor Lab (10ECL68)
4. Keyboard Interface

Dept. of ECE, GAT Page 48


Microprocessor Lab (10ECL68)

4. Key Board Interface


dispmsg macro msg next_col: ror al,1
lea dx,msg jc display
mov ah,09h inc ch
int 21h dec cl
endm jnz next_col
.model small mov al,bh
.data dec bl
pa equ 020e0h jnz next_row
pc equ 020e2h jmp start
m1 db 10,13,"press any key from display: dispmsg m2
keyboard interface $" mov dl,ch
m2 db 10,13,10,13, "entered key cmp dl,0ah
is $" jc digit
.code add dl,07h
mov ax,@data digit: add dl,30h
mov ds,ax call dispchar
mov dx,020e3h mov ah,4ch
mov al,90h int 21h
out dx,al dispchar proc
dispmsg m1 mov ah,02h
start: mov al,80h int 21h
mov ch,0 ret
mov bl,3 dispchar endp
next_row: rol al,1 end
mov bh,al
mov dx,pc Result:
out dx,al
mov cl,8
mov dx,pa
in al,dx

Dept. of ECE, GAT Page 49

You might also like