0

I am trying to compile an assembly code in linux ubuntu 32-bit. But when I compile it with nasm -felf32 assembly.asm && gcc assembly.o && ./a.out I face with Segmentation fault (core dumped). I understood that the problem is with printf.

I have searched a lot on the internet, there were several questions like this. But none of the answers worked for me.

    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

*** source code is copied from Nasm tutorial site. It is for printing Fibonacci numbers.

rkhb
  • 14,159
  • 7
  • 32
  • 60
Linda
  • 251
  • 1
  • 6
  • 16
  • 2
    You forgot to ask a question. What help do you need? Have you started analyzing the core dump? – David Schwartz Jun 18 '15 at 02:10
  • @DavidSchwartz printf causes segmentation fault. I want help to solve that. – Linda Jun 18 '15 at 02:12
  • 1
    The code is intended for 64 bit Linux but you are compiling and running it for 32-bit – samgak Jun 18 '15 at 02:12
  • @samgak compiling it in 32 bit causes this error:" instruction not supported in 64-bit mode." it is for lines of push, pop – Linda Jun 18 '15 at 02:14
  • @MattMcNabb it is a code to print first 90 numbers of Fibonacci – Linda Jun 18 '15 at 02:15
  • @samgak so, what should I do to convert this code for 32 bit? What should I do to be able to use printf in 32 bit mode? – Linda Jun 18 '15 at 02:17
  • Here is a [question](http://stackoverflow.com/questions/13892518/converting-32-bit-fibonacci-nasm-code-to-64-bit) that contains 32-bit code for computing Fibonacci numbrs. You can use it as a reference. – samgak Jun 18 '15 at 02:20
  • @samgak again it has this error: instruction not supported in 32-bit mode – Linda Jun 18 '15 at 02:29
  • @samgak - Code doesn't have an intrinsic bit-depth. However, of course one cannot use instructions (or registers) that only exist in a 64-bit ISA when compiling for a 32-bit architecture, and any logic which explicitly assumes a particular bit-depth will break. But that doesn't seem to apply here, as I believe all of the instructions used are valid x86 operations and nothing appears to explicitly require a 64-bit architecture. – aroth Jun 18 '15 at 03:53
  • @Linda - [This question](http://stackoverflow.com/questions/24126597/push-pop-segmentation-fault-at-assembly-x86) seems to imply that Nasm can get upset if it sees a `push e[?]x` or `pop e[?]x` when it's expecting a 64-bit instruction-set to be used. So perhaps double-check your Nasm options and/or version? – aroth Jun 18 '15 at 04:00
  • @Linda Right, you want to solve the segmentation fault. And in the process of trying to solve that, you needed some help. So you need to ask us a question whose answer will help you. But you didn't do that. Have you started analyzing the core dump? Do you know how to do that? Do you know what tool use? Do you know how to use it? You forgot to actually ask a question. You told a story and then just stopped. – David Schwartz Jun 18 '15 at 04:08
  • 1
    You pass the arguments for `printf` in 64-bit manner (`mov edi, format`). In 32-bit mode the arguments are passed on the stack, not in registers. In 64-bit mode you cannot push 32-bit registers (`push eax`). Suggestion: stay in 32-bit mode, change the call to printf accordingly and compile with `gcc -m32 ...`. – rkhb Jun 18 '15 at 06:31

1 Answers1

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...

That's untested. With only 32-bits, I don't think you'll get the full 90 numbers. You may need to alter your format string. You can get a 64-bit result with 32-bit code by using two registers, but you don't have code for that...

Frank Kotler
  • 3,079
  • 2
  • 14
  • 9