ПРОФЕССИОНАЛЬНЫЙ ПОДХОД
Relocatable Program Make Utility Copyright 1994 by LEGION SOFT vl.00 APR-01-94
значение ORG 1-го экз. адрес 1-го экземпляра адрес 2-го экземпляра длина экземпляра
ПРОФЕССИОНАЛЬНЫЙ ПОДХОД
START LD HL, (0RG1) ;
LD ВС,OFFSET ; подготовительные
ADD HL,BC
LD B,H ; операции
LD C,L ;
EXX ; сохраняем HL* для кор-
PUSH HL ; рентного возврата в
; BASIC
LD ВС,(LEN) ; по адресу CD_LEN :
LD (CD_LEN),BC ; длина экземпляра
LD HL,Pl_LEN-OFFSET; по адресу SC_LEN :
ADD HL,BC ; длина экземпляра +
LD (SC_LEN),HL ; скорректированная
длина PARTI
LD HL,(ADR2)
LD DE,(ADR1)
PUSH HL ; в IX - адрес начала
POP IX ; настроечной
ADD IX,ВС ; таблицы
LOOP3 LD А,(DE)^ ; основной цикл поиска
CP (HL) ; различающихся
DR Z,NXT_B ; байтов
PUSH HL EXX
POP HL
LD E,(HL) ;
INC HL ; в DE - корректируемое
LD D,(HL) ; значение
EX DE,HL ;
OR A ;
SBC HL,BC ; ну вот,
EX DE,HL ; скорректировали !
LD (HL),D
DEC HL ; и запихали его
LD (HL),E ; обратно
LD DE,(ADR2) ; в HL - значение
OR A ; смещения до
SBC HL,DE ; скорректированного
LD DE ,P1__LEN-OFFSET
ADD HL,DE ; значения
LD (IX+O),L
LD (IX+1),H ;
INC IX ; в таблицу его !
INC IX ;
ПРОФЕСС1 |
10НАЛЬНЫЙ |
ПОДХОД I |
|
|
EXX |
|
пропускаем |
|
LDI |
|
; 1 (один) байт |
fXT_B |
LDI |
|
; следующий байт |
|
JP |
PE,LOOP3 |
( пока есть такой ) |
|
PUSH |
IX |
|
|
POP |
DE |
|
|
XOR |
A |
; нулевое слово - |
|
LD |
(DE),A |
; в таблицу |
|
INC |
DE |
(это маркер конца) |
|
LD |
(DE),A |
р |
|
INC |
DE |
; DE - за таблицей |
|
LD |
HL,PART2 |
; добавили PART2 |
|
LD |
BC,P2_LEN |
; в конец файла |
|
LDIR |
|
* |
|
PUSH |
DE |
р |
|
LD |
DE,(ADR2) |
* |
|
DEC |
DE |
; добавили PART1 |
|
LD |
HL,P1 END-1 |
в начало файла |
|
LD |
ВС,PI LEN |
|
|
LDDR |
|
|
DE HL A
HL,DE
в HL - суммарная длина программы
ЕХ |
(SP),HL |
; ее - в стек, |
|
|
; HL * - восстановили |
ЕХХ |
|
; в ВС-суммарная длина |
POP |
ВС |
; программы |
RET |
|
все ! |
Вызов программы: LET A=USR ЗЕ4, суммарная длина программы. Адрес
#007С
_RET PARTI
LD
PUSH DI
в А после возврата -начала: ADR2-P1_LEN
; адрес RET в ПЗУ
сохраняем состояние триггера прерываний (*)
DEC |
SP |
; вместе с (**) |
DEC |
SP |
; определили адрес LABEL |
POP |
ВС |
в ВС его ! |
ПРОФЕССИОНАЛЬНЫЙ
EQU |
$+1 |
; SC_LEN=aflpec данных |
LD |
HL, 0 |
; этой ( <— ) команды |
ADD |
HL,BC |
; т.о. HL=адрес таблицы |
LD |
E,(HL) |
|
INC |
HL |
|
LD |
D,(HL) |
; DE = смещение из |
INC |
HL |
; таблицы |
LD |
A,D |
|
OR |
E |
; конец таблицы ? |
PUSH |
HL |
; <-- (***) |
RET |
Z |
; если да, |
то в результате (***)
переход на PART2, иначе просто сохранили HL
в DE - корректируемое значение
ну вот, скорректировали !
и запихали его обратно
PI END-PARTI
; (*) необходимо запретить прерывания, т.к. если процедура
; их обработки будет вызвана между возвратом из _RET и/или
; DEC-ами SP, то адрес LABEL будет безвозвратно потерян...
(Аплодисменты. Зрители рыдают.)
; Дело в том, что после возврата из подпрограммы _RET адрес
; LABEL лежит по адресу SP-2, а при вызове процедуры обработки
; прерываний адрес возврата будет записан туда же...
PART2 LD HL,-OFFSET ; DE - адрес
ADD HL,DE ; загрузки файла,
LD DE,P1_LEN ; HL - начало
EX DE,HL ; кода настроенной
ADD HL,DE ; программы
аналогичный трюк см. выше
ПРОФЕССИОНАЛЬНЫЙ
адрес начала свободного пространства за настроенной программой
P2 END-PART2
К сему мы хотим сказать, что главным критерием при написании этой программы был минимальный размер части, присоединяемой к настраиваемому коду (т.е. размер PART1 и PART2). Именно поэтому эти фрагменты получились не совсем читабельными.
Для облегчения работы с нашей процедурой мы состряпали небольшой BASIC-интерфейс:
10 REM *** RPMU Interface **** 20 GO ТО VAL"100" 30 BORDER NOT PI: PAPER NOT PI: INK VAL"7"
40 CLEAR VAL"29999"
50 LOAD "RPMU.COM" CODE VAL"3E
4"
60 PRINT "RMPU vl.00 installed "'"Use memory from 30300." 70 STOP
99 REM ***********************
100 CLS
110 INPUT "BLOCK1 ORG value : " ;D
120 A^VAL"30002":GO SUB VAL"1E3
и
130 INPUT "BLOCK1 loading addre ss: ";B1A 140 A-A+VAL"2":LET D»B2A:GO SUB VAL"1E3"
150 INPUT "BLOCK2 loading addre ss: ";D
160 A=A+VAL"2":GO SUB VAL"1E3" 170 INPUT "Length of BLOCKS : " ;D
180 AaA+VAL"2":GO SUB VAL"1E3"
190 LET D-USR VAL"3E4"
200 PRINT "Adjusting complited.
M
300 PRINT "Use SAVE ""name"" CO DE ";B1A-VAL"36";",";D
310 STOP
999 REM *********************** 1000 RANDOMIZE D 1010 POKE A,PEEK VAL "xx" : POKE
A+SGN PI,PEEK VAL "ХХ+1" 1020 RETURN
Примечание: xx - адрес системной переменной SEED.
Мы старались не привязываться к конкретному накопителю, поэтому не вставили в BASIC-программу команд. выгрузки полученного и загрузки исходных файлов. Единственная накопителезависимая (извините за выражение) команда - это LOAD в строке 50. Поэтому если Вы используете не ленту, а какое-нибудь другое внешнее устройство (например, дисковод, принтер, плоттер, мышь или настольную лампу) , то замените команду загрузки "RMPU.COM" на нужную. Кстати, запись НАШЕЙ BASIC-программы необходимо производить командой: SAVE "RMPU" LINE 30 (или аналогичной, которую "понимает" Ваш DOS или Микродрайв).
Ну а теперь рассказ о самом интересном: как же пользоваться тем, что мы тут накропали. Итак, чтобы получить релоцируемую программу нужно:
1. Откомпилировать Ваш ассемблерный файл с двумя различными значениями ORG, причем у этих значений должны отличаться и младшие байты. После этого необходимо запомнить (а кому трудно, записать) длину полученного кода и значение ORG одного из блоков.
Потом эти значения потребуются для работы RMPU.
2. Отгрузить полученные модули на внешний носитель.
3. Загрузить RPMU.
4. После того, как появится сообщение: "RMPU vl.00- installed..." загрузить Ваши модули в свободную память.
5. Запустить RPMU командой RUN и чистосердечно ответить на вопросы программы, введя ранее запомненные значения и адреса загрузки .
6. Сообщение: "Adjusting computed. " известит Вас о том, что настройка закончена и готовую программу можно сохранить на внешнем носителе. Для выгрузки на ленту надо использовать указанную команду (если у Вас другой носитель, то скорректируйте ее соответствующим образом).
Итак, Вы получили релоцируемую версию некоторой программы. Возникает резонный вопрос: "А как же ей пользоваться?" Все очень просто. Загружаете ее в память:
LOAD "name" CODE addr
И запускаете: LET A~USR addr
Программа вернется в BASIC и в результате в переменной А будет адрес первой свободной ячейки памяти, а по адресу addr разместится Ваша настроенная программа. Теперь Вы можете запускать ее обынной командой:
RANDOMIZE USR addr
Обратите внимание, что полученная программа содержит только то, что Вы написали. Процедура и таблица настройки удалены так как они больше не нужны.
Теперь нам хотелось бы остановиться на модификации программ, для которых у Вас нет исходного текста (пример: Memory Editor). В этом случае придется воспользоваться директивой "Т" монитора MONS для его получения. К сожалению этот способ подходит только для опытных пользователей, но другого пути на наш взгляд нет.
Наконец, несколько слов еще об одном варианте использования предлагаемой программы. На компьютере IBM PC есть очень интересная возможность организации своих процедур - OBJ файлы. Нечто подобное можно попытаться сделать и на SPECCY. Тут поможет предложенная Вами идея КЕРНАЛЯ. Делать это надо примерно так:
- Вы создаете свои кодовые процедуры так, чтобы они "общались" между собой только через КЕРНАЛЬ.
- Каждая процедура делается перемещаемой при помощи RPMU.
- Программа, которая должна их использовать, сама загружает эти процедуры в память (причем в любой комбинации) и запускает настройщик. Затем адреса размещения процедур заносятся в определенные ячейки КЕРНАЛЯ.
Таким образом Вы полуавтоматически можете создать кодовую часть будущей программы даже из BASICa. Это будет выглядеть примерно так:
10 DATA "NAME1", "NAME2", ...
20 CLEAR 29999 : LET ADR=3E4
30 FOR 1=1 TO NOF : REM NOF -оличество подключаемых файлов. десь должны находиться строки, оторые отвечают за запись адреса ачала очередной процедуры (т.е. DR ) В КЕРНАЛЬ.
80 READ N$
90 LOAD N$ CODE ADR : LET ADR» USR ADR 100 NEXT I
Мы понимаем, что предложенная идея не отличается особой элегантностью, но ведь это только идея. И может быть кто-то, опираясь на нее, создаст что-то действительно стоящее.
* * *