#assembly #x86 #nasm
#сборка #x86 #nasm
Вопрос:
Предполагается, что мы должны закодировать рекурсивную функцию fibbonachi, используя стек в качестве домашнего задания. Поскольку у меня нет никакого способа запустить код NASM непосредственно на моем ноутбуке, я использовал браузерные компиляторы, такие как jdoodle и coding ground, чтобы проверить, работает ли мой код, и выполнить отладку. После целого дня непрерывной работы я не могу найти, почему мой код все еще выдает ошибку segmentation fault.
Я проанализировал структуру стека шаг за шагом и не могу найти там ошибку. Возможно, я упускаю что-то очевидное, поскольку я все еще изучаю NASM и не полностью усвоил некоторые концепции. Ошибка также может быть в онлайн-браузере или, по крайней мере, в том, как он обрабатывает выходные данные: обычно я использую printf, но я попытался перепрофилировать приведенный ими пример кода.
Для целей отладки значение R вводится с помощью mov dword[R]. Кроме того, поскольку при выводе dosent используется printf, он выводит awnser в виде символа ascii, где 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, выдает ошибку «ошибка сегментации». Ожидаемый результат — соответствующий номер Fibbonachi для ввода.
Комментарии:
1.
fib
пытается получить доступ[ebx]
, но вы не инициализировали егоebx
к моменту вызоваfib
.2. Кстати, это
sub esp, 4
в вашей_start
процедуре бессмысленно, поскольку вы даетеesp
другое значение в самой следующей строке.3. Используйте регистры для хранения значений, с которыми вы работаете; для этого они и предназначены. Вы намеревались использовать
mov ebx, [esp 4]
для загрузки аргумента из стека?