我遇到了二进制搜索实施的问题。请注意,我不想修改此c代码,我试图将其转换为汇编代码。这是我的代码:
int binary_search_c(int n, int list[], int low, int high) {
int middle;
if (low > high)
return -1;
middle = (low + high)/2;
if (n == list[middle])
return middle;
if (n < list[middle]) {
high = middle - 1;
} else {
low = middle + 1;
}
return binary_search_c(n, list, low, high);
}
这是我在汇编中的二进制搜索。我已经用我第一次添加的内容评论了NEW,因此可能存在问题,尽管我很确定我的问题在于bin。
;* int binary_search(int n, int list[], int low, int high); *
;*****************************************************************************
%define n [ebp+8]
%define list [ebp+12]
%define low [ebp+16]
%define high [ebp+20]
binary_search:
push ebp
mov ebp, esp
sub esp, 4 ;one local var |
%define middle [ebp-4] ; define local var as middle | NEW
mov eax, low ; pull low into register
cmp eax, high ; compare low to high low > high
jle less; ; if less than or greater, go to less
mov eax, -1 ; move -1 into eax for return
jmp return; ; call return/end function
less: ;if low is not > high
mov eax, low ;move middle into register
add eax, high ;high+low
mov ebx, 2 ;move 2 into ebx for div
xor edx, edx ;clear edx |
xor eax, eax
div ebx ; div eax, by 2 =>(low+high)/2 | NEW
mov middle, eax ;move (low+high)/2 into middle
mov eax, n ; move middle into eax
mov edi, list ; move list into edi for list call
mov edx, middle ; move middle into edx as list index |
lea esi, [edi+edx*4] ; grab list[middle] |
mov ebx, [esi] ; move list[middle] into register| NEW
cmp eax, ebx ; compare n and list[middle]
jne notE; ; if not equal (n ==list[middle]
mov eax, middle ;move middle into eax for return
jmp return; ;call return/end function
notE: ;if n !=list[middle]
mov eax, n ;move eax into n
mov edi, list ; move list into edi to access list
mov ebx, middle ; move middle into ebx as index |
lea esi, [edi+ebx*4] ; grab list[middle] |
mov ebx, [esi] ;move list[middle] into ebx |NEW
cmp eax, ebx ; compare n and list[middle]
jge .else; ; if greater than or equal n < list[middle]
mov eax, middle ;move middle into eax for return
sub eax, 1 ;middle-1
mov ebx, high ; put high into ebx for replacement
mov ebx, eax ; high = middle-1
jmp bin; ;jump to next part[not return]
.else: ;if n >= list[middle]
mov eax, middle ;move middle into eax to add 1
add eax, 1 ; middle+1
mov ebx, low ;move low into ebx for change in low
mov ebx, eax ;low = middle+1
bin: ; final return
mov eax, high ; move high into eax for push
push eax ; push high
mov ebx, low ;low into ebx
push ebx ; push low
mov ecx, list ; list for push
push ecx ;push list
mov edx, n ;n for push
push edx ;push n |
call binary_search ; call search |
add esp, 16 ; add 16=>(4*4) to stack for reset | NEW
return: ;end function
leave
ret
因此,在尝试查找错误后切断我的代码后,尝试使用bin
运行任何内容时出现了seg错误
我认为我可能在使用add esp, 16
添加到堆栈时出错了,虽然我不确定它是否是我第一次调用函数许多参数和手头的局部变量。
我很乐意对我的代码进行任何优化,我对标记为NEW的事情感到厌倦,我需要弄清楚我在bin中做错了什么会引发错误,任何帮助都会非常感谢。
答案 0 :(得分:2)
mov eax, low ;move middle into register add eax, high ;high+low mov ebx, 2 ;move 2 into ebx for div xor edx, edx ;clear edx | xor eax, eax ;clear eax | div ebx ; div eax, by 2 =>(low+high)/2 | NEW
在此代码中,您尝试计算 middle ,但实际上并没有这样做,因为您在分割之前将EAX寄存器归零!
请删除xor eax, eax
说明。
mov ebx, high ; put high into ebx for replacement mov ebx, eax ; high = middle-1 jmp bin
这是另一个问题:
您想要设置较低的分区,但实际上并不存储新的高索引!
这样就可以了:
mov high, eax ; high = middle-1
jmp bin
同样适用于 low 索引。
答案 1 :(得分:0)
只是对工作代码的更新,具有div by 2
而不是移位,效率低下。万一其他人需要它,在这里:
;* int binary_search(int n, int list[], int low, int high); *
;*****************************************************************************
%define n [ebp+8]
%define list [ebp+12]
%define low [ebp+16]
%define high [ebp+20]
binary_search:
push ebp
mov ebp, esp
sub esp, 4 ;one local var
%define middle [ebp-4] ; define local var as middle
mov eax, low ; pull low into register
cmp eax, high ; compare low to high low > high
jle less; ; if less than or greater, go to less
mov eax, -1 ; move -1 into eax for return
jmp return; ; call return/end function
less: ;if low is not > high
mov eax, low ;move middle into register
add eax, high ;high+low
mov ebx, 2 ;move 2 into ebx for div
xor edx, edx ;clear edx
div ebx ; div eax, by 2 =>(low+high)/2
mov middle, eax ;move (low+high)/2 into middle
mov eax, n ; move middle into eax
mov edi, list ; move list into edi for list call
mov edx, middle ; move middle into edx as list index
lea esi, [edi+edx*4] ; grab list[middle]
mov ebx, [esi] ; move list[middle] into register
cmp eax, ebx ; compare n and list[middle]
jne notE; ; if not equal (n ==list[middle]
mov eax, middle ;move middle into eax for return
jmp return; ;call return/end function
notE: ;if n !=list[middle]
mov eax, n ;move eax into n
mov edi, list ; move list into edi to access list
mov ebx, middle ; move middle into ebx as index
lea esi, [edi+ebx*4] ; grab list[middle]
mov ebx, [esi] ;move list[middle] into ebx
cmp eax, ebx ; compare n and list[middle]
jge .else; ; if greater than or equal n < list[middle]
mov eax, middle ;move middle into eax for return
sub eax, 1 ;middle-1
mov high, eax
jmp bin; ;jump to next part[not return]
.else: ;if n >= list[middle]
mov eax, middle ;move middle into eax to add 1
add eax, 1 ; middle+1
;move low into ebx for change in low
mov low, eax ;low = middle+1
bin: ; final return
mov eax, high ; move high into eax for push
push eax ; push high
mov ebx, low ;low into ebx
push ebx ; push low
mov ecx, list ; list for push
push ecx ;push list
mov edx, n ;n for push
push edx ;push n
call binary_search ; call search
add esp, 16 ; add 16=>(4*4) to stack for reset
return: ;end function
leave
ret
感谢@Fifoernik的回答