我使用IAR Embedded Workbench for ARM 6.50.4功能安全版6.50 而且我似乎无法让汇编内联指令正常工作。
背景: 我尝试使用PIT中断在ARM7TDMI上实现上下文切换。 保存当前上下文时,我必须获取被中断函数的堆栈的地址,该函数被保存在一个全局C变量中,该变量在同一个c文件中声明:
unsigned int* ptTask_CurrentTask;
__irq void SysIrqHandler( void )
{
// ... saving registers
__asm volatile( "LDR R0, %0\n\t" ::"r"(ptTask_CurrentTask) );
//... save the new top of stack
//select new task and restore associated registers
}
根据我从EWARM_DevelopmentGuide.ENU.pdf收集的内容,上面的说明应使用正确的语法。 我也尝试了不同的方法来形成指令,但我得到的只是:
Error[og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error"
。
现在,当我将完整的上下文保存程序集例程导出到单独的.s文件中并从c调用该函数时,以下指令工作正常。
LDR R0, =ptTask_CurrentTask
由于装配说明是他们自己的工作,我在进行内联汇编指令的方式上有问题,但我看不出有什么问题。
答案 0 :(得分:2)
“r”约束表示通用寄存器,因此它最终会发出LDR R0, Rx
,这确实是无效的语法。如果你真的想在汇编代码中进行实际的指针取消引用,可以直接嵌入正确的语法:
__asm volatile( "LDR R0, [%0]\n\t" ::"r"(ptTask_CurrentTask));
或者,更好的是,使用适当的约束来指示它是内存操作数(指针)并将语法留给编译器:
__asm volatile( "LDR R0, %0\n\t" ::"m"(ptTask_CurrentTask));
或浪费额外的指令让编译器担心负载:
__asm volatile( "MOV R0, %0\n\t" ::"r"(*ptTask_CurrentTask));
无论哪种方式,直接触摸r0
而不在clobber列表中声明它可能是一个坏主意......
答案 1 :(得分:0)
由于r
约束,编译器已经将值加载到寄存器中,您不需要自己执行LDR
。 %0
引用已包含值ptTask_CurrentTask
的寄存器。您可以使用-S
选项进行检查,或者反汇编确实编译器会为您负载:
__asm volatile( "" ::"r"(ptTask_CurrentTask));
变为:
ldr r3, .L3 # these two are generated by the compiler
ldr r3, [r3, #0] # for loading the operand
... # here comes your asm code
.L3:
.word ptTask_CurrentTask
在这种情况下,编译器选择了r3
。如果您在r0
中特别需要它,则可以使用寄存器变量。