NASM - JBE指令给出了分段错误

时间:2017-09-09 09:08:54

标签: assembly nasm

我正在尝试使用NASM汇编程序在汇编中实现斐波纳契算法。 这是算法的伪代码

fibonacci_it(n):
    int f_i-1 = 1;
    int f_i-2 = 1;

    if (n==0):
        return 1;
    else:
        int i = 1;
        int f_i = 1;
        while (i < n):
            f_i = f_i-1 + f_i-2
            f_i-2 = f_i-1
            f_i-1 = f_i
            i = i + 1
        return f_i

我尝试的内容如下:

%include "asm_io.inc"

segment .data
prompt      db  "Enter number: ", 0

segment .bss
fibnum      resd 1

segment .text
    global asm_main

asm_main:
    enter   0,0
    pusha   

    mov         eax, prompt
    call        print_string
    call        read_int
    mov         [fibnum], eax

    push        dword [fibnum]
    call        fib_it
    call        print_int

    popa
    mov         eax, 0
    leave
    ret



fib_it:
    enter   12,0                ; 3 local variables: f_i, f_i-1, f_i-2
    pusha

    mov     dword [ebp-4], 1    ; initialize f_i
    mov     dword [ebp-8], 1    ; initialize f_i-1
    mov     dword [ebp-12], 1   ; initialize f_i-2
    mov     ecx, 1              ; i = 1
    mov     edx, 1              ; comparison operator for n
    cmp     [ebp+8], edx        ; n <= 1 ?
    jbe     end_fib_it          ; if n <= 1 -> end and return 1

fib_it_while:
    dump_regs 1
    mov     eax, [ebp-8]        ; eax = f_i-1
    add     eax, [ebp-12]       ; eax = f_i-1 + f_i-2
    mov     [ebp-4], eax        ; f_i = f_i-1 + f_i-2
    mov     eax, [ebp-8]        ; eax = f_i-1
    mov     [ebp-12], eax       ; f_i-2 = f_i-1
    mov     eax, [ebp-4]        ; eax = f_i
    mov     [ebp-8], eax        ; f_i-1 = f_i
    inc     ecx                 ; i += 1
    cmp     ecx, [ebp+8]        ; i < n ?
    jae     end_fib_it          ; end while loop if i < n
    jmp     fib_it_while        ; else -> loop again

end_fib_it:
    mov     eax, [ebp-4]        ; return f_i
    popa
    leave
    ret

程序首先从终端读取整数。然后它将此作为fib_it的参数推送到堆栈 当我运行程序时,它会产生分段错误。我发现,每次jbe end_fib_itjae end_fib_it为真且程序必须跳转,它就会产生分段错误。我用dump_regs进行了一些调试,发现while循环运行完美,jmp fib_it_while没有问题。

1 个答案:

答案 0 :(得分:3)

  

我发现每次jbe end_fib_it或jae end_fib_it为true且程序必须跳转然后它会产生分段错误。

您的观察可能根本不是问题。

push        dword [fibnum]
call        fib_it

当你调用fib_it时,你会在堆栈上推一个dword,然后你就不会在任何地方弹出它。

最简单的解决方案可能是以ret的替代形式结束fib_it:

popa
leave
ret 4      ; The 4 will remove the parameter from the stack

请勿使用pusha / popa

end_fib_it:
  mov     eax, [ebp-4]        ; return f_i
  popa

您希望在EAX中返回结果,但后面的popa指令会立即销毁您刚刚放入的内容!

由于您仅使用其他寄存器ECXEDX,因此最好将pusha更改为push ecx push edx。同时将popa更改为pop edx pop ecx

优化

mov     edx, 1              ; comparison operator for n
cmp     [ebp+8], edx        ; n <= 1 ?

如果您只是使用附加注册表EDX,为什么会使用其他注册表? 如果您将这对指令更改为:

cmp     dword [ebp+8], 1        ; n <= 1 ?

前面提到的pusha / popa替代品只会是push ecx / pop ecx