Laynetworks  
Web laynetworks.com Google
Home | Site Map | Tell a friends
Management Tutorials
Download
Tutorials
History
Computer Science
Networking
OS - Linux and Unix
Source Code
Script & Languages
Protocols
Glossary
IGNOU
Quiz
About Us
Contact Us
Feedback
 
Sign up for our Email Newsletter
 
Get Paid for Your Tech Turorials / Tips

 

 

Home > Computer Science >Computer Fundamentals
 
CS 01 CS 02 CS 03 CS 04 CS 05 CS 06 CS 07 CS 08 CS 09 CS 10 CS 11 CS 12 CS 13 CS 14 CS 15 CS 16 CS 17
 
Computer Fundamentals
 
Program in 8086 assembly language to multiply two 4 digit packed BCD nos.and print the result as ascii(decimal) value
contributed by Kailas Jagtap
 

.model small
.data

;Messages for user

s0 db 0dh,0ah,'MULTIPLICATION OF TWO 4 DIGIT PACKED BCD NUMBERS ..By Kailas Jagtap$'

s1 db 0dh,0ah,'Enter first 4-digit Decimal no (XXXX): $'

s2 db 0dh,0ah,'Enter second 4-digit Decimal no (XXXX): $'

s3 db 0dh,0ah,'Above nos. first converted to packed BCD form $'

s33 db 'and then to hex. form',0dh,0ah,0ah,'Packed BCD output : $'

s333 db 0dh,0ah,0ah,'Hexadecimal output : $'

s4 db 0dh,0ah,'Multiplication of above two nos.(printed in Hex) : $'

s44 db 0dh,0ah,'Multiplication of above two nos.(printed in ASCII) : $'

s5 db 0dh,0ah,' $'

s6 db 0dh,0ah,'***************** ERROR!!! - INVALID INPUT ****************** $'

n1 db 4 dup(0) ;storage for 1st no. from Keyboard (4 digits in unpacked ¼D form)

n2 db 4 dup(0) ;storage for 2nd no. from Keyboard (4 digits in unpacked ¼D form)

pnum1 dw 1 dup(0) ;2-byte storage for 1st no.(4 digits in packed BCD form)

pnum2 dw 1 dup(0) ;2-byte storage for 2nd no.(4 digits in packed BCD form)

unum1 db 4 dup(0) ;4-byte storage for 1st no.(4 digits in unpacked ¼D form)

unum2 db 4 dup(0) ;4-byte storage for 2nd no.(4 digits in unpacked BCD form)

;(unum1 & unum2(8 bytes)also used for storing upk remainders

;as they will become free after initial use)

hnum1 dw 1 dup(0) ;2-byte storage for 1st hex no.

hnum2 dw 1 dup(0) ;2-byte storage for 2nd hex no.

result dw 2 dup(0) ;4-byte storage for multiplication result(packed Hex)

uresult db 8 dup(0) ;8-byte storage for multiplication result(unpacked Hex)

quot db 8 dup(0) ;8-byte storage for quotient(unpacked Hex)

dividend dw 1 dup(0) ;2-byte storage for addr.of varying dividend

quotient dw 1 dup(0) ;2-byte storage for addr.of varying quotient

rmcnt db 1 dup(0) ;remainder counter

err_flg db 1 dup(0) ;error flag for indicating invalid i/p

.code

start:

mov ax,@data ;initialise ds with data seg. addr.

mov ds,ax

call disp_nl ;move cursor to new line

mov ah,9 ;display initial msg.

lea dx,s0

int 21h

call disp_nl ;move cursor to new line

call disp_nl ;move cursor to new line

mov err_flg,0 ;clear error flag

mov ah,9 ;display enter 1st no. msg.

lea dx,s1

int 21h

lea bx,n1 ;get 1st 4-dig.no. and store in

call input ;unpacked BCD form

cmp err_flg,0 ;is input invalid?

jz noerr ;if valid(z) go to get 2nd no.

;otherwise comeout flashing err msg

iperr: call disp_nl ;go to new line

call disp_nl ;go to new line

mov ah,9 ;display err msg.

lea dx,s6

int 21h

mov ah,4ch ;hand over control to DOS

int 21h

noerr: mov ah,9 ;display enter 2nd no. msg.

lea dx,s2

int 21h

lea bx,n2 ;get 2nd 4-dig.no.and store in

call input ;unpacked BCD form

