使用全局C变量的IAR内联程序集

时间:2022-12-12 03:13:09

I'm using IAR Embedded Workbench for ARM 6.50.4 Functional Safety Version 6.50 and I can't seem to get an assembly inline instruction working.

我正在为ARM 6.50.4功能性安全版本6.50使用IAR嵌入式工作台,而且我似乎无法让一个装配式的内联指令工作。

For the background: I'm trying to implement a context switch on an ARM7TDMI using the PIT Interrupt. When saving the current context I have to get the address of the stack of the interrupted function, which is saved inside a global C variable, which is declared in the same c file:

背景:我正在尝试使用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
}

From what I could gather from the EWARM_DevelopmentGuide.ENU.pdf the instruction above should be using the correct syntax. Also I have tried different ways of formating the instruction but all I get is:

从EWARM_DevelopmentGuide.ENU中收集的数据。上面的说明应该使用正确的语法。我也尝试了不同的方式来规范教学,但我所得到的是:

Error[og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error".

错误[og006]:内联汇编中的语法错误:“错误[401]:操作和语法错误”。

Now when I export the complete context saving assembly routine into a seperate .s file and call the function from c the following instruction is working just fine. LDR R0, =ptTask_CurrentTask

现在,当我将完整的上下文保存程序集导出到一个独立的.s文件并从c调用函数时,下面的指令可以正常工作。异地恋R0,= ptTask_CurrentTask

Since the assembly instructions on their own work, there has to be a problem with the way I'm doing the inline assembly instruction but I can't see what is wrong.

由于汇编指令在他们自己的工作上,我做内联汇编指令的方式有问题,但我看不出有什么问题。

2 个解决方案

#1


2  

The "r" constraint indicates a general-purpose register, so it ends up emitting LDR R0, Rx which is indeed invalid syntax. If you really want to do the actual pointer dereference in the assembly code, either embed the correct syntax directly:

“r”约束表示一个通用寄存器,因此它最终发出LDR R0, Rx实际上是无效的语法。如果您真的想在程序集代码中执行实际的指针删除引用,可以直接嵌入正确的语法:

__asm volatile( "LDR R0, [%0]\n\t" ::"r"(ptTask_CurrentTask));

Or, better, use the appropriate constraint to indicate that it is a memory operand (pointer) and leave the syntax to the compiler:

或者,最好使用适当的约束来表示它是一个内存操作数(指针),并将语法留给编译器:

__asm volatile( "LDR R0, %0\n\t" ::"m"(ptTask_CurrentTask));

Or waste an extra instruction and let the compiler worry about the load:

或者浪费额外的指令,让编译器担心负载:

__asm volatile( "MOV R0, %0\n\t" ::"r"(*ptTask_CurrentTask));

Whichever way, touching r0 directly without declaring it on the clobber list is probably a bad idea...

不管怎样,直接触摸r0而不将其声明在clobber列表中可能是一个坏主意……

#2


0  

The compiler is already loading the value into a register for you due to the r constraint, you don't need to do the LDR yourself. %0 references a register which already contains the value of ptTask_CurrentTask. You can check using -S option or disassembling that indeed the compiler does the load for you:

由于r约束,编译器已经将值加载到寄存器中,您不需要自己执行LDR。%0引用已经包含ptTask_CurrentTask值的寄存器。你可以使用-S选项检查或分解编译器确实为你做了负载:

__asm volatile( ""  ::"r"(ptTask_CurrentTask));

Becomes:

就变成:

    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

In this case the compiler picked r3. If you specifically need it in r0, you can use a register variable.

在这种情况下,编译器选择r3。如果在r0中特别需要它,可以使用寄存器变量。

#1


2  

The "r" constraint indicates a general-purpose register, so it ends up emitting LDR R0, Rx which is indeed invalid syntax. If you really want to do the actual pointer dereference in the assembly code, either embed the correct syntax directly:

“r”约束表示一个通用寄存器,因此它最终发出LDR R0, Rx实际上是无效的语法。如果您真的想在程序集代码中执行实际的指针删除引用,可以直接嵌入正确的语法:

__asm volatile( "LDR R0, [%0]\n\t" ::"r"(ptTask_CurrentTask));

Or, better, use the appropriate constraint to indicate that it is a memory operand (pointer) and leave the syntax to the compiler:

或者,最好使用适当的约束来表示它是一个内存操作数(指针),并将语法留给编译器:

__asm volatile( "LDR R0, %0\n\t" ::"m"(ptTask_CurrentTask));

Or waste an extra instruction and let the compiler worry about the load:

或者浪费额外的指令,让编译器担心负载:

__asm volatile( "MOV R0, %0\n\t" ::"r"(*ptTask_CurrentTask));

Whichever way, touching r0 directly without declaring it on the clobber list is probably a bad idea...

不管怎样,直接触摸r0而不将其声明在clobber列表中可能是一个坏主意……

#2


0  

The compiler is already loading the value into a register for you due to the r constraint, you don't need to do the LDR yourself. %0 references a register which already contains the value of ptTask_CurrentTask. You can check using -S option or disassembling that indeed the compiler does the load for you:

由于r约束,编译器已经将值加载到寄存器中,您不需要自己执行LDR。%0引用已经包含ptTask_CurrentTask值的寄存器。你可以使用-S选项检查或分解编译器确实为你做了负载:

__asm volatile( ""  ::"r"(ptTask_CurrentTask));

Becomes:

就变成:

    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

In this case the compiler picked r3. If you specifically need it in r0, you can use a register variable.

在这种情况下,编译器选择r3。如果在r0中特别需要它,可以使用寄存器变量。