我想使用内联汇编将两个内存位置读入 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
我已经阅读了几个小时不同的内联汇编教程,并且检查并仔细检查了我的输入/输出约束,但我只是坐在这里摸不着头脑。有人能发现我的错误吗?
我正在使用 arm-none-eabi-gcc
版本 4.8.4
最佳答案
相关段落隐藏在 the extended asm documentation 的中间:
Use the
&
constraint modifier (see Modifiers) on all output operands that must not overlap an input. Otherwise, GCC may allocate the output operand in the same register as an unrelated input operand, on the assumption that the assembler code consumes its inputs before producing outputs. This assumption may be false if the assembler code actually consists of more than one instruction.
如果您在加载之前拥有商店,那么您实际上会满足该假设,并且一切都会好起来。既然不这样做,那么您需要将输出标记为 Earlyclobber 操作数,即 "=&l"
。
关于c - 内联 C 汇编破坏了它自己的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37330704/