内联 C 汇编破坏了它自己的变量
Inline C assembly clobbers its own variables
我想使用内联汇编将两个内存位置读入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
我已经阅读了数小时的不同内联汇编教程,并且检查并仔细检查了我的 input/output 约束,但我只是坐在这里挠头。有人能发现我的错误吗?
我正在使用 arm-none-eabi-gcc
版本 4.8.4
您在使用输入之前破坏了 r2
和 r3
,并且您忘记通知编译器。你需要一个 &
early-clobber modifier for them:
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.
相关段落隐藏在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变量存储到其他内存位置。我编写的内联代码如下所示:
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
我已经阅读了数小时的不同内联汇编教程,并且检查并仔细检查了我的 input/output 约束,但我只是坐在这里挠头。有人能发现我的错误吗?
我正在使用 arm-none-eabi-gcc
版本 4.8.4
您在使用输入之前破坏了 r2
和 r3
,并且您忘记通知编译器。你需要一个 &
early-clobber modifier for them:
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.
相关段落隐藏在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"
.