对于存储和加载,您可以这样做:
ldr r0,[r1],#4
str r0,[r2],#4
无论您在末尾放置什么,在本例中为 4,都会在寄存器用于地址之后但在指令完成之前添加到基址寄存器(ldr 示例中的 r1 和 str 示例中的 r2),它非常类似于
unsigned int a,*b,*c;
...
a = *b++;
*c++ = a;
编辑,您需要查看反汇编以查看发生了什么(如果有)。我正在使用最新的代码源,或者现在只是来自导师图形工具链的精简版源。
arm-none-linux-gnueabi-gcc(Sourcery CodeBench Lite 2011.09-70)4.6.1
#include <stdio.h>
int main ()
{
int out[]={0, 0};
asm volatile (
"mov r0, #1 \n\t"
"str r0, [%0], #4 \n\t"
"add r0, r0, #1 \n\t"
"str r0, [%0] \n\t"
:: "r"(out)
: "r0" );
printf("%d %d\n", out[0], out[1]);
return 0;
}
arm-none-linux-gnueabi-gcc str.c -O2 -o str.elf
arm-none-linux-gnueabi-objdump -D str.elf > str.list
00008380 <main>:
8380: e92d4010 push {r4, lr}
8384: e3a04000 mov r4, #0
8388: e24dd008 sub sp, sp, #8
838c: e58d4000 str r4, [sp]
8390: e58d4004 str r4, [sp, #4]
8394: e1a0300d mov r3, sp
8398: e3a00001 mov r0, #1
839c: e4830004 str r0, [r3], #4
83a0: e2800001 add r0, r0, #1
83a4: e5830000 str r0, [r3]
83a8: e59f0014 ldr r0, [pc, #20] ; 83c4 <main+0x44>
83ac: e1a01004 mov r1, r4
83b0: e1a02004 mov r2, r4
83b4: ebffffe5 bl 8350 <_init+0x20>
83b8: e1a00004 mov r0, r4
83bc: e28dd008 add sp, sp, #8
83c0: e8bd8010 pop {r4, pc}
83c4: 0000854c andeq r8, r0, ip, asr #10
so the
sub sp, sp, #8
就是分配两个本地int out[0]和out[1]
mov r4,#0
str r4,[sp]
str r4,[sp,#4]
是因为它们被初始化为零,然后是内联汇编
8398: e3a00001 mov r0, #1
839c: e4830004 str r0, [r3], #4
83a0: e2800001 add r0, r0, #1
83a4: e5830000 str r0, [r3]
然后是 printf:
83a8: e59f0014 ldr r0, [pc, #20] ; 83c4 <main+0x44>
83ac: e1a01004 mov r1, r4
83b0: e1a02004 mov r2, r4
83b4: ebffffe5 bl 8350 <_init+0x20>
现在很清楚为什么它不起作用了。你没有声明为不稳定的。您没有给代码返回 ram 来获取 printf 的 out[0] 和 out[1] 的值,编译器知道 r4 包含 out[0] 和 out[1] 的值,那里该函数中的代码非常少,因此不必逐出 r4 并重用它,因此它使用 r4 作为 printf。
如果你把它改成易失性的
volatile int out[]={0, 0};
然后你应该得到想要的结果:
83a8: e59f0014 ldr r0, [pc, #20] ; 83c4 <main+0x44>
83ac: e59d1000 ldr r1, [sp]
83b0: e59d2004 ldr r2, [sp, #4]
83b4: ebffffe5 bl 8350 <_init+0x20>
printf 的准备工作是从 ram 读取的。