Printf вызывает ошибку сегмента

Я пытаюсь скомпилировать код сборки в 32-разрядной версии Linux Ubuntu. Но когда я компилирую его с nasm -felf32 assembly.asm && gcc assembly.o && ./a.out , я сталкиваюсь с Segmentation fault (core dumped). Я так понял, что проблема с printf.

Я много искал в Интернете, было несколько таких вопросов. Но ни один из ответов не сработал для меня.

    global  main
    extern  printf

    section .text
    main:
    push    ebx                     ; we have to save this since we use it

    mov     ecx, 90                 ; ecx will countdown to 0
    xor     eax, eax                ; rax will hold the current number
    xor     ebx, ebx                ; rbx will hold the next number
    inc     ebx                     ; rbx is originally 1
    print:
    ; We need to call printf, but we are using rax, rbx, and rcx.  printf
    ; may destroy rax and rcx so we will save these before the call and
    ; restore them afterwards.

    push    eax                     ; caller-save register
    push    ecx                     ; caller-save register

    mov     edi, format             ; set 1st parameter (format)
    mov     esi, eax                ; set 2nd parameter (current_number)
    xor     eax, eax                ; because printf is varargs

    ; Stack is already aligned because we pushed three 8 byte registers
    call    printf                ; printf(format, current_number)

    pop     ecx                     ; restore caller-save register
    pop     eax                     ; restore caller-save register

    mov     edx, eax                ; save the current number
    mov     eax, ebx                ; next number is now current
    add     ebx, edx                ; get the new next number
    dec     ecx                     ; count down
    jnz     print                   ; if not done counting, do some more

    pop     ebx                     ; restore rbx before returning

    ret
    format:
    db  "%20ld", 10, 0

*** исходный код скопирован с учебного сайта Nasm. Это для печати чисел Фибоначчи.


person Linda    schedule 18.06.2015    source источник
comment
Вы забыли задать вопрос. Какая помощь вам нужна? Вы начали анализировать дамп ядра?   -  person David Schwartz    schedule 18.06.2015
comment
@DavidSchwartz printf вызывает ошибку сегментации. Я хочу помочь решить это.   -  person Linda    schedule 18.06.2015
comment
Код предназначен для 64-битной версии Linux, но вы компилируете и запускаете ее для 32-битной версии.   -  person samgak    schedule 18.06.2015
comment
@samgak, компилирующий его в 32-битном режиме, вызывает эту ошибку: инструкция не поддерживается в 64-битном режиме. это для линий толчка, поп   -  person Linda    schedule 18.06.2015
comment
@MattMcNabb это код для печати первых 90 чисел Фибоначчи.   -  person Linda    schedule 18.06.2015
comment
@samgak Итак, что мне сделать, чтобы преобразовать этот код в 32-битный? Что я должен сделать, чтобы иметь возможность использовать printf в 32-битном режиме?   -  person Linda    schedule 18.06.2015
comment
Вот вопрос, содержащий 32-битный код для вычисления чисел Фибоначчи. Вы можете использовать его как ссылку.   -  person samgak    schedule 18.06.2015
comment
@samgak снова имеет эту ошибку: инструкция не поддерживается в 32-битном режиме   -  person Linda    schedule 18.06.2015
comment
@samgak - Код не имеет внутренней разрядности. Однако, конечно, нельзя использовать инструкции (или регистры), которые существуют только в 64-битной ISA, при компиляции для 32-битной архитектуры, и любая логика, явно предполагающая определенную разрядность, сломается. Но это, кажется, не применимо здесь, поскольку я считаю, что все используемые инструкции являются допустимыми операциями x86, и ничто не требует явной 64-битной архитектуры.   -  person aroth    schedule 18.06.2015
comment
@Linda - Этот вопрос, кажется, подразумевает, что Nasm может расстроиться, если он видит push e[?]x или pop e[?]x, когда ожидает использования 64-битного набора инструкций. Так что, возможно, перепроверьте параметры и/или версию Nasm?   -  person aroth    schedule 18.06.2015
comment
@ Линда Правильно, вы хотите устранить ошибку сегментации. И в процессе попытки решить это вам нужна была помощь. Поэтому вам нужно задать нам вопрос, ответ на который вам поможет. Но ты этого не сделал. Вы начали анализировать дамп ядра? Вы знаете, как это сделать? Вы знаете, какой инструмент использовать? Вы знаете, как его использовать? Вы забыли задать вопрос. Вы рассказали историю, а затем просто остановились.   -  person David Schwartz    schedule 18.06.2015
comment
Вы передаете аргументы для printf 64-битным способом (mov edi, format). В 32-битном режиме аргументы передаются в стеке, а не в регистрах. В 64-битном режиме вы не можете использовать 32-битные регистры (push eax). Предложение: оставайтесь в 32-битном режиме, соответствующим образом измените вызов printf и скомпилируйте с помощью gcc -m32 ....   -  person rkhb    schedule 18.06.2015


Ответы (1)


This is too easy a question for all this fuss. You've found a 64-bit tutorial, and converting it to 32-bit is not as simple as changing rax to eax. Here's how you call printf in 32-bit code.

 print:
    ; We need to call printf, but we are using rax, rbx, and rcx.  printf
    ; may destroy rax and rcx so we will save these before the call and
    ; restore them afterwards.

; comment does not match code!

    push    eax                     ; caller-save register
    push    ecx                     ; caller-save register

    push eax ; (current number)
    push format             ; set 1st parameter (format)
    call    printf                ; printf(format, current_number)
    add esp, 4 * 2 ; "remove" 2 parameters - 4 bytes each

    pop     ecx                     ; restore caller-save register
    pop     eax                     ; restore caller-save register
; etc...

Это не проверено. Только с 32-битами я не думаю, что вы получите полные 90 чисел. Возможно, вам придется изменить строку format. Вы можете получить 64-битный результат с 32-битным кодом, используя два регистра, но у вас нет кода для этого...

person Frank Kotler    schedule 18.06.2015