x86程序集分段错误

时间:2015-11-03 16:28:13

标签: assembly

我可以编译它,但是当我运行它时,我得到“分段错误” 如果有人解释为什么会爱。

.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

1 个答案:

答案 0 :(得分:2)

您似乎正在使用GNU汇编程序和GCC的C库来构建可执行文件。代码的主要问题是在使用之前不要设置寄存器%ebp 。通常使用C,您的函数首先设置本地堆栈帧,其中包括初始化%ebp 。要正确设置本地堆栈帧,并在返回之前清理堆栈,可以使用如下代码:

.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

可以找到初学者的堆栈框架指南和32位C调用约定here

关于您的代码的另一条评论。你这样做:

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

我不确定您是否尝试使用此代码。几乎看起来你试图将1337放在堆栈上作为局部变量(但是没有在堆栈上为局部变量分配空间)。因为看起来你试图简单地调用printf,其中第二个参数是一个整数,你应该只是在堆栈上推送该值(1337)。上面的所有代码应该只是:

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

main的最终清理代码可能如下所示:

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