我试图在一些以前存在的ARM汇编代码中找到一个异常。有问题的行是:
ldr x0, [x21, x19, lsl #3]
上面公式的结果是x0
具有无效的内存地址,后续代码尝试使用该地址。
我知道lsl
正在执行左移3,但我不确定它实际上是在执行移位。我以前从没见过移位左边的值。移位通常是指要移位的值、移位的距离和方向。如果上面的行同时使用x21和x19,那么它们在移位中是如何使用的?是否其中一个寄存器是低32位,另一个是高32位?x19
当前为0x0x21
当前是大于0x0的值
我不能改变上面的行,但我可以改变x19和x21的值。任何帮助解释这将不胜感激。
我已经通过汇编代码跟踪,找到了所有寄存器的值,并在互联网上搜索如何解码有问题的行
1条答案
按热度按时间ars1skjm1#
如何解释装配方程右侧的内存引用?
不知道你说的装配方程是什么意思,所以不清楚它的右边是什么。
如果指令要存储(这涉及到在C中位于
=
的左侧,如在a[i]=v
中),则寻址模式将在汇编中的相同位置,如在str x0, [x21, x19, lsl #3]
中。如果问题是关于第二个寄存器
x19
,这是一个索引,它被移位,而基址x21
没有移位。我认为使用术语addressing mode而不是汇编方程会有更好的搜索结果。例如,参见here。
64-位ARM具有几种索引寻址模式。
在
ldr x0, [x21, x19, lsl #3]
中,寻址模式的第一个寄存器x21
预期保存64位指针。寻址模式下的第二个寄存器x19
保存索引。这里它是一个64位索引,在与第一个寄存器的(未缩放)值相加之前,它也通过lsl #3
缩放8,以形成最终的内存访问地址。该指令的最简单用法如下:
所以
a
的类型是array of或pointer to long int(64位)。C语言会自动将i
缩放8,所以当我们用C编写它时,我们看不到这一点,尽管机器代码必须这样做。在
v=a[i]
中,数组的基址a
在x21
中,索引i
在x19
中,而v
是x0
。除此之外,处理器还可以将索引寄存器视为有符号或无符号的32位int而不是long,这对于选择
int
为32位的C代码很好。