【问题标题】:GCC error message for ARM inline assembly: ARM register expectedARM 内联汇编的 GCC 错误消息:预期 ARM 寄存器
【发布时间】:2012-07-27 22:01:59
【问题描述】:

下面是我用 C 和内联汇编编写的一段代码,用于将数组 blk 中的一些 short 值加载到 ARM R 寄存器中。

...
short *blk; 
... //blk memory allocation and initialization
short tmp0, tmp1, tmp2;
asm volatile (
"ldrh %[tmp0], [%0]\n\t"
"ldrh %[tmp1], [%1]\n\t"
"ldrh %[tmp2], [%2]\n\t"
: [tmp0] "=r" (tmp0), [tmp1] "=r" (tmp1), [tmp2] "=r" (tmp2)
: "m" (blk[0])  , "m" (blk[8]), "m" (blk[8*2])
: 
);

我从 arm gcc 4.6 收到此错误消息

/tmp/ccDEBLCN.s:266: Error: ARM register expected -- `ldrh r3,[[r5,#0]]'

GCC 抱怨 ldrh %[tmp2], [%2] 行,但我不明白为什么。我查看了LDRH 指令,在我看来我的指令模板是正确的。

Load memory halfword [15:0] from register address + 5-bit immediate offset
LDRH <Rd>, [<Rn>, #<immed_5> * 2]

顺便说一句,这是我用来编译它的命令:

arm-none-linux-gnueabi-gcc -O2 -march=armv7-a -mthumb 

【问题讨论】:

  • 您是否尝试将“=r”更改为“r”?这是我正在使用的语法。
  • 它应该是 "=r" 因为tmp 是输出的。无论如何,如果我将其更改为“r”,我会收到此错误。193:3: error: output operand constraint lacks '=' 193:3: error: invalid lvalue in asm output 0
  • 对此有什么想法吗?我一直无法找到解决此问题的方法。
  • 如果代码只是您所显示的,那么编译器只是在抱怨您正在将数据加载到寄存器中而不是使用它。 ARM 不支持内存到内存的操作,所以你需要将数据 LDR 到寄存器中,然后将数据 STR 回内存。
  • 不,我已经从代码中删除了许多细节。但我不明白你的评论。您从哪条消息中得出的结论是我没有使用数据?无论如何,即使我没有使用数据,它也应该是一个警告,显然我没有从编译器收到任何警告消息。另外,为什么说我在做 mem to mem 操作? LDR 清楚地从一个地址(此处为blk,“m”表示允许内存操作数,具有机器支持的任何类型的地址)加载到寄存器(此处为tmp,“r”表示 ARM 内核寄存器)。最后,在这段代码中,我不存储任何数据。对不起,我没有得到你。

标签: c gcc arm inline-assembly


【解决方案1】:
asm (
"ldrh %[tmp0], %[ref0]\n\t"
"ldrh %[tmp1], %[ref1]\n\t"
"ldrh %[tmp2], %[ref2]\n\t"
: [tmp0] "=&r" (tmp0), [tmp1] "=&r" (tmp1), [tmp2] "=r" (tmp2)
: [ref0] "m" (blk[0])  , [ref1] "m" (blk[8]), [ref2] "m" (blk[8*2])
: 
);

【讨论】:

    【解决方案2】:

    看起来编译器可能会抱怨您的代码实际上没有做任何事情。这真的是你的本意吗?

    ...
    short *blk; 
    ... //blk memory allocation and initialization
    short tmp0, tmp1, tmp2;
    asm volatile (
    "ldrh r0,[%[BLK]]\n\t"
    "ldrh r1,[%[BLK], #8]\n\t"
    "ldrh r2,[%[BLK], #16]\n\t"
    "strh r0,[%tmp0] \n\t"
    "strh r1,[%tmp1] \n\t"
    "strh r2,[%tmp2] \n\t"
    : [tmp0] "r" (tmp0), [tmp1] "r" (tmp1), [tmp2] "r" (tmp2), [BLK] "r" (blk)
    : "r0", "r1", "r2"
    : 
    );
    

    【讨论】:

    • 是的,有点。您使用 ro, r1, r2 作为临时寄存器。但我试图从内存(这里是 blk 数组)直接加载到 tmp0、tmp1 和 tmp2(tmp0、tmp1 和 tmp2 本身存储在 r 寄存器中)。这里给出的另一个答案是直接加载到 tmp 变量中。不过感谢您的帮助。
    • 让我重新表述我的意思。我的意思是从内存(此处为 blk)加载到核心寄存器(此处为 R 寄存器),我想在我的 C 代码中将这些寄存器称为 tmp0、tmp1、tmp2 变量。
    • 我一直认为 GCC 会做错事,而我通常是对的。我认为您对 GCC 的要求太多,无法尝试将寄存器分配给内联 asm 中的局部变量并使其正常工作。内联 asm 是一种特殊情况(例如 kludge),而 GCC 似乎并没有平等地对待它周围的 C 代码。根据我的经验,您需要让 asm 代码完成所有需要完成的工作,并假设它与 C 代码不同,唯一的例外是您可以读取 C 变量,但编译器认为您仍然不是访问这些变量,除非 C 也使用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多