c - 内联 C 汇编破坏了它自己的变量

标签 c assembly arm inline-assembly cortex-m

我想使用内联汇编将两个内存位置读入 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/

相关文章:

arm - DPDK转发测试时出现大量 "dTLB-load-misses"

assembly - 如何在ARMv8中ERET到相同的异常级别?

c - 如何检查某个函数是否可以被另一个特定函数间接调用?

将通用指针转换为 int 指针以进行优化

algorithm - 汇编程序第一遍和第二遍的教程

c - 如何在没有 Glibc 的情况下在 C 中使用内联汇编获取参数值?

c - 使用函数调用循环比空循环更快

visual-studio-2008 - 了解 Arm Assembler 分支偏移计算

c++ - 有哪些简单的 zlib 教程?

c - 如何在 defconfig 中包含 c#ifdef 变量