DecTimers ; Декаем таймеры
GetNextProc ; Берем следующуий процесс
STS ADDRL, ZL ; Сейвим адрес в ADDRx
STS ADDRH, ZH
loadRegs ; Грузим регистры
STS ZLT, ZL ; сохраняем Z, лишний раз не грузим стек
STS ZHT, ZH
LDS ZL, ADDRL ; ADDRx в Z
LDS ZH, ADDRH
PUSH ZL ; Пишем в стек адрес возврата
PUSH ZH
LDS ZL, ZLT ; и респим регистры Z
LDS ZH, ZHT
STS R16T,R16 ; сейвим R16
LDS R16, SREGT ; восстанавливаем SREG. ДАЛЕЕ НИКАКОЙ
МАТЕМАТИКИ!!!
OUT SREG, R16 ; а то испортим
OUTI TCNT0, 0 ; Обнуляем таймер
OUTI TIFR, 1 ; и его флаг прерывания
LDS R16, R16T ; вернем многостарадальный R16
RETI ; Валим нафиг
Первое, что я делаю — достаю из стека адрес возврата и сохраняю в
переменные. Зачем? А затем, что после некоторых манипуляций стек
переключится на другой процесс, а там будут уже совершенно другие
данные. Сохранится он потом в ProcTable. Сейчас ВРОДЕ БЫ код написан
так, что это не обязательно. Однако так надежнее, и, если что, проще
дописать новые возможности.
Далее пресловутое сохранение регистров, адреса, пересчет таймеров, переход
к следующей процедуре в очереди (доставание ее адреса), загрузка регистров
нового процесса. Под конец пишем в стек НОВЫЙ адрес возврата, для
другого процесса, и RETI прыгает туда.
Обрати внимание, что восстановление SREG из переменной идет в самом
конце диспетчера. Иначе при первой же математической операции (будь то
Add, Sub или даже INC) испортятся флаги. А я этого не хочу. Также в конце