Printf导致Segment故障

时间:2015-06-18 02:05:35

标签: assembly printf nasm ubuntu-13.04

我正在尝试在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复制的。它用于打印斐波那契数字。

1 个答案:

答案 0 :(得分: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...

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