cmp err_flg,0 ;is input invalid?

jnz iperr ;if yes(nz) comeout flashing err msg

;convert nos. n1 & n2 from unpacked to packed BCD

lea bx,n1 ;get 1st no.

call u_to_p ;convert

mov pnum1,ax ;store converted no.

lea bx,n2 ;get 2nd no.

call u_to_p ;convert

mov pnum2,ax ;store converted no.

;convert first no. from packed BCD to unpacked

lea si,pnum1 ;get addr. of 1st packed no.

lea di,unum1 ;get addr. for storing no. converted to unpacked form

call p_to_u ;convert from packed to unpacked

 

lea bx,unum1 ;get start addr. of 1st unpacked no.

call u_to_h ;convert 4 bytes of unpacked no. to equivalent 2 byte hex

mov hnum1,dx ;store converted hex no.

 

;convert second no. from packed BCD to Hex

lea si,pnum2 ;get addr. of 2nd packed no.

lea di,unum2 ;get addr. for storing no. converted to unpacked form

call p_to_u ;convert from packed to unpacked

 

lea bx,unum2 ;get start addr. of 2nd unpacked no.

call u_to_h ;convert 4 bytes of unpacked no. to equivalent 2 byte hex

mov hnum2,dx ;store converted hex no.

;display pk BCD and hex nos.

call disp_nl ;move cursor to new line

mov ah,9 ;display pk BCD output msg.

lea dx,s3

int 21h

lea dx,s33

int 21h

 

;display packed BCD nos.(pnum1 & pnum2)

lea si,pnum1 ;get addr.of 1st pk BCD no.(no.in 2 byte word)

call display ;display 1st pk BCD no.

call disp_nl ;move cursor to new line

lea si,pnum2 ;get addr.of 2nd pk BCD no.(no.in 2 byte word)

call display ;display 2nd pk BCD no.

mov ah,9 ;display hex output msg.

lea dx,s333

int 21h

 

;display hex nos.(hnum1 & hnum2)

lea si,hnum1 ;get addr.of 1st hex no.

call display ;display 1st hex no.

call disp_nl ;move cursor to new line

lea si,hnum2 ;get addr.of 2nd hex no.

call display ;display 2nd hex no.

;multiply nos.(in hex form) i.e. hnum1 X hnum2

mov ax,hnum1 ;get 1st no.

mov cx,hnum2 ;get 2nd no.

mul cx ;word to word mul.- result in dx(msb) & ax(lsb)

mov result,dx ;store msb part first

mov result+2,ax ;store lsb part

;display mul.result in hex form

call disp_nl ;move cursor to new line

call disp_nl ;move cursor to new line

mov ah,9 ;display mul.in hex msg.

lea dx,s4

int 21h

lea si,result ;get addr.of result (msb part)

call display ;display msb part

lea si,result+2 ;get addr.of result (lsb part)

call display ;display lsb part

;------------------

;convert result from packed(4 byte Hex) to unpacked(8 byte Hex)

lea si,result ;get addr. of result(msb)

lea di,uresult ;get addr. for storing no. converted to unpacked form

call p_to_u ;convert from packed to unpacked

lea si,result+2 ;get addr. of result(lsb)

lea di,uresult+4;get addr. for storing no. converted to unpacked form

call p_to_u ;convert from packed to unpacked

;display msg 'mul.result in ascii'

call disp_nl ;move cursor to new line

call disp_nl ;move cursor to new line

mov ah,9 ;display mul.in hex msg.

lea dx,s44

int 21h

;divide result(dividend) by 10 successively until quotient is <10

;collect remainders in each /10 and display them in reverse order

;which will be mul.result displayed in decimal

lea si,uresult ;get start add. of unpacked result

lea di,quot ;get start add. of unpacked quotient

;every quot has one digit less than dividend

nxt_div: mov [dividend],si ;save current pointers(addr.)

mov [quotient],di

mov dh,0ah ;get divisor 10

mov ah,[si] ;first get two msb digits(upk) for division(1st now & next in loop)

mov ch,8-1 ;counter(0-7) for dividing 8 upk digits

mov cl,4 ;counter for nibble shifting

div_agn: inc si ;point to next dig of current dividend

inc di ;point to next dig of current quotient

mov al,[si] ;get next dig and combine it with earlier

shl ah,cl ;remainder to carry out next division

