【发布时间】: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