ZX-Ревю 1994 №4 1993 г.

Релоцируемость программ - После публикации статьи Александра Гмарь "Memory Editor" нас буквально захлестнула волна писем по поводу устранения недостатка программы - её нерелоцируемости. Два наиболее удачных варианта усовершенствования программы мы приводили в третьем номере журнала за этот год.


РЕЛОЦИРУЕМОСТЬ ПРОГРАММ

© Артем Зайцев, г. Чита, 1994.

После публикации в РЕВЮ-94 № 1 на стр.51 статьи Александра Гмарь "Memory Editor" нас буквально захлестнула волна писем по поводу устранения недостатка программы - её нерелоцируемости (было письмо и от автора программы). Два наиболее удачных варианта усовершенствования программы мы приводили в третьем номере журнала за этот год (стр. 66). Считаем, что тема эта в основном, исчерпана, но, в заключение, приводим статью, в которой, на наш взгляд, содержится наиболее систематизированный подход к проблеме релоцируемости любой программы.

Я предлагаю Вашему вниманию две процедуры на ассемблере, которые помогут сделать релоцируемой любую программу. Для этого их нужно снабдить таблицами указания на те адреса, в которых содержатся команды абсолютного перехода, обращения к подпрограммам и программным переменным и разместить их непосредственно перед основной программой. Первая процедура использует таблицу смещений, то есть каждый последующий адрес вычисляется путем прибавления к предыдущему адресу соответствующего смещения из таблицы. Вторая процедура использует таблицу абсолютных адресов нужных ячеек. Это единственное отличие этих двух процедур. В остальном принцип их работы одинаков и заключается в следующем. Процедура определяет адрес, в котором она находится в данный момент, вычитает из него ADDR=A-LEN-47 для первой и ADDR=A-2*LEN-44 для второй процедуры. Здесь A - адрес, под который была ассемблирована исходная программа, LEN - количество изменяемых ячеек (компонентов таблицы). После вычисления разности процедура при помощи таблицы находит адреса в тексте программы, которые требуют корректировки, увеличивает содержащиеся в них двухбайтные значения на разность и переходит к следующей ячейке таблицы. После того, как вся программа будет скорректирована под адрес загрузки, ей передается управление.

Приводимый в листинге блок является как бы заголовком и подготавливает данные для основного блока. После его работы регистры содержат следующие значения (см. на следующей странице):

Процедура 1.

CALL #007С ; По адресу #007С в ПЗУ находится команда

DEC SP ; RET, т.е. программа возвращается, ничего

DEC SP ; не сделав, но на стеке останется при этом

POP HL ; адрес на 3 меньший, чем адрес загрузки программы, который

мы и помещаем в регистр HL. Помещаем в DE адрес. Вычисляем разность. Теперь разность в DE. B ВС количество ячеек таблицы. B HL адрес начала таблицы.

Подгоняем адрес начала таблицы под адрес загрузки. Копируем HL в IX.

LOOP PUSH DE ; Два раза сохраняем разность на стеке.

Помещаем в DE смещение из текущей ячейки таблицы.

Останавливаем в HL адрес следующей изменяемой ячейки. B DE помещаем двухбайтный адрес из программы, подлежащий изменению.

Помещаем в HL разность, а старое значение HL временно сохраняем на стеке. B DE измененное значение адреса.

Возвращаем измененное значение в программу.

Вспоминаем в DE разность. Переходим к следующей ячейке таблицы. Количество оставшихся ячеек уменьшаем на 1. Проверяем ВС на ноль.

Зацикливание.

Если таблица исчерпана, то IX указывает

на адрес сразу после таблицы. Теперь переход на IX

запустит программу.

LD

DE,ADDR

SBC

HL, DE

EX

DE, HL

LD

BC,LEN

LD

HL,BEGIN

ADD

HL, DE

PUSH

HL

POP

IX

PUSH

DE

PUSH

DE

LD

D,0

LD

Е,(IX+0)

ADD

HL, DE

LD

E,(HL)

INC

HL

LD

D,(HL)

EX

(SP),HL

ADD

HL, DE

EX

DE, HL

POP

HL

LD

(HL),D

DEC

HL

LD

(HL),E

POP

DE

INC

IX

DEC

BC

LD

А, В

OR

С

JR

NZ,LOOP

PUSH

IX

RET

DE - разность.

ВС - количество разрядов таблицы.

IX - начало таблицы смещений. В дальнейшем IX будет указывать на текущий адрес в таблице.

HL - первоначально также указывает на начало таблицы, но в дальнейшем, в отличие от IX, будет указывать на адрес текущей изменяемой ячейки. Таким образом, первое смещение осуществляется относительно начала таблицы, но оно может осуществляться и от произвольного адреса, например, от начала программы. Для этого нужно добавить строки:

LD HL,адрес

ADD HL,DE

Нужно также заметить, что все смещения считаются положительными (от 0 до 255).

Вторая процедура, как уже говорилось, отличается от первой тем, что использует таблицу не однобайтных смещений, а двухбайтных абсолютных ссылок.

Процедура 2.

#007C SP SP HL

DE,ADDR HL, DE DE, HL BC,LEN

Эта часть аналогична представленной в процедуре 1.

CALL

DEC

DEC

POP

LD

SBC

EX

LD

Следует помнить, что здесь каждая ячейка таблицы занимает два байта, поэтому LEN будет в два раза меньше, чем длина самой таблицы.

Переброска значений HL и DE в регистры HL и BC альтернативные.

HL,BEGIN HL, DE DE HL

HL BC A,2 E,(HL) HL

D,(HL) DE, HL HL, BC A

NZ,LOOP_2 DE, HL (HL),D HL

(HL),E

HL HL BC A, B C

NZ,LOOP_1 HL

LD ADD LOOP_1 PUSH PUSH EXX POP POP LD

LOOP_2 LD INC LD EX ADD DEC JR EX LD DEC LD EXX INC INC DEC LD OR JR

PUSH RET

2 проход Принимаем в DE измененный адрес и увеличиваем его на разность.

1 проход Принимаем в DE ад-pec из таблицы, перебрасываем его в HL и увеличиваем на разность.

Помещаем измененный адрес назад в программу.

Переключаемся на основной набор. Переходим к следующей ячейке таблицы.

Уменьшаем количество оставшихся ячеек и проверяем их на ноль.

Зацикливание. Запуск программы.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Открытые письма Nemo №6.276
Тест - Умeeтe ли вы oбращаться с дeньrами? He бeсnoкoйтeсь - с вами всe в noрядкe. Плoxиe нoвoсти - залor бoлeзни.
Интервью - Открытие Спектрума: Вячеслав Медноногов/Copper Feet, Павел Федин, Александр Майоров/MAS, Андрей Савичев.
Новости
Обзор WEB - англоязычные ресурсы о ZX Spectrum.

В этот день...   21 ноября