我正在查看小型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 回答
看来你是对的 .
我找不到一个明确的来源,而且Electrical Engineering的人们也不能找到它 .
我们得到的最接近的是来自AVR ISA manual的
sei
指令的声明:现在,正如EE网站中所提出的那样,这可能是
sei
指令本身的一个特征,或者它可能是架构本身的一个特征2 .如果您查看操作码
sei
实际上只是bset 7
但是bset
页面中没有关于待处理中断的注释,尽管bset 7
就像sei
一样 .所以我相信无论何时使用
out
或sei
,在SREG中设置I位都会屏蔽中断一条指令 .有关链接问题的更多信息:AVR sei instruction 3 .
1链接的问题与您的相同,它包含的实际答案不像这个假的答案 .
2即它不计算你如何改变
SREG
.3重新连结 .