有人可以帮我理解stmdb,ldmia,以及如何用arm汇编语言实现这个C ++代码?

时间:2014-04-13 17:10:13

标签: c++ assembly arm

所以我有这段代码,其中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个元素数组的前四个元素,所以我会假设我改变了#34;#0&#34;到&#34;#4&#34;,它会导致接下来的四个元素发生变化,但它并没有。为什么?

1 个答案:

答案 0 :(得分:16)

首先,正如您所演示的那样,加载/存储多个指令主要用于堆栈操作(尽管它们也可以生成高效的memcpy)。简单地说,它们按顺序从/ {加载/存储从base addressbase address + (number of registers * 4)的连续内存块。

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


对于常规加载/存储指令,它们有3种寻址模式 - 偏移,预索引和后索引。 sp已被后索引,意味着从lr中的地址“加载pc,然后将0添加到ldr v1, [a1], #0”,从而将v1更改为{{1 }}不会影响地址 used ,只会将值写回基址寄存器。如果你已经实现了循环那么效果就会变得清晰可见。

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

a1

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

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


[1]这意味着下降的堆栈 - 对应的“递减后”和“递增前”寻址模式存在以运行升序堆栈。