BOB51 писал(а):Подстановку перенаправления выхода через подмену адреса возврата в верхушке стека что-ли содеять хочется?

Так учти особенности адресации памяти у АВРок - там не метка подставляться должна, а метка,смещенная на бит влево с младшим битом = 0.
и сам указатель стека скорректировать для переустановки надо:
для начала сделаем sp=sp+2 согласно имеющемуся МК (скоко там регистро - два или один - допустим POPами тоже можно "гасить")
затем грузим
ldi rn,low(metka*2)
push rn
ldi rn,high(metka*2)
push rn

Если честно, мне кажется, что я толком нифига не понял, что вы сказали. Но рассуждения такие:
sp=sp+2 - это мы передвигаем указатель стека, то есть место, куда будет произведена следующая запись или откуда следующее чтение.
ldi rn,low(metka*2)
push rn
ldi rn,high(metka*2)
push rn
А вот прочитав это, я вспомнил, что ещё в обучалке динамической индикации, в подпрограмме, которая достаёт из матрицы код символа, который надо вывести на индикатор, там тоже адрес матрицы умножался на 2.
Спойлер
Код: Выделить всё
Decoder:
;преобразование двоичного числа
;в код 7-сегментного индикатора
ldi ZL,Low(DcMatrix*2) ;инициализация массива
ldi ZH,High(DcMatrix*2)
ldi Temp2,0 ;прибавление переменной
add ZL,Temp1 ;к 0-му адресу массива
adc ZH,Temp2
lpm ;загрузка значения
mov Temp1,r0
ret
И тут меня посещает некое удивление, т.к. в
статье DI HALT'a адрес на 2 не умножается.
Спойлер
Код: Выделить всё
LDI R17,low(M1)
PUSH R17
LDI R17,High(M1)
PUSH R17
Думаю, щас уберу в подпрограмме с массивом кодов символов умножение адреса на 2 и посмотрю, что будет

Просто хочется это сделать, чтобы увидеть самому.
А моя программа в данный момент имеет следующий принцип и код у неё такой:
1).Работает основной цикл, по нажатию кнопки мы переходим во второстепенный цикл, из которого программа сама вернётся через некоторое время.
2).Внутри второстепенного цикла мы переходим в подпрограмму и делаем то, что в ней написано.
3).Но если нам по UART приходит команда, надо срочно выходить из подпрограммы и идти не туда, откуда мы сюда пришли, а в основной цикл.
А в коде сделано так:
Код: Выделить всё
;Проверяем, пришёл ли байт по UART
LDS UARTTemp, UCSR0A ; Проверить, пришло ли что-нибудь по UART
SBRS UARTTemp,7 ;
rjmp nocom3 ; Не пришло - выходим отсюда
LDS UARTTemp, UDR0 ; Пришло - читаем полученный байт.
;********************************************
SUBI UARTTemp,0x30 ;Это чтобы облегчить общение с Термитом и присланная с компа цифра, на самом деле была этой цифрой в понимании МК.
cpi UARTTemp,7 ;Сравниваем пришедшую команду с тем, что значит срочно выходить обратно в основной цикл.
brne nocom3 ;Если не то, то ничего не делаем, идём дальше.
Pop UARTTemp ;Или забираем из стека адрес возврата, чтобы вернуть SP к тому, что там изначально было положено до вызова подпрограммы.
Pop UARTTemp
jmp actioncommand ; Перепрыгиваем в цикл основной программы.
В этом коде вообще нет ret, но насколько я помню, это просто возврат по адресу, лежащему в 2 последних байтах стека (вернее тех, где находится SP), в отличии от reti, где ещё снимается флаг, а раз мы почистили стек через Pop, то ничего криминального не произошло. Естесственно, если в начале обработки этой подпрограммы в стек не было заPushено что-то ещё (а у меня не было).
И да, я знаю, что есть прерывание по получению байта по UART, но пока что меня устраивает такой вариант проверки прихода команды.