or al,ah ;make 1 byte packed binary from 2 upk bytes

mov ah,0 ;(e.g. 02 0E converted to 00 2E bin )

div dh ;ax/dh, ah=rem (00 to 09 always) al=quo(00 to 0f always)

mov [di],al ;store current quot. dig in quotient

dec ch ;all 8 dig of dividend are divided?

jnz div_agn ;if not,get next dig for division

;otherwise, save current remainder(ah) on stack

mov al,0 ;only ah can not be pushed on stack

push ax ;save remainder on stack(which is upk BCD digit)

inc rmcnt ;incr.rem counter by 1

;check whether after successive div. quot. is reduced to <10

;i.e. first 7 bytes are 0 and last byte is <10

mov cl,0 ;counter for counting zeros in quotient

mov di,[quotient];get quotient start addr.

chk_z: mov ah,[di] ;get next dig from quotient

cmp ah,0 ;is dig 0 ?

jnz div_cont ;if not, continue dividing the quotient again

inc di ;otherwise point to next dig for checking

inc cl ;update zero counter

cmp cl,7 ;is it crossing 7 ?

jl chk_z ;if not(0-6), get next dig from quotient for checking

mov ah,[di] ;otherwise get last(8th)dig

cmp ah,9 ;is it <10 ?

jle disp_bcd ;if yes(0-9), go to display all remainders

;otherwise, continue dividing the quotient again

div_cont: mov si,[dividend];get start addr.of dividend

mov cl,8 ;counter for filling zeros

mov al,0 ;load zero

fz: mov [si],al ;fill a byte of dividend with 0

inc si ;point to next location

loop fz ;loop until all 8 bytes filled with 0

 

mov si,[quotient] ;now si will point to old quot.(treating it as new dividend)

mov di,[dividend] ;and di will point to old dividend (which will store new quot.)

jmp nxt_div ;go to divide quotient again

;

disp_bcd: call disp_ln ;ah=last rem, display it first

dbcd: pop ax ;ah=next rem in reverse order

call disp_ln ;display all rem one by one

dec rmcnt ;all rem over?

jnz dbcd ;if not,get next one

mov ah,4ch ;otherwise, hand over control to DOS

int 21h

;-----------------------------------------------------------------

;get 4-dig.no.from Keyboard and store in 4 byte buffer(in unpacked BCD form)

input PROC NEAR

mov cl,4 ;counter for 4 bcd dig i/p

again:

mov ah,1 ;dos int call for geting keyboard i/p

int 21h ;input is in al

cmp al,30h ;check for validity(below 0?)

jb inval ;if <30h, set err flg

cmp al,39h ;check for validity(beyond 9?)

jg inval ;if >39h, set err flg

sub al,30h ;make from ascii to bin

mov [bx],al ;store it in buffer

inc bx ;point to next location in buffer

dec cl ;all 4 i/p are over?

jnz again ;if not(nz), loop for next input

ret ;otherwise return, as 4 i/ps collected

inval: mov err_flg,0ffh ;set err flag

ret ;return immediately breaking i/p loop

input ENDP

;convert 4-digit BCD no. from unpacked(4 bytes) to packed(2 bytes) form

u_to_p PROC NEAR

mov ah,[bx] ;get 1st upk no.

mov cl,4 ;counter for nibble shifting

shl ah,cl ;shift right nibble to left e.g.change 03 to 30

inc bx ;point to next no.

add ah,[bx] ;add next no. to 1st shifted no.

inc bx ;point to next no.

mov al,[bx] ;get next upk no.

shl al,cl ;shift right nibble to left

inc bx ;point to next no.

add al,[bx] ;add next no. to no.shifted earlier

ret ;return with ax=packed no.

u_to_p ENDP

;Convert 4-digit BCD no. from packed(2 bytes) to unpacked(4 bytes)form

p_to_u PROC NEAR

mov ax,[si] ;get packed no.

call conv_pu ;first convert no.in ah to unpacked & store

mov ah,al ;then get no.in al for conversion

inc di ;point to next storage location

call conv_pu ;convert no.in al to unpacked & store

ret

p_to_u ENDP

conv_pu PROC NEAR

push ax ;save no.in ah for future use

and ah,0f0h ;mask lower nibble to extract upper nibble

mov cl,4 ;load shift count

shr ah,cl ;shift right 4 times to shift upper nibble to right

