【问题标题】:Can someone help me understand stmdb, ldmia, and how I can go about implementing this C++ code in arm assembly language?有人可以帮我理解 stmdb、ldmia 以及如何用 arm 汇编语言实现这个 C++ 代码吗?
【发布时间】:2014-04-13 17:10:13
【问题描述】:

所以我有这段代码,其中 N 是两个数组的大小。

int i;

for (i = 0; i < N; i++)
{
    if (listA[i] < listB[i])
    {
        listA[i] = listB[i];
    }
}

我正在尝试将其实现为 ARM 汇编子例程,但我完全不知道如何处理数组。到目前为止我有这个:

sort1:
    stmdb    sp!, {v1-v5, lr}
    ldmia    sp!, {v1-v5, pc}

我假设我必须使用 cmp 来比较这些值,但我什至不确定要使用哪些寄存器。有人有什么指导吗?

编辑:

好的,我现在有了这个代码:

sort1:
    stmdb    sp!, {v1-v5, lr}     @ Copy registers to stack
    ldr      v1, [a1], #0         @ Load a1
    str      v1, [a2], #0         @ Copy elements of a1 to a2 
    ldmia    sp!, {v1-v5, pc}     @ Copy stack back into registers

这会复制一个 10 元素数组的前四个元素,所以我假设如果我将“#0”更改为“#4”,它会导致接下来的四个元素发生变化,但事实并非如此。为什么?

【问题讨论】:

标签: c++ assembly arm


【解决方案1】:

首先,正如您所展示的,加载/存储多条指令主要用于堆栈操作(尽管它们也可以产生高效的memcpy)。简而言之,它们从base addressbase address + (number of registers * 4) 的连续内存块中按顺序加载/存储指定的寄存器。

在给定的示例中,stmdb sp!, {v1-v5, lr} 在“递减之前”寻址模式下存储 6 个寄存器1,因此有效基地址为sp-24 - 它将存储@987654328 的内容@@sp-24v2sp-20,...直到lrsp-4。由于存在用于基址寄存器写回的! 语法,因此它将从sp 中减去24,使其指向v1 的存储值。 ldmia 是完全相反的——“Increment After”表示有效基地址为sp,因此它将加载从spsp+20 的寄存器,然后将24 加到sp。请注意,它将堆叠的 lr 值直接加载到 pc 中 - 这样您就可以恢复寄存器并在单个指令中执行函数返回。


对于常规的加载/存储指令,它们有 3 种寻址模式 - 偏移、预索引和后索引。 ldr v1, [a1], #0 是后索引的,意思是“从a1 中的地址加载v1,然后将0 添加到a1”,因此将#0 更改为#4 不会影响使用的地址 ,只有之后写回基址寄存器的值。如果你在那儿实现了循环,效果就会变得清晰可见。

考虑一些示例 C 表达式如何映射到这些寻址模式可能会有所帮助:

int a;       // r0
int *b;      // r1

a = b[1];    // ldr r0, [r1, #4]   (offset)
a = *(b+1);  // similarly

a = *(++b);  // ldr r0, [r1, #4]!  (pre-indexed)

a = *(b++);  // ldr r0, [r1], #4   (post-indexed)

请记住,偏移值也可以是寄存器而不是立即数,因此有几种可能的方法来实现给定的循环。

对于权威参考,我建议通读 ARM Architecture Reference Manual 的说明部分,或者对于不太详尽但更易于理解的介绍,Cortex-A Series Programmer's Guide


[1] 这意味着降序堆栈 - 存在相应的“递减之后”和“递增之前”寻址模式用于运行递增堆栈。

【讨论】:

  • 很棒的评论。非常感谢!
  • 更准确的说,stmdb/ldmia对应一个full降序栈,而stmda/ldmib对应一个empty降序栈。完整的升序堆栈需要 stmib / ldmda 指令。
猜你喜欢
  • 2021-02-12
  • 2021-12-24
  • 2021-10-15
  • 1970-01-01
  • 2017-09-23
  • 2015-07-14
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
相关资源
最近更新 更多