Не удается найти источник ошибки прерывания сегментации

#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] для загрузки аргумента из стека?