我想使用内联汇编将两个内存位置读入C变量,然后将两个C变量存储到其他内存位置。我编写的内联代码如下所示:
unsigned int us32 = (uint32_t)us;
__asm__ __volatile__("ldr %1, [%4, #0x10]\r\n" //read my 2 memory locations
"ldr %0, [%4, #0x18]\r\n"
"str %2, [%4, #0x14]\r\n" //write my 3 memory locations
"str %2, [%4, #0x18]\r\n"
"str %3, [%4, #0x10]\r\n"
: "=l" (leftover_time), "=l" (rollflag)
: "l" (us32), "l" (ena), "l" (s)
: "memory", "cc");
但是,从我的内联代码生成的程序集似乎不起作用。它将我想要存储的变量加载到r2和r3中,然后使用我尝试加载的变量迅速破坏它们。从下面的反汇编中可以清楚地看到这一点,我使用arm-none-eabi-objdump
us32 = (uint32_t)us;
c8e: 6bbb ldr r3, [r7, #56] ; 0x38
c90: 637b str r3, [r7, #52] ; 0x34
__asm__ __volatile__("ldr %1, [%4, #0x10]\r\n"
;;; These 4 instructions load the variables I want to write to memory
;;; into r2 and r3
c92: 2207 movs r2, #7
c94: 4b39 ldr r3, [pc, #228] ; (d7c <reschedule+0x16c>)
c96: 6819 ldr r1, [r3, #0]
c98: 6b7b ldr r3, [r7, #52] ; 0x34
;;; BOOM!! r2 and r3 have been clobbered, they no longer contain the
;;; values that I want to write (a constant #7 and unsigned in us32).
;;;
;;; The data that I want to read is indeed pointed by r1 + 16 and r1 + 24
c9a: 690b ldr r3, [r1, #16]
c9c: 698a ldr r2, [r1, #24]
c9e: 614b str r3, [r1, #20]
ca0: 618b str r3, [r1, #24]
ca2: 610a str r2, [r1, #16]
ca4: 633a str r2, [r7, #48] ; 0x30
ca6: 62fb str r3, [r7, #44] ; 0x2c
我已经阅读了几个小时不同的内联汇编教程,我已经检查过&amp;仔细检查了我的输入/输出限制,我只是坐在这里挠挠脑袋。有人能抓住我的错误吗?
我使用的是arm-none-eabi-gcc
版本4.8.4
答案 0 :(得分:3)
相关段落隐藏在the extended asm documentation:
的中间对所有不能与输入重叠的输出操作数使用
&
约束修饰符(请参阅Modifiers)。否则,GCC可以将输出操作数分配到同一寄存器中作为无关输入操作数,前提是汇编代码在产生输出之前消耗其输入。如果汇编代码实际上包含多个指令,则此假设可能为假。
如果您在装载之前有商店,那么您实际上会满足这个假设,一切都会好的。既然你没有,那么你需要将输出标记为早期操作数,即"=&l"
。
答案 1 :(得分:2)
您在使用输入之前已经破坏了???
和list [] = [[]]
list (x:xs) = [(x,c) : ys | ys <- list xs, c <- [C,I,U] ]
,而您忘记通知编译器。你需要一个r2
早期修补符修饰符:
在所有输出操作数上使用'&amp;'约束修饰符(请参阅修饰符) 不得与输入重叠。否则,GCC可能会分配输出 操作数与同一寄存器中的无关输入操作数相同 假设汇编代码之前消耗了它的输入 产出产出。如果汇编代码,这个假设可能是错误的 实际上由多个指令组成。