gpt4 book ai didi

assembly - AT&T 汇编代码中的段错误(核心转储)错误

转载 作者:行者123 更新时间:2023-12-04 05:39:15 25 4
gpt4 key购买 nike

我用汇编语言编写了一个简单的程序,试图在我的 64 位 Ubuntu 操作系统上运行它。但是,它因“段错误(核心转储)错误”而失败。

这是我的代码:

    .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

最佳答案

您的代码中有多个问题。

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

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

这里:

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

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

但它甚至比这更糟糕。在 64 位模式下,参数的传递方式不同。第一个参数在寄存器 rdi 中。 , rsi , rdx , rcx , r8r9 .所以,这给了我们:
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 位系统调用接口(interface)。在 64 位程序中,您必须使用 64 位系统调用接口(interface):
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 应用程序二进制接口(interface) AMD64 架构处理器补充草案版本 0.99.6
  • 不同 C++ 编译器和操作系统的调用约定 作者:Agner Fog
  • 关于assembly - AT&T 汇编代码中的段错误(核心转储)错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11480777/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com