assembly 如何解释装配方程右侧的内存引用?

shyt4zoc  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(81)

我试图在一些以前存在的ARM汇编代码中找到一个异常。有问题的行是:

ldr     x0, [x21, x19, lsl #3]

上面公式的结果是x0具有无效的内存地址,后续代码尝试使用该地址。
我知道lsl正在执行左移3,但我不确定它实际上是在执行移位。我以前从没见过移位左边的值。移位通常是指要移位的值、移位的距离和方向。如果上面的行同时使用x21和x19,那么它们在移位中是如何使用的?是否其中一个寄存器是低32位,另一个是高32位?
x19当前为0x0
x21当前是大于0x0的值
我不能改变上面的行,但我可以改变x19和x21的值。任何帮助解释这将不胜感激。
我已经通过汇编代码跟踪,找到了所有寄存器的值,并在互联网上搜索如何解码有问题的行

ars1skjm

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,以形成最终的内存访问地址。
该指令的最简单用法如下:

long a[];        // perhaps as parameter, alternately, long *a;
long i;          // some indexing variable
long v = a[i];   // accessing some element at index i of array a

所以a的类型是array of或pointer to long int(64位)。C语言会自动将i缩放8,所以当我们用C编写它时,我们看不到这一点,尽管机器代码必须这样做。
v=a[i]中,数组的基址ax21中,索引ix19中,而vx0
除此之外,处理器还可以将索引寄存器视为有符号或无符号的32位int而不是long,这对于选择int为32位的C代码很好。

相关问题