内联C程序集破坏了它自己的变量(Inline C assembly clobbers its own variables)

编程入门 行业动态 更新时间:2024-10-24 20:12:18
内联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

我已经阅读了几个小时不同的内联汇编教程,我检查并仔细检查了我的输入/输出约束,我只是坐在这里挠挠脑袋。 有人能抓住我的错误吗?

我正在使用arm-none-eabi-gcc版本4.8.4

I want to use inline assembly to read two memory locations into C variables and then store two C variables to other memory locations. The inline code that I have written looks like this:

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");

The assembly that is generated from my inline code, however, doesn't seem to work. It loads the variables that I want to store into r2 and r3 and then promptly clobbers them with the variables I am trying to load. This is pretty clear from the disassembly below, which I got using 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

I've read different inline assembly tutorials for hours and I've checked & double-checked my input/output constraints and I'm just sitting here scratching my head. Can someone catch my mistake?

I am using arm-none-eabi-gcc version 4.8.4

最满意答案

相关段落隐藏在扩展的asm文档的中间:

对所有不能与输入重叠的输出操作数使用& constraint修饰符(请参阅修饰符 )。 否则,GCC可以将输出操作数分配到同一寄存器中作为不相关的输入操作数,前提是汇编代码在产生输出之前消耗其输入。 如果汇编代码实际上包含多个指令,则此假设可能为假。

如果您在装载之前有商店,那么您实际上会满足这个假设,一切都会好的。 既然你没有,那么你需要将输出标记为earlyclobber操作数,即"=&l" 。

The relevant paragraph is hidden right in the middle of 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.

If you had the stores before the loads, you would actually meet that assumption and everything would be fine. Since you don't, then you need to mark the outputs as earlyclobber operands, i.e. "=&l".

更多推荐

本文发布于:2023-08-06 06:34:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1446648.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自己的   内联   变量   程序   破坏了

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!