【问题标题】:assembly, segmentation fault组装,分段错误
【发布时间】:2015-10-31 11:36:37
【问题描述】:

这段代码导致分段错误,我不知道为什么会这样, 该代码只是应该将堆栈中 esp 的当前位置传递给 ebp 并且只需在 ebp 上使用间接寻址模式来获取地址的值, 我不知道为什么操作系统会终止导致分段错误

.section .data
.section .text
.globl _start
_start:
movl $50,%edx
pushl, %edx
movl %esp,%ebp
movl (%ebp),%ebx  ## this causes the problem for some reason, 
movl $1,%eax     
int $0x80         ## Program should return an exit status of %ebx value

【问题讨论】:

  • 如果你有C代码,请贴出来。
  • R sahu,嘿,stackoverflow,建议我也应该在 c 部分发布我的帖子,例如,我没有 C 代码。
  • 为我工作。唯一可能发生的问题是您没有正确清理堆栈(有一个 push 没有匹配的 pop),但由于您在此过程中所做的只是发出一个系统调用,这应该没关系。
  • 您在pushl,%edx 中有一个额外的逗号,但我希望这只是复制粘贴错误。此外,我们希望您在 linux 上以 32 位模式运行它。你忘了提供这些重要的细节,以及你用来构建它的命令行。
  • 看,这就是问题所在。您设法将其编译为 64 位代码。不知道如何,因为pushl %edx 甚至没有组装。无论如何,使用as --32 test.s -o test.o; ld -melf_i386 test.o -o test正确创建一个32位版本。

标签: assembly x86


【解决方案1】:

正如 Jester 所说,问题在于 64 位 Linux 工具默认制作 64 位程序。他有一个坏习惯,就是用 cmets 写答案,所以我就在这里复制一下:

as --32 test.s -o test.o; ld -melf_i386 test.o -o test

gcc -m32 foo.s -ffreestanding -nostdlib -o foo

你的段错误

movl (%ebp),%ebx

因为%rsp 的高 32 位不是全零,所以%esp%rsp 是不同的地址。你可以用 gdb 找到这个问题。您会注意到您有 64 位寄存器。有关将 gdb 用于 asm 的信息,请参阅 https://stackoverflow.com/tags/x86/info

我将在这条线上多选一些:

pushl, %edx

_start 除了是语法错误(额外的逗号)之外,不需要保存任何寄存器。 x86-64 ABI says 你应该假设它们都充满了随机垃圾,除了堆栈指针。它还说%rdx 具有您应该向atexit() 注册的函数的地址,但在当前的Linux 上,%rdx 在进程入口处归零。 (命令行参数在堆栈上。)

我认为 x86 32 位进程启动的情况几乎相同。

【讨论】:

  • (更新:当您的 _start 在动态链接的可执行文件中由 ld.so 调用时,RDX 不为零。它是共享库的析构函数的回调函数指针。RDX 和其他 regs 除外RSP 在_start 在Linux 中静态 链接的可执行文件中为0,以避免信息泄漏,但在动态可执行文件中,其他regs 可以保存垃圾。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2013-08-05
相关资源
最近更新 更多