Avr汇编编程:堆栈上的原子分配

时间:2016-06-16 15:09:41

标签: assembly interrupt avr

我正在查看小型C程序的avr-gcc程序集生成代码。以下应该在堆栈上分配一个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后为什么

也许有保证在(重新)启用中断后,在下一条指令完成之前不会将中断记入账户?

1 个答案:

答案 0 :(得分:5)

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

我们得到的最接近的是来自AVR ISA manual sei指令的声明:

  

设置SREG(状态寄存器)中的全局中断标志(I)。 SEI之后的指令将在任何待处理中断之前执行。

现在,正如EE网站中所提出的那样,这可能是sei指令本身的一个特征,也可能是架构本身 2 的一个特征。

如果您查看操作码sei实际上只是bset 7,但bset页面中没有关于待处理中断的注释,尽管bset 7的行为与{sei相同1}}。
所以我相信,无论何时使用outsei,在 SREG 中设置 I-bit 都会屏蔽中断一条指令。

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

1 链接的问题与您的相同,它包含的实际答案与此假设不同。
2 即它不会计算你如何改变SREG 3 重新连接。