【问题标题】:Printf causes Segment faultPrintf 导致段错误
【发布时间】:2015-09-03 12:01:58
【问题描述】:

我正在尝试在 linux ubuntu 32 位中编译汇编代码。 但是当我用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 tutorial site 复制而来。它用于打印斐波那契数。

【问题讨论】:

  • 你忘了问问题。你需要什么帮助?你开始分析核心转储了吗?
  • @DavidSchwartz printf 导致分段错误。我需要帮助来解决这个问题。
  • 该代码适用于 64 位 Linux,但您正在为 32 位编译和运行它
  • @samgak 以 32 位编译它会导致此错误:“64 位模式不支持指令。”它是用于推送、弹出的行
  • 您以 64 位方式 (mov edi, format) 传递 printf 的参数。在 32 位模式下,参数在堆栈中传递,而不是在寄存器中。在 64 位模式下,您无法推送 32 位寄存器 (push eax)。建议:保持 32 位模式,相应更改对 printf 的调用并使用gcc -m32 ... 编译。

标签: assembly printf nasm ubuntu-13.04


【解决方案1】:

对于所有这些大惊小怪的问题来说,这个问题太简单了。找到了64位的教程,把它转成32位可不是把rax改成eax那么简单。以下是在 32 位代码中调用 printf 的方法。

 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 字符串。您可以通过使用两个寄存器获得 32 位代码的 64 位结果,但是您没有用于该代码的代码...

【讨论】:

    猜你喜欢
    • 2016-01-07
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 2021-01-27
    • 2016-02-02
    相关资源
    最近更新 更多