Не надо делать все сразу! Тем более, не понимая откуда какие проблемы возникают. Итак, по порядку:
1. LD (QUIT+1),SP: QUIT LD SP,0
Не надо писать программы, в которых SP на выходе не равен SP на входе!!! Если есть разбаланс стека, это серьезный баг, иногда очень трудноуловимый! Оставьте SP в покое - если он у вас в программе портится, путь лучше выход в из нее в BASIC (скорее всего, печальный) это покажет после очередного изменения программы, приведшего к разбалансу стека.
2. Если в программе есть DI, на выходе в BASIC должен быть EI, иначе остаемся без кнопок в BASIC'е. Зачем принудительно включать прерывания, если их не выключали?
3. Не понятно зачем при каждом выходе устанавливать IM1. Если Вы его меняли, то сами знаете, когда надо его вернуть обратно. Если нет - либо больше некому его менять, либо тот, кто поменял, знает зачем это сделал, когда надо вернуть обратно, и расстроится, если вы сами принудительно это сделаете когда оно не ожидает такой подставы. Кстати, IM 1 правильно возвращать так: DI: LD A,#3F: LD I,A: IM 1: EI.
4. LD IY,23610 - эта инструкция стоит в ПЗУ сразу после возврата из подпрограммы пользователя. На выходе этого делать не надо. Ограничение на использование IY состоит в том, что в обработчике прерывания IM 1 есть инструкция INC (IY + 40), увеличивающая старший байт переменной FRAMES. И, если Вы не запретили прерывания, переписав IY, то при переполнении младших байт FRAMES у Вас в программе что-то увеличится без вашей на то воли. Регистр IY можно использовать свободно только если прерывания запрещены или если установлен режим IM 2, но стандартная процедура обработки прерываний не зовется когда в IY Ваше значение.
5. А вот по поводу 10072 в HL' - это правда, без этого значения там хужает калькулятору, который "досчитывает" функцию USR после возврата из Вашей подпрограммы. Это значение точно портится, если вы зовете подпрограммы, реализующие команды Бэйсика DRAW, CIRCLE, ну, или портите его сами.