【问题标题】:Segmentation fault: 11 With Array Assignment in Loop Using x86 GNU GAS Assembly分段错误:11 使用 x86 GNU GAS 程序集在循环中分配数组
【发布时间】:2018-07-10 18:21:40
【问题描述】:

这个问题与我在here 发布的另一个问题相似。我正在尝试在c/c++ 中编写以下程序集版本:

int x[10];
for (int i = 0; i < 10; i++){
 x[i] = i;
}

本质上,创建一个数组来存储值 1 到 9。

我当前的逻辑是创建一个循环到10 的标签(调用自身直到达到结束值)。在标签中,我已将更新数组的指令放置在当前迭代索引处。但是,使用gcc filename.s 编译并使用./a.out 运行后,错误Segmentation fault: 11 会打印到控制台。我的代码如下:

.data
  x:.fill 10, 4
  index:.int 0
  end:.int 10

.text
.globl _main
_main:
  pushq %rbp
  movq %rsp, %rbp
  subq $16, %rsp
  jmp outer_loop
  leave
  ret

outer_loop:
 movl index(%rip), %eax;
 cmpl end(%rip), %eax
 jge end_loop
 lea x(%rip), %rdi;
 mov index(%rip), %rsi;
 movl index(%rip), %eax;
 movl %eax, (%rdi, %rsi, 4)
 incl index(%rip)
 jmp outer_loop
 leave
 ret

end_loop:
  leave
  ret

奇怪的是下面的代码

lea x(%rip), %rdi;
mov index(%rip), %rsi;
movl index(%rip), %eax;
movl %eax, (%rdi, %rsi, 4)

仅当它不在重复调用的标签中时才有效。有谁知道我如何在不引发Segmentation fault: 11 的情况下循环实现上面的代码?我在 MacOS 上使用 x86 程序集,使用 GNU GAS 语法编译 gcc。

请注意,这个问题不是 this 问题的重复,因为使用了不同的汇编语法并且问题的范围不同。

【问题讨论】:

  • 我有一个愚蠢的问题......为什么不直接编译/查看程序集而不是自己编写呢?
  • @IlanKeshet 这是可能的,但是,我只是出于教育目的自己编写代码。
  • @IlanKeshet : 有些人喜欢做无用的东西来取乐——包括我自己。
  • 局部变量自然映射到寄存器,而不是静态存储。通过使代码膨胀以将本地人保存在命名的静态存储位置而不是寄存器中,您使自己的生活变得困难。如果您确实需要存储/重新加载它们(例如,您可以将本地地址传递给另一个函数),请像编译器一样在堆栈上执行。您的 asm 就像编译器为 static volatile int i = 0; 所做的一样。 (volatile 因为编译器仍会通过将其保存在寄存器中进行优化,除非您为使用 GDB 进行一致调试而反优化,因为 debug-info 不适用于 regs)
  • @PeterCordes 我不知道使用堆栈来存储变量。如果可能,x86gnu 中是否有示例?谢谢。

标签: gcc assembly x86 gnu gnu-assembler


【解决方案1】:

您正在使用 64 位指令访问 32 位内存区域:

mov index(%rip), %rsi;

这导致%rsi 被分配从index 开始并以end 结束的内存内容(我假设没有对齐,尽管我不记得GAS 的规则)。因此,%rsi 实际上被分配了值0xa00000000(假设循环的第一次迭代),并且执行以下movl %eax, (%rdi, %rsi, 4) 会导致 CPU 尝试访问您的进程未映射的地址。

解决办法是去掉赋值,把后面的行替换为movl index(%rip), %esi。 32 位操作保证总是清除 64 位寄存器的高位,因此您可以安全地在地址计算中使用%rsi,因为它将包含当前索引,仅此而已。

您的调试器会告诉您这一点,所以请下次使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    相关资源
    最近更新 更多