繁体   English   中英

AVR中的内联汇编

[英]inline assembly in avr

void save_context(uint8_t index) {
    context *this_context = contextArray + index;
    uint8_t *this_stack = this_context->stack;


    asm volatile("st %0 r0":  "r"(this_stack));
}

我有这样的东西。

!!! 我想将寄存器r0 r1 r2 ...存储到我的stack []数组中。

我正在编程的是上下文切换。 上下文具有如下结构:

typedef struct context_t {
   uint8_t stack[THREAD_STACK_SIZE];
   void *pstack;
   struct context_t *next;
}context;

我的问题是我无法将c变量“ this_stack”传递给内联程序集。 我的目标是将所有寄存器,堆栈指针和SREG存储在我的堆栈中。

编译后,它给出错误:描述资源路径位置类型

`,' required    5_multitasking      line 754, external location: C:\Users\Jiadong\AppData\Local\Temp\ccDo7xn3.s C/C++ Problem

我查阅了avr内联汇编教程。 但是我并没有得到很多。 有人可以帮我吗?

"label"没有意义,应该是一个约束。 尝试将堆栈指针保存到数组中也没有任何意义。 用该数组的地址加载堆栈指针可能很有意义,但这不是save_context

无论如何,要获取SPL的值(即堆栈指针),您可以执行以下操作:

asm volatile("in %0, %1": "=r" (*this_stack) : "I" (_SFR_IO_ADDR(SPL)));

(有一个q约束,但至少我的gcc版本不喜欢它。)

要获取真实的寄存器,例如r26您可以执行以下操作:

register uint8_t r26_value __asm__("r26");
asm volatile("": "=r" (r26_value));

在GCC手册中记录了一个约束“ m”,但它并不总是适用于AVR。 这是如何从sanguino / bootloaders / atmega644p / ATmegaBOOT运行的示例

asm volatile("...
    ...
    "sts    %0,r16      \n\t"
    ...
    : "=m" (SPMCSR) : ... );

我发现“ m”很脆弱。 如果函数使用C代码中的变量,则在内联汇编之外,编译器可能会选择将其放置在Z寄存器中,并且也会尝试在汇编器中使用Z。 与sts指令一起使用时,这将导致汇编程序错误。 查看C编译器的汇编程序输出是调试此类问题的最佳方法。

无需使用“ m”约束,您只需将所需的文字地址放入汇编代码中即可。 有关示例,请参见pins_teensy.c ,其中timer_0_fract_count不包括在:

asm volatile(
    ...
    "sts    timer0_fract_count, r24"    "\n\t"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM