Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly NASM-JBE指令给出了分段错误_Assembly_Nasm - Fatal编程技术网

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

Assembly NASM-JBE指令给出了分段错误,assembly,nasm,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

我正在尝试使用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
fibonacci\u it(n):
int f_i-1=1;
int f_i-2=1;
如果(n==0):
返回1;
其他:
int i=1;
int f_i=1;
而(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
%包括“asm_io.inc”
段.数据
提示db“输入编号:”,0
第2部分:bss
fibnum resd 1
段.文本
全球ASMU主
asm_main:
输入0,0
普沙
mov-eax,提示符
调用打印字符串
调用read_int
mov[fibnum],eax
推送dword[fibnum]
称之为谎言
调用print_int
波帕
mov-eax,0
离开
ret
小谎:
输入12,0;3个局部变量:f_i,f_i-1,f_i-2
普沙
莫夫·德沃德[ebp-4],1;初始化f_i
莫夫·德沃德[ebp-8],1;初始化f_i-1
莫夫·德沃德[ebp-12],1;初始化f_i-2
mov-ecx,1;i=1
mov-edx,1;n的比较运算符
cmp[ebp+8],edx;再绕一圈
结束fib\u it:
mov-eax[ebp-4];返回f_i
波帕
离开
ret
程序首先从终端读取一个整数。然后将其作为fib_it的参数推送到堆栈中 当我运行程序时,它给出了一个分段错误。我发现每次
jbe end\u fib\u it
jae end\u fib\u it
都是真的,程序必须跳转,然后给出一个分段错误。我对
dump_regs
进行了更多的调试,发现while循环运行得很好,
jmp fib_it_while
没有问题

我发现每次jbe end_fib_it或jae end_fib_it都是真的,程序必须跳转,然后它就会给出一个分段错误

你的观察可能根本不是问题

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

最简单的解决方案可能是以另一种形式
ret
结束fib_it:

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

不要使用
pusha
/
popa
您想在
EAX
中返回一个结果,但是后面的
popa
指令将立即销毁您刚才放在那里的内容

由于您仅使用附加寄存器
ECX
EDX
,因此最好将
pusha
更改为
push ECX
push EDX
。同时将
popa
更改为
pop-edx
pop-ecx


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

@Codey我添加了一个优化。
输入0,0
也非常慢。如果你想谈论优化,使用内存做任何事情(并像OP那样复制内存)比英特尔Haswell上的简单的
add eax,edx
/
add edx,eax
要慢12到18倍。至少他们决定将循环计数器保留在寄存器中,并使用循环上限只读。(比另一种方法要好得多,对于
inc[mem]
使用RMW,对于
cmp
使用另一个加载)对于一个像样的asm斐波那契(它将序列存储在一个数组中),请参阅。第一个版本只是一个简单的一次一个版本,带有register
mov
。更高版本通过对介绍代码的各种优化展开:)将所有数据保留在内存中而不是寄存器中的速度非常慢
addeax,edx
/
addedx,eax
更有效地计算斐波那契序列!从相当简单的开始,查看一些好的编写方法。
popa
leave
ret 4      ; The 4 will remove the parameter from the stack
end_fib_it:
  mov     eax, [ebp-4]        ; return f_i
  popa
mov     edx, 1              ; comparison operator for n
cmp     [ebp+8], edx        ; n <= 1 ?
cmp     dword [ebp+8], 1        ; n <= 1 ?