IAR内联汇编使用全局C变量

时间:2015-02-27 09:30:30

标签: c assembly arm inline iar

我使用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

由于装配说明是他们自己的工作,我在进行内联汇编指令的方式上有问题,但我看不出有什么问题。

2 个答案:

答案 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中特别需要它,则可以使用寄存器变量。