我们应该使用堆栈作为作业来编写递归的fibbonachi函数。因为我无法直接在笔记本电脑上运行NASM代码,所以我使用了基于浏览器的编译器(例如jdoodle和编码基础)来测试我的代码是否有效并进行调试。经过一整天的不间断工作,我无法找到为什么我的代码仍然出现分段错误错误。
我已经逐步分析了堆栈的结构,并在那里找不到错误。我可能仍缺少明显的东西,因为我仍在学习NASM,但尚未完全掌握一些概念。该错误也可能是在线浏览器内部发生的,或者至少是如何处理输出的:我通常使用printf,但是我尝试重新利用它们提供的示例代码。
出于调试目的,使用mov dword [R]输入R的值。另外,由于输出剂量器使用printf,因此它将输出显示器作为ascii characther,其中characther的ascii代码是输出的数字。
section .text
global _start
fib:
;ret <- esp
;R
;ebps
;??? <- ebp?
cmp dword[esp + 4], 4
JS TroisOuMoins
mov dword[ebx], esp
add dword[ebx], 8
push dword[ebx]
;ebps' <- esp
;ret
;R
;ebps
;??? <- ebp?
mov ebp, dword[esp]
;ebps' <- esp
;ret
;R
;ebps <- ebp
sub dword[esp + 8], 1 ; R = R - 1
push dword[esp + 8]
;R' <- esp
;ebps'
;ret
;R
;ebps <- ebp
call fib
;fib1 <- esp
;ebps'
;ret
;R
;ebps <- ebp
push dword[esp]
;fib1 <- esp
;fib1
;ebps'
;ret
;R
;ebps <- ebp
mov ebx, dword[esp + 16]
mov dword[esp + 4], ebx
pop dword[esp + 16]
dec dword[esp]
;R' <- esp
;ebps'
;ret
;fib1
;ebps <- ebp
call fib
;fib2 <- esp
;ebps'
;ret
;fib1
;ebps <- ebp
mov ebx, dword[esp]
add dword[esp + 12], ebx
sub esp, 8
;ret <- esp
;fibTotal
;ebps <- ebp
mov ebp, dword[ebp]
;ret <-esp
;fibTotal
;ebps
;??? <-ebp?
TroisOuMoins:
ret
_start:
push ebp ; --> 1 - sauvegarder l'état de la pile et du record d'activation présent (le contenu du ebp est mis sur la pile)
mov ebp, esp ; Mettre la valeur du "stack pointer" dans le "base pointer".
mov dword[R], 4
push ebp
push dword[R]
call fib
pop dword[R]
mov ebp, dword[esp]
sub esp, 4
mov esp, ebp
pop ebp ; <-- 1- restauration du ebp original
mov ebx, dword[R]
mov [sum], ebx
mov ecx, msg
mov edx, len
mov ebx, 1
mov eax, 4
int 0x80
mov ecx, sum
mov edx, 1
mov ebx, 1
mov eax, 4
int 0x80
mov eax, 1
int 0x80
section .data
R: times 4 db 0 ; 32-bits integer = 4 bytes
msg db "Fibbonachi is "
len equ $ - msg
segment .bss
sum resb 1
根据设计,该代码适用于情况1、2和3(该函数跳过了情况1、2和3的递归调用,因此问题可能出在其中。)大于4的任何数字都会产生错误“分段故障”。预期结果是输入的对应的斐波那契数。