【发布时间】:2023-03-15 04:00:02
【问题描述】:
我正在将一个小型学术操作系统从 TriCore 移植到 ARM Cortex(Thumb-2 指令集)。为了让调度器工作,我有时需要直接跳转到另一个函数而不修改堆栈或链接寄存器。
在 TriCore(或者更确切地说,在 tricore-g++)上,这个包装模板(适用于任何三参数函数)有效:
template< class A1, class A2, class A3 >
inline void __attribute__((always_inline))
JUMP3( void (*func)( A1, A2, A3), A1 a1, A2 a2, A3 a3 ) {
typedef void (* __attribute__((interrupt_handler)) Jump3)( A1, A2, A3);
( (Jump3)func )( a1, a2, a3 );
}
//example for using the template:
JUMP3( superDispatch, this, me, next );
这将生成汇编程序指令J(又名 JUMP)而不是 CALL,在跳转到(否则正常)C++ 函数 superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to) 时,堆栈和 CSA 保持不变。
现在我需要在 ARM Cortex(或者更确切地说,对于 arm-none-linux-gnueabi-g++)上的等效行为,即生成 B(又名 BRANCH)指令而不是 BLX(又名带有链接的 BRANCH和交换)。但是 arm-g++ 没有 interrupt_handler 属性,我找不到任何等效属性。
于是我尝试求助asm volatile,直接写asm代码:
template< class A1, class A2, class A3 >
inline void __attribute__((always_inline))
JUMP3( void (*func)( A1, A2, A3), A1 a1, A2 a2, A3 a3 ) {
asm volatile (
"mov.w r0, %1;"
"mov.w r1, %2;"
"mov.w r2, %3;"
"b %0;"
:
: "r"(func), "r"(a1), "r"(a2), "r"(a3)
: "r0", "r1", "r2"
);
}
到目前为止,至少在我的理论中,一切都很好。 Thumb-2 需要在寄存器中传递函数参数,在这种情况下是 r0..r2,所以它应该可以工作。
但随后链接器死了
undefined reference to `r6'
在 asm 语句的右括号中......我不知道该怎么做。好吧,我不是 C++ 方面的专家,而且 asm 语法也不是很简单……所以有人给我提示吗?提示 arm-g++ 的正确 __attribute__ 是一种方法,修复 asm 代码的提示是另一种方法。另一种方法可能是在输入 asm 语句时告诉编译器 a1..a3 应该已经在寄存器 r0..r2 中(我调查了一下,但没有找到任何提示)。
【问题讨论】:
-
a1、a2、a3 是指针吗?尝试将它们转换为
(void*) -
ARM 中断处理程序的属性是
interrupt。见gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -
@Mike:不,该属性仍会生成
BLX指令... -
@osgx:它们不一定是指针......
-
您可以像这样将变量声明在特定的寄存器中:
register int reg0 asm("r0") = a1;。 gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
标签: c++ assembly systems-programming