我正在尝试使用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_it
或jae end_fib_it
为真且程序必须跳转,它就会产生分段错误。我用dump_regs
进行了一些调试,发现while循环运行完美,jmp fib_it_while
没有问题。
答案 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
指令会立即销毁您刚刚放入的内容!
由于您仅使用其他寄存器ECX
和EDX
,因此最好将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
。