Sorting - Jonathan A Titus

Reprinted with permission from American Laboratory, Vol. 11, No. 10, pp. 133-136.
Copyright 1979 by International Scientific Communications, Inc.
Microcomputer interfacing
Q
Sorting
By Christopher A. Titus, Peter
R. Rony, David G. Larsen, and
Jonathan A. Titus
UITE OFTEN, a program will
execute much. faster if the
values it accesses are
sorted. Sorting also is useful when
data values or alphanumeric strings
have to be' output to a printer or a
cathode-ray tube (CRT) in a specific
order. Sorting is defined as the rearrangement of data values in a list,
table, record, or file in an ascending
or descending order. If the data
values consist of alphanumeric
strings, then the strings will be sorted
in alphabetic or alphanumeric order.
A number of different methods
can be used to sort data, including:
straight insertion sort, binary insertion sort, Shell's sort, bubble sort,
quick sort, heap sort, merge-exchange sort, and two-way merge
sort. In general, all of these sorting
methods can be classified as one of
the following sorting methods: insertion method, exchange method, selection method, merge method, distribution method. J ,2
This column discusses only the exchange method of sorting numeric
values. Specifically, this column is
concerned with the bubble sort method. This method is perhaps one of
the slowest methods that can be used.
However, it is probably easier to
write a bubble sort subroutine than
any other type of sort subroutine.
As an example of the use of the
bubble sort method to sort numeric
values that are stored in a list, assume that a certain list contains five
eight-bit unsigned data values
(nodes), as shown in Table 1. The list
is stored in memory from memory
location X to memory location
X + 4. If the data value (node) in
memory location X is greater than
the data value in memory location
X + I, the two values are exchanged.
This means that the data value in
memory location X is written into
memory location X + I, and the
value previously stored in memory
location X + I is stored in memory
location X. Because an exchange has
just taken place, a register or memory location is loaded with a specific
value to indicate that an exchange
has taken place. If the data value in
memory location X is less than the
data value in X + I, no exchange
takes place. This assumes that we
want to sort the list in ascending
order, where the smallest data value
eventually will be stored in memory
location X and the largest data value
eventually will be stored inX + 4.
Whether or not an exchange takes
place, the microcomputer next compares the data values in memory locations X + I and X + 2.. If the content of memory location X + I is
greater thanX + 2, an exchange takes
place. If the content of memory location X + I is less than the content of
memory location X + 2, no exchange
takes place. This compare-and-exchange process continues until the
microcomputer reaches the end of
the list. When the end of the Jist is
reached, the microcomputer examines the content of a register or memory location to see if any exchanges
took place. If any did, the micro-
Table 1
Bubble sorting a list of data
Memory address
X
X+1
X+2
X+3
X+4
Dr. C. Titus is Consultant, and Dr. J.
Titus is President, Tychon, Inc. Dr.
Rony, Department of Chemical Engineering, and Mr. Larsen, Department of
Chemistry, are with the Virginia Polytechnic Institute and State University.
Initially
3
2
5
4
1
1st pass 2nd pass 3rd pass 4th pass 5th pass
3
2
2
1
2
2
3
3
1
2
4
5
1
3
3
4
1
4
4
4
1
5
5
5
5
Results
2
2
2
1
1
3
3
1
2
2
4
1
3
3
3
1
4
4
4
4
5
5
5
5
5
79
b
ITHIS Sll1JROUTUJE USES T;'lE bUBbLE SORT ALGORITHC1
ITO SORT SINGLE PRE,CISIO'J (a-bIT>, l!c,SIGNED
INtJtluERS STORED 1:\1 t1E,;'lOHY.
E'JTER THIS SUbROUTl"JE
IWITH THE STARTI~G ADDRESS OF THE LIST
I(T'IE LQIoTER /-IDDRESS> I:-J REGISTEH PAIR H AcJD THE
IFlNkL ADDHESS IeJ REGI STER PAL R D.
usorrr.
PASSl,
t10 VAle
SUBL
f10VEA
,'lOVAD
SbbH
MOVDA
PlISHH
01lS1I D
f1VI C
000
'-'PI,
f10\!/-I'1
INXH
C'1 Prl
JC
N r.XT
o
J~
NEXT
o
no VbM
t10vt1k
LJCXH
'3E~<T,
!101/MB
INXrI
MVI C
377
DCXD
"10VAD
Of{kl::
,JN7.
UPl
IGET THE,LO bYTE OF TilE dIGHEST ADDRESS
ISUbTRkCT THE BEGI~~I~G LO ADDRESS
ISAVE THE RESl'LT H
E
IGET r-n: HI BYTE OF THE HIGHEST ADDRESS
I SUBTHACT THE BEG!"J'J I~JG n r ADDRESS
ISJO\VE THE HESl'LT DJ LJ
ISkVE TdE I'JITIAL ADDl1ESS
ISAVE THE bYTE COU1T O~ THE STAC~
ITllE C REGISTER IS USED TO !'JDICATE
I I F AI EXCHf-I'JGE TA;CES PLACE
IGET A 'lODE FROM THE LI ST
I 1-, CHEt1 E"JT H&L TO THE N EXT xo DE
ICQr1PARI:: A A'JD ME,,1ORY
I IF '1E!'10hY > 1\, DO NOT EXC!-lA'IlGE
ITdUl.
I',STEAD, EXAi1I'JE THE 'lEXT TWO
I~'ODES 1:. THE LI ST
I I F TilEY ARE ECl:AL, DO 'JOT
IEXCdf-l',GE THFl EITHER
ISAVE. THE: CO.'JTE"T OF ME:l0RY 1'3 Ii
ISAVE THE: CONTE:'-IT OF A IN ,1D1ORY
/lJACI( UP ] t1P10HY LOCATIO'I AND
ITHEJ SI-IVE TJiE CO:,TE!'JT OF b I:'l NE,;10RY
I1NCHEf1LJT T;tE PST ADDR.ESS
ITHE C HEGI STER IS l'SElJ TO I'JDl GATE
ITHAT A'J E;:{CIiA.1GE liAS TAKE'J PLACE
IDE.G!<E..'lE'JT TdI:: GOl."JT
I I S Tli E CO lI'JT U0 0 ?
IdAVE
ILL ST,
~OT
CHECKED TdE E1TIRE
Sf) ){EEP CHECi(l'JG
o
~10\lAC
OHAA
POPD
DOP:-l
J-g
!>ASSI
U
nET
IGET THE EXC;1i-dGf, I!JDI GATOR UTO
ITdE l-\ HEGI STEFl. I\'JD SET THE FLAGS
ILlJkD {;",r: '.v I Td TdE bYTE COl'~lT
ILOAD H&L WITrl TdE I~ITIAL ADDRESS
IA\J EXCf-lh'JGE OGCUO{RJ::D, SO EXA,'ll'JE
ITdE LI ST lJ~E :10l'tE Tlt1E
I RETl.1mJ ',J;{ E 'J
~'JO
l::XCrlA, GES
T /~i{ E PI.. AC E
Figure 1 A ltst-sort subroutine that uses the exchange method (bubble sort),
computer has to make another pass
through the list. Only when the microcomputer makes a pass through
the entire list, and no exchanges take
place, is the list sorted,
Table I contains a list that is bubble sorted. On the first pass through
the list, the three and the two are exchanged. The five and the four also
are exchanged, followed by the five
and one. The largest value in the list
(five) is bubbled up to the top of the
list. On the second pass, the four is.
bubbled up to memory location
X + 3, just behind the five. The three
and two are bubbled up to their appropriate positions in the list in the
third and fourth passes. On the fifth
pass, the data values are in the proper sequence. No exchanges take
place, therefore the list is sorted. A
80
bubble sort subroutine for the 8080,
which can be used to sort eight-bit
unsigned numbers, is listed in Figure
1.
The BSORT subroutine must be
called with the starting address of the
list in register pair H and the final
address of the list in register pair D.
If the list in Table I is to be sorted by
the BSORT subroutine, register pair H
would contain the address X and register pair D would contain the address X + 4, Starting at BSORT, the
8080 subtracts the starting address
(X) from the final address (X + 4)
and saves the result (the node count)
in register pair D. The node count is
used to indicate to the 8080 when it
has reached the end of the list. At
PASSl, the starting address of the list
(X) and the node count are saved on
the stack. The C register is loaded
with 000, because it will be used as
the exchange indicator. If an exchange takes place during a pass
through the list, the C register will be
set to 377. This means that when the
8080 has examined all of the nodes in
the list, it will examine the content of
the C register to see if any exchanges
took place during the last pass
through the list. If the C register contains 377, at least one exchange took
place, so the 8080 will have to make
another pass through the list.
The 8080 begins the actual compare-and-exchange instructions at
UP!. The first node is moved to the A
register, and the memory address in
register pair H is incremented by one
to X + I. The two in memory location X + I then is compared to the
three in the A register. If the content
of X + 1 is equal to or greater than
the content of the A register, the
8080 jumps to NEXT. This means that
no exchange should occur.
If the content of memory (two) is
less than the content of the A register
(three), the node in memory is moved
to the B register and the content of
the A register is stored in memory.
The memory address is then decremented (X + I to X) and the node in
the B register (two) is written back
into memory. The memory address is
then incremented (to X+' I). The C
register is loaded with 377 because an
exchange just took place.
By decrementing the node count
contained in register pair D, the 8080
can determine if the entire list has
been examined. If it has not, the
8080 jumps back to UPl, where the
three in X + 1 is compared to the five
in X + 2. As expected, these two
nodes are not exchanged. The next
time through the UPl loop, the 8080
compares and exchanges the five in
X + 2 with the four in X + 3. The next
time that the UPl loop is executed,
the five in X + 3 is compared and exchanged with the one in X + 4. At
this point, the node count in register
pair D is decremented to zero. Because of this, the 8080 examines the
content of the C register. If the content of the C register is nonzero
(377), the 8080 jumps back to PASSI
so that it can make another pass
through the list. The 8080 will con"tinue to make passes through the list
*050 000
i;SS 16,
~10VA£
SUbL
~i0V£H
PASS I,
MOVAD
SDbH
RRC
MOVDA
'10VA£
RRC
MOVEA
PUSHH
PUSH 0
t1VI C
000
UPl,
PUSHD
MOVI::I1
INXH
MOVDM
INXH
I'lJXH
MOVAM
XRAD
JM
POSN EG
IGET TiiE FI'JAL ADDRESS (LSbY>
IS1.!BTRHCT THE PJITIHL ADDRESS (LSBY>
ISAVE THE RESVLT (LSUY>
IGET THE FINAL HDliRESS (MS8Y)
ISUbTRHCT THE INITIHL ADDRESS (MSBY)
IDI\lID£ THE RESULT bY TWO
lAND SAVE IT
ITHE'1 DIVIDE THE LSUY OF THE
I REStJL T BY TWO
ISAVE THE START.!'IJG ADDRESS OF THE LIST
I SAVE THE NODE COU'lJT
I SET THE EXCHA\lGE I~'1DI CATOR TO
IZERO
I SAVE THE 'lODE COU'lT
IGET rn i; LSBY OF A NODE
IINCREMEJ'lT THE: MEMORY ADDRESS
IGET THE MSBY OF THE SAME NODE
II'lJCREMEi'lT THE ADDRESS TloJICE
ITO THE MSbY OF THE NEXT ,'lODE
IGET ITS riSbY I'JTO THE A REGISTER
IEX'OR IT WITH THE tiSbY 1'1 D.
I I F ONE OF THE "1UMBERS IS "1EGIATIVE, FI:'1D OUT WHICH O"1E
o
SUH2,
DCXH
MOVAE
SUBM
MOVBA
INXH
MOVAD
SHBM
JC
DW"11
o
onAb
JZ
DHN I
o
EXCH,
O;(AS IS,
MOVI3M
MOVMD
DCXH
MOVCM
MOVME
DCXH
MOVMB
DCXH
MOVMC
I"1XH
I"1XH
MVI C
IGET THE ~1S13Y OF THE
SECO"1D /I
ISAVE THE MSbY OF THE FIRST
IDECREME..'lT TO THE LSBY
IGET THE LS8Y OF THE SECOND /I
ISAVE THE LSBY OF THE FIRST (I
IDECRL'1ENT TO THE MSBY
ISAVE THE MSI:JY OF THE SECO"1D /I
IDECREliE"1T TO THE LSBY
ISAVE THE LSBY OF THE SECO'JD/I
I I:IICREME'1T TO THE MSBY
ITHEN TO THE LSBY
ITHEJ SET THE EXCHA'iGE I'lDICATOR
ITO
POPD
DCXD
MOVAD
ORAE
J"J7..
UPI
IPOP THE '/ODE COU'JT
IDECREME.."JT IT
IGET THE MSHY OF THE "10DE COU"1T
lOR IT 'NlTH THE LSBY
II S THE cous r 7..ERO? rIO, THEN
IEXAMI,'iE; THE "1EXT TWO :-lODES.
POPD
POPH
MOVAC
ORAA
J'\JZ
nASS I
IYES, POP THE SECO·'1D 'iODE COtNT
IA'lD THE STAR1"UG ADDRESS OF
ITHE LIST. WHAT IS THE STATE OF
ITHE E.'<:CHA'IGE I~'1DICATOR?
IAN EXCH/,'lGE TOOK PLACE, SO
IE"{A,1UE THE LIST AGA1"'J;
RET
1"10 EXCHA\JGES TOOI( PLACE,
MOVAM
lIS THE 'JEGATIVE :'lUMBER IN MEMORY?
Ji'l
EXCH
o
IYES, THE'J IT IS LESS THAN THE
IPOSI Tl VE Ntr.iBER 1"1 REGI STER
I PAl R D.
DCXH
JMP
O;(ASI S
IDECREME,'n TO THE LSBY
I AND TH B'1 EXAM 1'1 E TH E ;'1 EXT TWO
INODES IN THE LI ST
o
DWN I,
GET O-"1E or THE :1SBYS
ISUBTRACT THE OTHE:R
ICONTE.''lT OF MEMORY I S LARGER
ITHA'I THE CONTENT FO REGI STER
I PAl R D, SO THE a RD.ER I S CORRECT
1"10 CARRY, ARE THEY EQUAL?
IYES, THElJ DO NOT EXCHA'1GE THEM
INO\~
377
o
POSNEG,
IDECREl1ENT THE ADDRESS TO THE LSBY
IHOTH NUMI:JERS ARE POSITIVE OR
INEGAT.! VE, SO "COMPARE" THEl1
onAH
o
377
RETUR\J.
Figure 2 A bubble sort subroutine for tti-bit signed numbers.
until the C register contains zero
when the node count is decremented
to zero. When the C register does
contain zero, the 8080 will return
from the BSORT subroutine.
If desired, signed or floating-point
numbers or alphanumeric strings can
be sorted using the bubble sort method. Assume that 16-bit signed numbers are to be sorted, and that the
sign of the number is stored in the
most significant bit of the 16-bit
number. If the sign bit is a logic zero,
the sign of the number is positive and
if the bit is a logic one, the number is
negative. The bubble sort subroutine
listed in Figure 2 performs the same
operations as the one in Figure 1, except that the difference between the
starting and final addresses of the list
has to be divided by two, because
each 16-bit number (node) requires
two eight-bit memory locations for
storage. Also, the 8080 cannot execute any 16-bit comparison instructions, so two eight-bit subtractions
must be performed.
Perhaps the biggest difference between the two subroutines is that the
8080 has to check the signs of the two
nodes being compared. If the sign of
both numbers is the same (both positive or negative), the 16-bit comparison can be performed as usual. However, if the sign of the two numbers is
different (one number is positive and
one number is negative), the 8080 has
to ensure that the positive number is
stored in the higher memory locations.
In Figure 2, the 8080 first subtracts
the starting address in register pair H
from the final address in register pair
D. Note that the final address is the
address where the least-significant
byte (LSBY) of the last number is
stored. After the 16-bit final address
is subtracted, the 16-bit result is rotated once to the right, because each
node requires two memory locations
for storage. Note that the most significant byte (MSBY) of the result is
rotated to the right first, followed by
the LSBY.
At PASS), the starting address of
.fhe list and the node count are saved
on the stack. The C register is set to
zero to indicate that no exchanges
have taken place. Starting at UP), the
node count in register pair D is again
saved on the stack. The first 16-bit
81
i
node then is moved to register pair
D. The LSBY of the node is moved to
the E register and the MSBY (including the sign bit) is moved to the D
register. The address in register pair
H is incremented twice, so that it addresses the memory location containing the MSBY and sign bit of the second node. The MSBY's of both nodes
are then exclusive-oa'd, and if the
signs of the numbers are different
(one is positive and one is negative),
the 8080 jumps to POSNEG.
If the 8080 jumps to POSNEG, it has
to determine which number is positive and which is negative. To accomplish this the 8080 gets the MSBY
from the node in memory, and performs an OR operation with itself to
set the 8080's flags. If the number in
memory is negative, the 8080 jumps
to EXCH, so that the negative number
is moved to a lower memory address
and the positive number is moved to
a higher memory address. If the
number in memory is positive, the
two numbers are in the proper order,
so the 8080 simply jumps to OKASIS
when the node count is decremented
and the exchange indicator is examined.
If both numbers are positive or
negative, the 8080 does not execute
the JM to POSNEG, stored in memory
just before SUB2. Instead, the 16-bit
number in memory is subtracted
from the 16-bit number in register
pair D. If the content of memory is
greater than or equal to the content
of register pair D, the 8080 jumps to
DWNl, because the numbers are in the
proper order. If the content of memory is less than the content of register
pair D, the 8080 executes the instructions at EXCH.
The instructions at EXCH move the
node addressed by register pair H to
register pair B. The larger of the two
nodes then is moved from register
pair D to memory. The memory address in register pair H then is decremented, so that the smaller node in
register pair B can be saved in memory, at a lower memory address. The
two nodes now have been exchanged,
so the exchange indicator (the C register) is set to 377.
Whether or not an exchange has
taken place, the 8080 executes the instructions at OKASIS when two nodes
82
have been compared (and exchanged,
if required). The instructions at OKASIS cause the node count to be
popped off of the stack. The node
count then is decremented and examined to see if it is equal to zero. If it is
not (meaning that there are additional nodes in the list that must be ex"
amined), the 8080 jumps back to
UPI, where the decremented node
count is saved on the stack and the
compare-and-exchange instructions
are executed again.
If the node count is decremented
to zero, the JNZ to UPI is not executed. The 8080 has completed a pass
through the list, so it must check the
state of the exchange indicator. To
do this, the 8080 pops the original
node count and the starting address
of the list off the stack. The exchange indicator then is moved to the
A register, where it performs an OR
operation with itself. If an exchange
took place during the last pass
through the list, the 8080 jumps back
to PASS\. If this happens, register
pair D contains the node count and
register pair H contains the starting
address of the list. If no exchanges
took place during the last pass
through the list, the content of the C
register is zero, so the 8080 returns
from the BSS16 subroutine. The 16bit signed numbers contained in the
list have been sorted.
As mentioned earlier, sorting lists
are necessary because a program may
execute faster if it has to access these
lists or alphanumeric strings may
have to be sorted before being
printed. There are a number of other
sorting methods that can be used to
sort data. Many of these methods are
much faster than the bubble sort
method, but there are very few that
are easier to write.
References
I. KNUTH, D.E. The Art of Computer
Programming, Vol. 3, Sorting and
Searching (Addison-Wesley, Reading,
MA,1973).
2. TITUS, C.A. 808018085 Software Design, Book 2. Asynchronous Communications, Interrupt and Data
Structure for 8080- and 8085-based
Microcomputers (Howard W. Sams &
Co., Indianapolis, IN, 1979).