用于二分查找的 8085 程序
先决条件 - 二分搜索
问题——在 8085 微处理器中编写一个汇编语言程序,在 10 个数字的列表中找到一个给定的数字。如果找到将 1 存储在输出中,否则将 2 存储在输出中。此外,存储迭代次数和元素的索引(如果找到)。
示例:让列表如下:
Test-1:
Input: 21H (at 3000H)
Output: 1 (success) in 3001H,
2 (index) in 3002H, and
3 (iteration number) in 3003H.
Test-2:
Input: 22H (at 3000H)
Output: 2 (failure) in 3001H,
X (don't care) in 3002H, and
4 (iteration before failure) in 3003H
假设 -
假设要与之比较的数据存储在3000H中,数字列表从3010H到3019H,结果存储如下:3003H中的迭代次数,3001H中的成功/失败(1/2)和3002H中的索引
算法 -
- 将 0 移到 Accumulator 并存储在 3003H 中,表示到目前为止的迭代次数。
- 将 0 和 9 分别移动到 L 和 H 寄存器。
- 从 3000H 加载累加器中要搜索的数据,并将其移至 B 寄存器。
- 从 3003H 中检索迭代次数,将其加一并存储回 3003H。
- 将 H 寄存器的值移动到累加器并与 L 寄存器进行比较。
- 如果产生进位,则二进制搜索结束,因此跳转到第 20 步。
- 将 L 寄存器的值加到累加器并右移。
- 将累加器的值存储在寄存器 C 中并强制复位进位标志(如果设置)。
- 在 DE 寄存器对中加载数组的起始地址。
- 将累加器的值加到寄存器 E 并将结果存储在 E 中。
- 将 0 移至累加器并使用 ADC 命令将由于先前加法产生的任何可能的进位相加,并将其存储回寄存器 D。
- 加载 DE 对指向的值并与寄存器 B 比较。如果产生进位,则跳转到第 15 步,如果设置了零标志,则跳转到第 17 步。
- 将寄存器 C 的值移动到累加器并递减累加器。
- 将累加器的值移动到 H 并跳转回第 4 步。
- 将寄存器 C 的值移动到累加器并递增累加器。
- 将累加器的值移动到 L 并跳转回第 4 步。
- 将 1 移至 3001H 中的 Accumulator ad store 表示成功。
- 将寄存器 C 的值移动到累加器并存储在 3002H 中以保存索引。
- 跳转到声明 21。
- 将 2 移到 Accumulator 并存入 3001H 表示失败。
- 结束程序。
程序 -Address Label Instruction Comment 2000H LDA 3000H Load value to search for 2003H MOV B, A Save it in register B 2004H MVI A, 0 2006H STA 3003H Store iteration number 2009H M0V L, A 200AH MVI A, 9 200CH MOV H, A Storing high and low indices in H-L pair done 200DH start_loop: LDA 3003H Load iteration number 2010H INR A Increment iteration number 2011H STA 3003H Store back in 3003H 2014H MOV A, H Store high index in Accumulator 2015H CMP L Compare with lower index 2016H JC loop_end If carry generated, this means high is less than low so binary search over 2019H ADD L Add high to low 202AH RAR Right rotate to divide by two and generate mid 202BH MOV C, A Save mid in register C 202CH JNC reset If carry flag unset, go directly to reset. 202FH CMC Force unset carry flag 2030H reset NOP 2031H LXI D, 3010H Load start address in D-E pair 2034H ADD E Add mid to E to get the offset 2035H MOV E, A Get the changed address back in E so it becomes a pointer to arr[mid] 2036H MVI A, 0 Handle possible overflow 2038H ADC D 2039H MOV D, A Memory index handled 203AH LDAX D Load the array element in accumulator 203BH CMP B Compare with value to search 203CH JC else_block Implies value is greater than value at mid, so we need low=mid+1 203FH JZ print If zero flag set, match found. Jump to print block 2042H MOV A, C Neither executed so value 2043H DCR A mid=mid-1 2044H MOV H, A h=mid 2045H JMP start_loop Jump back 2046H else_block MOV A, C We need low=mid+1 2047H INR A mid=mid+1 2048H MOV A, L l=mid 2049H JMP start_loop 204CH print MVI A, 1 Move 1 to Accumulator 204EH STA 3001H Store it in 3001H to indicate success 2051H MOV A, C Move index, that is mid, back to Accumulator 2052H STA 3002H Store it in 3002H 2055H JMP true_end Jump to end of the code 2058H loop_end MVI A, 2 205AH STA 3001H Store 2 in 3001H to indicate failure 205DH true_end HLT Terminate
解释 -
- 我们在步骤 2 中将较高和较低索引的值(在本例中为 9 和 0)分别移动到 H 和 L 寄存器
- 在第 5 步中比较较高和较低的指数。在得到一个进位(表示低>高)时,我们跳到循环结束,否则转到第 6 步。
- 在第 7 步和第 8 步中,我们将 H 和 L 寄存器的值相加并右移,相当于 (high+low)/2 以便在 C 语言中找到索引
- 在第 10 步中,我们将 mid 的值添加到数组的起始地址,使其充当偏移量,类似于 C 中 *(arr+x) 和 arr[x] 的相同方式。
- 步骤 11 确保不会发生溢出。
- 在第 12 步中,我们将中间索引处的值与要搜索的值进行比较。如果相等,我们跳出循环并适当地设置值。
- 如果它们不相等,则第 12 步适当地分支,让我们将 mid 递增/递减 1 并将该值移动到 L/H 寄存器,必要时(就像在 C 中完成的 high=mid-1 或 low=mid+1 一样)并返回循环开始,即第 2 步。
注意 –如果要搜索的元素小于数组中的最小元素,此方法将失败。为了处理这个问题,在循环的开头添加一个额外的零,并在步骤 2 中分别将值 10 和 1 移动到 HL 对。