我正在尝试追查一些先前存在的 ARM 汇编代码中的异常。有问题的行是:
ldr x0, [x21, x19, lsl #3]
上式的结果是x0
具有无效的内存地址,后续代码会尝试使用该地址。
我知道它lsl
正在执行左移 3,但我不确定它实际上在执行什么操作。我以前没有见过移位左侧的值。转移通常是指要转移的值、转移的距离以及转移的方向。如果上面的行同时使用 x21 和 x19,它们在班次中如何使用?寄存器之一是低32位,另一个是高32位吗?
x19
当前为 0x0
x21
当前为大于 0x0 的值
我无法更改上面的行,但我可以更改 x19 和 x21 的值。任何解释这一点的帮助将不胜感激。
我追踪了汇编代码,找到了所有寄存器的值,并在互联网上搜索了如何解码有问题的行
不确定装配方程是什么意思,所以不清楚它的右侧是什么。
如果指令要存储(这涉及到位于 C 的左侧
=
,如 中a[i]=v
),则寻址模式将位于汇编中的相同位置,如 中str x0, [x21, x19, lsl #3]
。如果问题是关于第二个寄存器 ,
x19
那么它是一个索引,它被移位,而基数x21
则没有。我认为使用术语“寻址模式”而不是“汇编方程”会获得更好的搜索结果。例如,请参见此处。
64位ARM有多种索引寻址模式。
在 中
ldr x0, [x21, x19, lsl #3]
,寻址模式的第一个寄存器x21
预计保存一个 64 位指针。寻址模式中的第二个寄存器x19
保存索引。lsl #3
这里它是一个 64 位索引,并且在添加到第一个寄存器的(未缩放的)值之前,还通过 缩放了 8,以形成最终的内存访问地址。该指令最简单的用法如下:
所以 的类型
a
是 long int 数组或指针(64 位)。C语言会自动缩放i
8,所以当我们用C编写它时,我们看不到这一点,尽管机器代码必须这样做。其中
v=a[i]
,数组的基地址a
是 inx21
,索引i
是 inx19
,而v
isx0
。除此之外,处理器还可以将索引寄存器视为有符号或无符号的 32 位 int,而不是 long,这对于选择
int
32 位的 C 代码来说是有好处的。