在 GNU 的C++代码中使用 C 标头。包括内联装配的错误:'asm'中不可能的约束

Using C headers in C++ code in GNU. Error including inline assembly: impossible constraint in 'asm'

本文关键字:错误 约束 asm 不可能 包括内 代码 C++ GNU 标头      更新时间:2023-10-16

我有一个奇怪的。我正在开发一个嵌入式系统,使用供应商的头文件。我正在使用GCC 4.6.3编译文件。我想用c++写我的代码,我有错误,我不知道。我正在运行一个供应商示例程序,我所做的只是将main.c文件的名称更改为main.cpp。因此,我认为,头文件是由c++编译器解释的。其中一个包含以下行:

__attribute__((naked)) static return_type signature 
  { 
     __asm( 
         "svc %0n" 
         "bx r14" : : "I" (number) : "r0" 
     ); 
}

如果文件名为main.c,则文件可以正确编译,我认为这是因为该文件正在由C编译器处理。如果我使用c++,得到的错误是

error: impossible constraint in 'asm'

但是,我对C编译器没有问题。我需要调用在c++文件中使用此定义的函数。我考虑过编写留在c端并链接到它们的包装器函数,但这将是一个真正的痛苦,而且效率较低。有什么建议吗?

svc也称为swi,是ARM/Thumb软件中断指令。它只接受常量,但它们与其他寄存器常量不同。也就是mov r0, #4096。如果希望指定一个即时对象,则需要使用预处理器和令牌粘贴。number不能是变量寄存器

#define syscall(number) __attribute__((naked)) static return_type signature 
  { 
     __asm( 
         "svc " #number "n" 
         "bx r14" : : : "r0" 
     ); 
  }

注意: #'C'预处理器的字符串化。还要注意的是,查看SVC号是低效的,因为它在I-CACHE中,检查需要D-CACHE。一般来说,它总是constant,而函数数字被传递到寄存器中,以便更快地进行系统调用。

gcc手册说,

'I'-可作为数据的直接操作数的整数处理指令。即取值范围为0的整数以2的倍数旋转到255

这是典型的数据处理操作数——immediate, ARM的A5.1.3节。SVC操作数在拇指模式下是固定的8位,在ARM模式下是固定的24位。这可能与其他一些约束,我不知道,但至少预处理器的字符串化将工作,只要一个数字常量传递给宏。

我想这是幸运的,这工作从gcc和不幸的g++没有。您可以通过使用-S并使用这两个工具查看(并发布)输出来获得更深入的了解。

编辑:您的代码似乎与gcc-4.7.2一起工作,但numberconst int本地在我的情况下,number的使用可能是问题。也许它有一个微妙的语义变化,从'C'到' c++ '。

查看GCC手册(内联汇编器)以了解您的机器的约束的确切含义。老版本的GCC在检查约束条件方面非常草率,也许您正在被这个问题咬伤。奇怪的是,gccg++(相同的版本?)处理代码的方式不同,它只是可能是一个编译器错误,但我认为只有在所有其他解释已经用尽之后。