Mic*_*aud 0 assembly avr interrupt
我正在查看avr-gcc小型C程序的程序集生成代码.以下应该在堆栈上分配一个100字节的本地数组.
extern void foo(char [], int);
void bar()
{
char t[100];
foo(t,100);
}
Run Code Online (Sandbox Code Playgroud)
当然它通过从堆栈指针中减去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
Run Code Online (Sandbox Code Playgroud)
我还不相信恢复状态指令的位置.
为什么在更新SPL后没有完成?
也许保证在(重新)启用中断后,在下一条指令完成之前不会将中断记入账户?
看来你是对的.
我无法找到一个明确的来源,也都不可以这样的家伙在电气工程显然是1.
我们得到的最接近的是AVR ISA手册中关于该sei指令的声明:
设置SREG(状态寄存器)中的全局中断标志(I).SEI之后的指令将在任何挂起中断之前执行.
现在,正如EE网站中所提出的那样,这可能是sei指令本身的一个特征,也可能是架构本身的一个特征2.
如果你看一下操作码sei实际上只是bset 7但是没有关于挂起中断的注释bset,尽管bset 7表现得像sei.
因此,我相信无论何时使用或,在SREG中设置I位都会屏蔽中断一条指令. outsei
有关链接问题的更多信息:AVR sei指令3.
1链接的问题与您的相同,它包含的实际答案不像这个假的答案.
2即它不计算你如何改变SREG.
3重新连结.