【问题标题】:Segmentation fault (core dumped) error in AT&T assembly codeAT&T 汇编代码中的分段错误(核心转储)错误
【发布时间】:2014-01-20 10:59:34
【问题描述】:

我用汇编语言编写了一个简单的程序,试图在我的 64 位 Ubuntu 操作系统上运行它。但是,它因“Segmentation fault (core dumped) error”而失败。

这是我的代码:

    .section .data
    values :
        .int 10, 15, 20, 25, 30 ,35, 40, 45, 50, 55, 60
    output :
        .asciz "The value is %d\n"
   .section .text
   .globl main
   main :
        nop
        movl $0, %edi
   loop :
        movl values( , %edi, 4), %eax
        pushq %rax
        pushq $output
        call printf
        addl $8, %esp
        inc %edi
        cmpl $11, %edi
        jne loop
        movl $0, %ebx
        movl $1, %eax
        int $0x80

【问题讨论】:

  • 我认为您的大部分e__ 寄存器应该是r__。看起来这是作为 x86 程序集编写的,并且没有进行所有必要的更改就被强制移植到 x64。
  • 我试过了,还是不行。
  • 组装成64位?那么堆栈不是 DWORD 而是 QWORD 对齐的,所以你向 rsp 添加 8 是错误的,应该在你的 printf 调用之后向 rsp 添加 16
  • 你是对的,这里有一个错误。谢谢。

标签: assembly


【解决方案1】:

您的代码中存在多个问题。

64bit Ubuntupushq %rax 我推断您正在尝试制作 64 位可执行文件。

如果是这样的话,那么……

这里:

pushq %rax
pushq $output
call printf
addl $8, %esp

您在函数调用后没有正确平衡堆栈。你还记得这是 64 位代码吗?您需要添加到rsp,而不是esp。另外,如果你 push 2 个 8 字节的参数,你必须准确地删除 2 个 8 字节的参数,这意味着你必须添加 16 个,而不是 8 个。

但情况比这更糟。在 64 位模式下,参数的传递方式不同。第一个参数在寄存器rdirsirdxrcxr8r9 中。所以,这给了我们:

movq %rax, %rsi
movq $output, %rdi
movq $0, %rax ; number of vector registers used for var-arg-function printf()
call printf

这里:

inc %edi

您刚刚通过调用破坏了rdi 的值,并使用此寄存器进行参数传递。您需要在通话前手动推送rdi,然后将其弹回。或者您可以将其保存在全局变量中。如果您选择 push 和 pop,请确保堆栈指针 rsp 在任何 call 指令之前始终是 16 字节对齐的。

这里:

movl $0, %ebx
movl $1, %eax
int $0x80

您正在使用 32 位系统调用接口。在 64 位程序中必须使用 64 位系统调用接口:

movq $60, %rax ; sys_exit
movq $0, rdi ; return 0 (success)
syscall

现在,我觉得这个也可能有问题:

movl $0, %edi
loop :
movl values( , %edi, 4), %eax

一般来说,您不应该在 64 位代码的地址计算中使用 32 位寄存器和 32 位指令。我将其更改为:

movl $0, %rdi
loop :
movl values( , %rdi, 4), %eax

如果两者都不起作用,因为values 的地址距离rip 超过 2GB(事实:在 64 位模式下的大多数指令和大多数指令中,位移仅限于内存操作数中的 32 位有符号整数)其中在 64 位模式下也没有仅位移内存操作数编码,它们在那里使用 rip-相对寻址),您将需要手动添加 values 的 64 位地址并将数组中的索引相乘由 4. 确保执行 64 位加法,过程中没有任何截断。

必读:

  • System V 应用程序二进制接口 AMD64 架构处理器补充草案版本 0.99.6

  • 不同 C++ 编译器和操作系统的调用约定 作者:Agner Fog

【讨论】:

  • 你真好。非常感谢。我在看PROFESSIONAL ASSEMBLY LANGUAGE这本书,它的代码示例都是在32位操作系统上编写的,所以当我在我的64位操作系统上测试它们时遇到了很多问题。再次感谢您!
猜你喜欢
  • 2022-10-13
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多