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 它打印正确,一切正常。 在底部添加了呼叫退出,现在它似乎工作了,再次感谢:)! 上面的代码应该与leave
和ret
一起工作,而不需要调用exit
,除非你构建的程序与我预期的不同。如果您在问题中添加了用于编译和链接的命令,我可能会给您一个更好的答案。
@FelixRabe 我实际上并没有仔细查看您编写的所有代码。我已经修复了另一个可能导致问题的错误(这是您尝试将 1337 传递给 printf 的方式)。以上是关于x86 程序集分段错误的主要内容,如果未能解决你的问题,请参考以下文章
总线错误:Mac OS X 上带有 GCC 的内联 x86 程序集