mov [di],ah ;store unpacked no. e.g. in packed 24h, 02 extracted

inc di ;point to next storage location

pop ax ;restore old no. in ah

and ah,0fh ;mask upper nibble to extract lower nibble

mov [di],ah ;store unpacked no. e.g. in packed 24h, 04 extracted

ret

conv_pu ENDP

;display 4-dig. hex no. available in a word(2 bytes)

;e.g bx=1234h i.e. bh=12h bl=34h

display PROC NEAR

mov bx,[si] ;get hex no. in bx(display bh & bl one by one)

call dis_byt ;first display upper byte(in bh)

mov bh,bl ;move byte in bl to bh for display

call dis_byt ;display lower byte

ret

display ENDP

dis_byt PROC NEAR

mov ah,bh ;get byte in ah

and ah,0f0h ;mask lower nibble

call conv_un ;conv. upper nibble of byte to ascii(result in ah)

call disp ;display upper nibble of byte in ah

mov ah,bh ;get byte in ah again

and ah,0fh ;mask upper nibble

disp_ln: call conv_ln ;conv. lower nibble of byte to ascii(result in ah)

call disp ;display lower nibble of byte in ah

ret

dis_byt ENDP

;convert upper nibble in byte from BCD to ascii

;input ah=BCD no. ouput ah=ascii code

conv_un PROC NEAR

shr ah,1 ;shift right 4 times e.g. 10h to 01h, add 30h

shr ah,1 ;to it to make it 31h(ascii for 1)

shr ah,1

shr ah,1

conv_ln:add ah,30h ;convert to ascii code(also used for conv.of lower nibble)

cmp ah,39h ;if no.>9 i.e.A to F add 7 to make

jle conv ;it corresponding displayable ascii code

add ah,7 ;e.g if 0C, 0C+7=13h, 13h+30h=43h(ascii for C)

conv: ret

conv_un ENDP

disp PROC NEAR

mov dl,ah ;int 21 needs byte(to be displayed) in dl

disp1: mov ah,2 ;select function no. of int 21

int 21h ;dos call for displaying byte in dl

ret

disp ENDP

disp_nl PROC NEAR ;move cursor to new line on screen

mov ah,9

lea dx,s5

int 21h ;display cr & lf

disp_nl ENDP

;convert 4-digit BCD no. from unpacked to equivalent hex form

;e.g. upk no. in 4 bytes - 01 02 03 04, hex no. in 2 bytes - 04D2 h

;bx=start addr.of upk BCD no. dx=actual hex no.

u_to_h PROC NEAR ;e.g 01 02 03 04 = 1x1000 + 2x100 + 3x10 + 4

mov ax,1000 ;First do calculation for 1000's place e.g. 1x1000

mov ch,0 ;word to word mul. so ch should be 0

mov cl,[bx] ;get upk BCD byte for mul.

mul cx ;ax X cx Result in dx(MSB) & ax(LSB)

;we can not use just 'mul cl' here, as 1000 D = 03E8 H

;which will require word mul. & not byte mul.

;after mul.dx=0 always, as max.is 1000x9=9000D=2328H

;which definately fit in 2 bytes(in ax), so we can

;spoil dx and use for other work

mov dx,ax ;save mul.result of 1000's place

push dx ;save dx as used in further mul.

mov ax,100 ;do calculation for 100's place e.g. 2x100

inc bx ;point to next byte of upk BCD

mov cl,[bx] ;again word mul.required as max is 9x100=900D=0384H

mul cx ;word to word mul.

pop dx ;get previously saved calculation of 1000's place

add dx,ax ;add calculations of 100's place and 1000's place

;dx not necessary to save as no word to word mul. further

mov ax,10 ;do calculation for 10's place e.g. 3x10

inc bx ;point to next byte of upk BCD

mov cl,[bx] ;byte mul.ok(word mul.not required as max.is 9x10=90D

mul cl ;which can fit in one byte only

add dx,ax ;add result to above addition of two places

 

inc bx ;point to next byte of upk BCD

mov cl,[bx] ;get no.at one's place

mov ch,0 ;word to word addition so ch should be 0

add dx,cx ;add last byte to above addition of three places(e.g add 4)

ret

u_to_h ENDP

end start

end

 
Top  
Back Next
 
Donation | Useful links | Link to Laynetworks.com | Legal | SharePoint Development
Copyright © 2000-2010 Lay Networks All rights reserved.