题目
在附加段中,有一个从小到大顺序排列的无符号数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组的长度。在AX中有一个无符号数,要求在数组中查找AX,如找到,CF=0,并在SI中给出该元素在数组中的偏移地址;如未找到,置CF=1
思路
折半查找过程如下:
(1) 初始化被查找数组的首尾下标,low=1,high=n
(2) 若low>high 则查找失败,置CF=1,退出程序
否则计算中点 mid = (low+high)/2
(3) ax与中点元素比较,若ax = r[mid] ,则查找成功,程序结束;
若k<r[mid] 转为步骤四,若k>r[mid] ,转为步骤五
(4) 低半部分查找lower,high = mid-1,返回步骤2,继续查找
(5) 高半部分查找higher,low = mid+1,返回步骤2,继续查找
代码
datasg segment
low_idx dw ?
high_idx dw ?
datasg ends
;-----------------
extendsg segment
array dw 10,0,1,2,3,4,5,6,7,9,10 ;数组的第一个单元存放数组的长度
extendsg ends
;=================
codesg segment
assume es:extendsg,ds:datasg,cs:codesg
main proc far
start:
push ds
sub ax,ax
push ax
mov ax,datasg
mov ds,ax
mov ax,extendsg
mov es,ax
mov ax,3 ;ax中存放待比较的数
;------------------
;compare ax with first number
cmp ax,es:[di+2] ;ax和第一个数比较
ja chk_last ;大于第一个数
lea si,es:[di+2] ;第一个数的偏移地址赋值给si
je exit ;ax等于第一个数,CF=0
stc ;ax不等于第一个数,CF=1
jmp exit
;compare ax with last number
chk_last:
mov si,es:[di] ;有几个数
shl si,1 ;si*2 一个数占两个byte
add si,di ;si指向最后一个数
cmp ax,es:[di] ;和最后一个数比较
jb search ;小于最后一个数,则需要查找
je exit ;ax等于最后一个数,CF=0
stc ;ax不等于最后一个数,CF=1
jmp exit
;Search for value within the list
search:
mov low_idx,1 ;low_idx 指向第一个数
mov bx,es:[di]
mov high_idx,bx ;high_idx 指向最后一个数
mov bx,di ;bx指向数组元素的首地址 (bx+2)为第一个数的地址
mid:
mov cx,low_idx
mov dx,high_idx
cmp cx,dx
ja no_match ;low_idx>high_idx 则退出查找
add cx,dx
shr cx,1 ;计算cx = (low_idx+high_idx)/2
mov si,cx ;si为(low_idx+high_idx)/2
shl si,1 ;si*2 指向下一次查找的地址
compare:
cmp ax,es:[bx+si] ;mid和ax比较
je exit ;相等退出
ja higher ;ax>[mid]
lower:
dec cx ;cx = (low_idx+high_idx)/2-1
mov high_idx,cx ;high_idx = (low_idx+high_idx)/2-1
jmp mid
higher:
inc cx ;cx = (low_idx+high_idx)/2+1
mov low_idx,cx ;low_idx = (low_idx+high_idx)/2+1
jmp mid
no_match:
stc
;------------------
exit:
ret
main endp
codesg ends
end start
调试
一、测试ax能找到的情况,ax = 3
能找到,偏移量是8
二、测试ax小于第一个数的情况
三、测试ax大于最后一个数的情况
四、测试ax夹在中间没有找到的情况
ax = 8