Я работаю с проприетарным MCU, в котором есть встроенная библиотека в металле (маска ROM). Я использую компилятор clang, который использует встроенный ASM, подобный GCC. Проблема, с которой я сталкиваюсь, - это вызов библиотеки, поскольку у библиотеки нет согласованного соглашения о вызовах. Хотя я нашел решение, я обнаружил, что в некоторых случаях компилятор выполняет оптимизацию, которая регистрируется clobber непосредственно перед вызовом, я думаю, что что-то не так с тем, как я делаю что-то. Вот код, который я использую:
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 содержит вызов функции, но в противном случае адрес возврата, скорее всего, будет затерт. В любом случае я не смог найти способ сделать это.
static __inline__ ...
в заголовке, то gcc обычно никогда не создает ее (и всегда вставляет код на сайте вызова). - person FrankH.   schedule 04.01.2013asm()
(на самом деле ничего, но компилятор просто оставляет это в покое) завершается, и затем вы выполняете свой фанк-вызов. Если вы хотите сделать какое-то странное соглашение о вызовах, вы должны сделать это сами внутриasm()
- person vonbrand   schedule 23.01.2013