使用全局 C 变量的 IAR 内联汇编
IAR inline assembly using global C variable
我正在为 ARM 6.50.4 功能安全版本 6.50 使用 IAR Embedded Workbench
而且我似乎无法使汇编内联指令正常工作。
对于背景:
我正在尝试使用 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
既然汇编指令在他们自己的工作中,我执行内联汇编指令的方式肯定有问题,但我看不出有什么问题。
由于 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
中特别需要它,你可以使用一个寄存器变量。
"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 列表中声明它可能是一个坏主意...
我正在为 ARM 6.50.4 功能安全版本 6.50 使用 IAR Embedded Workbench 而且我似乎无法使汇编内联指令正常工作。
对于背景: 我正在尝试使用 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
既然汇编指令在他们自己的工作中,我执行内联汇编指令的方式肯定有问题,但我看不出有什么问题。
由于 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
中特别需要它,你可以使用一个寄存器变量。
"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 列表中声明它可能是一个坏主意...