程序集intel x86调用函数与局部变量

时间:2016-10-20 08:37:49

标签: c assembly nasm

我遇到了二进制搜索实施的问题。请注意,我不想修改此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中做错了什么会引发错误,任何帮助都会非常感谢。

2 个答案:

答案 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的回答