Felix Rabe
Felix Rabe

Reputation: 48

x86 Assembly segmentation fault

I can compile it but when I run it I get "segmentation fault".
Would love if someone explained why.

.section .data
digitformatstr: 
.string "%d\n"

.section .text
.global main

main:
    push    $1337
    pop     %eax
    movl    %eax, -4(%ebp)
    push    -4(%ebp)
    push    $digitformatstr
    call    printf
    addl    $8, %esp

Upvotes: 0

Views: 383

Answers (1)

Michael Petch
Michael Petch

Reputation: 47563

You appear to be using GNU assembler and GCC's C Library to build your executable. The primary problem with your code is that you don't set up register %ebp before using it. Typically with C your function sets up the local stack frame first which includes initializing %ebp. To properly set up the local stack frame, and cleanup the stack before returning you could use code like this:

.section .data
digitformatstr:
.string "%d\n"

.section .text
.global main

main:
    push    %ebp           /* setup local stack frame */
    mov     %esp, %ebp

    push    $1337
    pop     %eax
    movl    %eax, -4(%ebp)
    push    -4(%ebp)
    push    $digitformatstr
    call    printf
    addl    $8, %esp

    leave                  /* remove local stack frame */
    ret

A beginner's guide to the stack frame and 32-bit C calling convention can be found here.

One other comment about your code. You do:

    push    $1337
    pop     %eax
    movl    %eax, -4(%ebp)
    push    -4(%ebp)
    push    $digitformatstr
    call    printf

I'm not sure what you were trying to do with this code. It almost appears you were trying to place 1337 on the stack as a local variable (but space hasn't been allocated on the stack for local variables). Since it appears you are trying to simply call printf where the second argument is an integer, you should just push that value (1337) on the stack. All the code above should simply be:

    push    $1337               /* 2nd argument to printf */
    push    $digitformatstr     /* 1st argument to printf */
    call    printf              /* call printf

The final cleaned up code for main could look something like:

main:
    push    %ebp            /* setup local stack frame */
    mov     %esp, %ebp

    push    $1337           /* 2nd argument to printf */
    push    $digitformatstr /* 1st argument to printf */
    call    printf          /* call printf
    addl    $8, %esp        /* cleanup the 2 32 bit arguments */
                            /* we pushed on the stack */

    leave                   /* remove local stack frame */
    ret

Upvotes: 2

Related Questions