Binary search
Twelve sorted bytes searched by halving the range, with the index left in e, 0xFF when the value is not there, and the middle kept on the stack while the accumulator does the reading.
Twelve bytes in order, and the program finds which one holds 91 by halving the range it is looking
in until nothing is left. It leaves the index in e, or FF when the value is not in the array.
Two elements are read out of the twelve, where walking the array would read ten.
Bubble sort left an array in order. This is what being in order is worth: every comparison throws away half of what is left, so an array of a thousand elements takes about ten reads and one of a million takes about twenty.
You need to know: the "Bubble sort" Example and the "Addressing on the Z80" lecture. What is new here is a loop that jumps straight to an element instead of walking to it, which on this machine is an address worked out by hand every time round.
srl a is the halving: shifting a number one place right divides it by two and throws the remainder
away, which is the rounding down that (low + high) / 2 wants. It is the unsigned shift, which is
right here because an index is never negative.
high is one past the range it is looking in, so it starts at count and the loop runs while
low < high. The M68K page keeps the last index instead and lets it go down to -1, which it can
afford because it is working in longs. Here low and high are bytes, and a byte that goes below
zero comes back as 255, which as an unsigned comparison is the largest number there is and would
keep the loop going forever. Nothing in the program ever subtracts past zero now.
The four instructions after ld hl, numbers are how a byte gets added to a pair, because there is
no add hl, a: the low half is added in a, and the carry out of that addition is what inc h
puts into the high half. It is two instructions when the array cannot cross a 256 byte boundary and
four when it might, and this one keeps the jr nc because you cannot see from the source where the
assembler put the array.
push af and pop af are there because a has two jobs in one pass. It carries the middle index
into the address arithmetic and then has to hold the element that was read, so the index goes on the
stack for the two instructions in between and comes back in whichever branch is taken. Every path
through the loop pops exactly once, which is what keeps sp where it started.
The two probes are 38 and then 91. Each one either matches, or moves low past the middle, or
brings high down to it, and the loop ends when low catches high up. e comes out at 09,
which is the index of 91, so de reads 5B09: the target in d and the answer in e.
Try changing ld d, 91 to ld d, 90, which is not in the array. de comes out at 5AFF, the FF
that ld e, 0xFF put there before the loop started, because a search that finds nothing has to say
so and 0 is a perfectly good index.