Legv8 中是否有使用另一个寄存器而不是立即偏移量的 LOAD 或 STORE?

Is there a LOAD or STORE in Legv8 that uses another register instead of a immediate offset?

Legv8中是否有不使用立即数偏移量的加载或存储指令?我在底部问题中没有 i 的值,当我使用 LDUR 或 STUR 时,我无法抵消数据 [i]。我使用了 ARMv8 的 STR 和 LDR。还有其他方法可以回答这个问题吗?

Convert the following C program into LEGv8 assembly program. Assume variables k, x, y and i are associated with registers X19, X20, X21, and X22 respectively. The base address of array data[] is in register X25. Each element of array data[] occupies 8 bytes.

if ( x > y )  
     k = x – y;  
else  
    k = y – x;  
while (data[i] < k) {  
    data[i] = data[i] + k;  
    i = i + 1;  

这是我写的。

IF:  
    SUBS X23, X20, X21 // CHECK IF X> Y  
B.LT ELSE // IF LESS THAN, BRANCH TO ELSE  
    SUB X19, X20, X21 // STORE K = X-Y  
B.LOOP  
ELSE:   
    SUB X19, X21, X20 // STORE K= Y-X;  
LOOP:  
    LDR X24, [X25, X22] // load into X24, base address from X24 with offset from X22  
    SUBS X18, X24, X19 // CHECK IF data[i] < k  
    B.GT EXIT  
    ADD X24, X24, X19 // data[i] += k  
STR X24, [X25, X22] // store into X25 with offset from X22, the value from X24  
    ADDI X22, X22, #1 // I += 1  
    B.LOOP  
EXIT:  

str/ldr是可以使用多种寻址方式的普通指令

ldur/stur 仅在立即数不是 4 或 8 的倍数时对寄存器 + 常量偏移有用。

具有该寻址模式的 ldr 的正常形式将其编码为缩放值,因此它可以使用更广泛的偏移量。 U 表示 "unscaled"。 (但这是一个 encoding 细节:asm 源代码仍然总是有一个字节偏移量,如 ldr w0, [x0, 4] 以加载下一个 intx0.Godbolt).但正如我所说,ldr/str 可以使用任何寻址模式。

你说得对 ldur 对于 data[i] 没有用 运行 时间变量 i.

Is there another way i could have answered this question?

是的,当然有很多方法可以安排你的循环。例如使用指针增量而不是 2 寄存器寻址模式,在循环外计算 data+i

或者将您的计数器增加 8 作为字节偏移量,而不是每次使用时都需要缩放的数组索引。 (我想你忘了这一点,除非 LEGv8 不同于 AArch64)。

或者优化掉 i 并只计算一个终点指针来进行比较。

甚至可以使用 AdvSIMD(NEON 的 AArch64 版本)SIMD 指令进行矢量化以一次执行 2 次加法。

你也可以用底部的条件分支来构造循环,这总是好的(循环内的指令更少)。即使这意味着你需要一个 compare/branch 来跳过循环,如果它应该 运行 零次。

但所有这些方式都只使用ldr/str,而不是ldur/stur。作为寻址模式的一部分,您不需要偏移量,只需 2 个寄存器。