AVR汇编编程:栈上的原子分配

Avr assembly programming: atomic allocation on the stack

我正在查看 avr-gcc 汇编为小型 C 程序生成的代码。下面应该在堆栈上分配一个 100 字节的本地数组。

extern void foo(char [], int);

void bar()
{
  char t[100];
  foo(t,100);
}

当然可以,方法是从堆栈指针中减去 100。

我了解到,由于avr是8位机器,更改16位堆栈指针需要2个步骤(更改SPH和SPL)。此外,通过禁用中断来提供一些原子性是个好主意。它是由序列

完成的
in r28,__SP_L__
in r29,__SP_H__           ; get SP
subi r28,100              ; new SP in R29:R28 = OLD -100 
sbc r29,__zero_reg__
in __tmp_reg__,__SREG__   ; save status to r0
cli                       ; disable interrupts
out __SP_H__,r29          ; update SPH
out __SREG__,__tmp_reg__  ; restore status   -- why here ?
out __SP_L__,r28          ; update SPL

我还不确定恢复状态指令的位置。

为什么更新 SPL 后没有完成?

也许可以保证在(重新)启用中断后,在下一条指令完成之前不会考虑中断?

看来你是对的。
我找不到确切的来源,Electrical Engineering 的人显然也找不到1

我们得到的最接近的是 AVR ISA manualsei 指令的声明:

Sets the Global Interrupt Flag (I) in SREG (Status Register). The instruction following SEI will be executed before any pending interrupts.

现在,正如 EE 站点中所质疑的那样,这可能是 sei 指令本身的一个特性,或者它可能是体系结构本身的一个特性 2

如果您查看操作码 sei 实际上只是 bset 7,但是 bset 页面中没有关于未决中断的注释,尽管 bset 7 表现得像sei.
所以我相信在 SREG 中设置 I-bit 将屏蔽中断以获取更多指令,无论何时使用 outsei

有关链接问题的更多信息:AVR sei instruction3


1链接的问题与你的相同,它包含真实的答案,而不是这个假的。
2 即它不计算你如何改变 SREG.
3 已重新链接。