x86 程序集分段错误

Posted

技术标签:

【中文标题】x86 程序集分段错误【英文标题】:x86 Assembly segmentation fault 【发布时间】:2015-11-03 16:28:12 【问题描述】:

我可以编译它,但是当我运行它时,我得到“分段错误”。 如果有人解释原因会很高兴。

.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

【问题讨论】:

您使用ebp 作为指针,但我没有看到您初始化ebp 以指向任何地方的有效地址。 我会在哪里做呢? :/ 我感到困惑 @FelixRabe 你想让%ebp指向什么? 【参考方案1】:

您似乎正在使用 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

【讨论】:

工作得很好!你在代码完成后我得到分段错误:o 它打印正确,一切正常。 在底部添加了呼叫退出,现在它似乎工作了,再次感谢:)! 上面的代码应该与leaveret 一起工作,而不需要调用exit,除非你构建的程序与我预期的不同。如果您在问题中添加了用于编译和链接的命令,我可能会给您一个更好的答案。 @FelixRabe 我实际上并没有仔细查看您编写的所有代码。我已经修复了另一个可能导致问题的错误(这是您尝试将 1337 传递给 printf 的方式)。

以上是关于x86 程序集分段错误的主要内容,如果未能解决你的问题,请参考以下文章

大会 x86 上的推送/弹出分段错误

总线错误:Mac OS X 上带有 GCC 的内联 x86 程序集

错误 C2403 使用内联 x86 C++ 程序集将寄存器内容移动到变量

程序集 x86:如何计算 32 位长整数中的设置位数

操作数必须是可重定位的程序集 x86 问题

在“任何 CPU”.NET 程序集上强制 x86 CLR