Вот самое оригинальное решение топика :). Алгоритм, естественно, можно модифицировать. Но идею я постараюсь до вас донести, спектрумисты.
Процедура, естественно, релоцируема.
Прерывания можно и не запрещать, если вы уверены в том что не данная процедура не модифицирует код процедуры обработки прерываний и вызываемых ею подпрограмм в неподходящий момент.)
В общем, эта процедура ищет в памяти последовательность #18,#02
и если находит, то обнуляет смещение, и если получается что она модифицировала сама себя, то IX будет указывать на нашу программу и мы его скорректируем с PC, а если модифицировала что-то иное - то тут же восстановит данные и поиск продолжится.
Код:;тут надо бы запомнить режим прерываний, процедуру писать не буду
di
;а можно и не запрещать прерывания по вышеизложенным причинам.
ld ix,#4000 ;начинаем искать в памяти с этого адреса
bad ld a,#18 ;ищем код JR
not_jr cp (ix+0) ;в памяти лежит JR?
inc ix
jr nz,not_jr ;если не JR, поиск далее
ld a,(ix+0) ;иначе берем смещение за JR
cp 2 ;сравниваем с величиной относительного смещения нашего JR
jr nz,bad ;оно не такое как у нас?
ld (ix+0),0 ;если значение такое же, то уничтожаем смещение
DEFB #18 ;вот тут после JR (код #18)
DEFB 2 ;cмещение указывает через ловушку
jr trapped ;<----сюда попадем если обнулили искомое смещение.
ld (ix+0),a ;иначе попадаем сюда. восстанавливаем смещение
jr bad ;и снова ищем JR
trapped ;cюда попадаем, если уничтожили нужное смещение
ld (ix+0),a ;восстанавливаем байт смещения
;IX установлен на байт смещения
LD DE,16
ADD IX,DE
;вот и все. PC вычислен
;IX=$ !!!
;тут можно восстановить режим прерываний, если изменяли его ранее

