我正在使用具有内置金属库(掩模 ROM)的专有 MCU。我使用的编译器是 clang,它使用类似 GCC 的内联 ASM。我遇到的问题是调用库,因为库没有一致的调用约定。虽然我找到了一个解决方案,但我发现在某些情况下,编译器会在调用之前立即对寄存器进行优化,我认为我做事的方式有问题。这是我正在使用的代码:
int EchoByte()
{
register int asmHex __asm__ ("R1") = Hex;
asm volatile("//Assert Input to R1 for MASKROM_EchoByte"
:
:"r"(asmHex)
:"%R1");
((volatile void (*)(void))(MASKROM_EchoByte))(); //MASKROM_EchoByte is a 16-bit integer with the memory location of the function
}
现在这有一个明显的问题,虽然变量“asmHex”被断言为寄存器 R1,但实际调用不使用它,因此编译器“不知道”R1 在调用时被保留。我使用以下代码来消除这种情况:
int EchoByte()
{
register int asmHex __asm__ ("R1") = Hex;
asm volatile("//Assert Input to R1 for MASKROM_EchoByte"
:
:"r"(asmHex)
:"%R1");
((volatile void (*)(void))(MASKROM_EchoByte))();
asm volatile("//Assert Input to R1 for MASKROM_EchoByte"
:
:"r"(asmHex)
:"%R1");
}
这对我来说似乎真的很难看,应该有更好的方法。另外我担心编译器可能会在两者之间做一些废话,因为调用本身没有表明它需要 asmHex 变量。不幸的是, ((volatile void (*)(int))(MASKROM_EchoByte))(asmHex) 不起作用,因为它将遵循 C 约定,将参数放入 R2+ (R1 保留用于刮擦)
请注意,不幸的是,更改 Mask ROM 库是不可能的,并且有太多常用例程无法在 C/C++ 中重新创建它们。
干杯,谢谢。
编辑:我应该注意,虽然我可以在 ASM 块中调用该函数,但编译器对无调用函数进行了优化,并且通过在汇编中调用它看起来好像没有调用。如果有某种方式表明内联 ASM 包含函数调用,我可以走这条路线,但否则返回地址可能会被破坏。在任何情况下,我都无法找到一种方法来做到这一点。