Радио-86РК/Радио 05-88/Пишем перемещаемые программы

Материал из Emuverse
Версия от 15:53, 17 сентября 2008; Panther (обсуждение | вклад) (http://retro.h1.ru/RK86/Programm/MovePrg.html)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Данный материал защищён авторскими правами!

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

Автор: Е. ЕРЕМИН

Источник: http://retro.h1.ru/RK86/Programm/MovePrg.html

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

Для достижения перемещаемости используют различные приемы: размещают в определенной области памяти стандартную таблицу переходов, формируют специальную таблицу коррекции BITMAP, применяют особые процедуры модификации адресов в командах перехода. Можно, однако заранее позаботиться о перемещаемости разрабатываемой программы и получить в результате код мало зависящий или, в идеальном случае, совсем не зависящий от места расположения в памяти компьютера. Некоторые приемы, позволяющие достичь этого, описаны ниже.

Предполагается, что читатель знаком с основными принципами работы микропроцессора КР580ВМ80 и имеет перед собой таблицу с системой его команд.

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


; ПОДПРОГРАММА ОПРЕДЕЛЕНИЯ КОЛИЧЕСТВА БАЙТ В КОМАНДЕ
; ВХОД: HL - АДРЕС КОМАНДЫ
; ВЫХОД:В - ЧИСЛО БАЙТ В КОНАНДЕ (0-КОМАНДЫ НЕТ)
;	С - НАЛИЧИЕ АДРЕСА В КОНАНДЕ (0-НЕТ, 1-ДА)
;	D - КОД КОНАНДЫ
; 	HL - СОХРАНЯЕТСЯ АДРЕС КОНАНДИ
; ВЫЗОВ ПОДПРОГРАННЫ NB ПО ОТНОСИТЕЛЬНОНУ АДРЕСУ
0120 		ORG 120Н
0120	110100 		LXI D,1 	; СМЕЩЕНИЕ ДЛЯ АДРЕСА П/П
0123 	CDZZZZ 		CALL ХХХХ 	; ВЫЗОВ П/П (СМ. ПРИМЕЧАНИЕ)
0126 	С9 		RET
; ПОДПРОГРАММА NB (КОЛИЧЕСТВО БАЙТ)
;
0127 	010001 		LXI В,100Н
012А 	7Е 		MOV А,Н 	; КОД КОНАНДЫ
012В 	57 		MOV D,A 	; СОХРАНИТЬ В D
012С 	B7 		ORA А
012D 	С8 		RZ 		; ВЫХОД ПРИ NOP (В=1, С=0)
012Е 	17 		RAL 		; ПРОВЕРКА НА СОВПАДЕНИЕ
012F 	17 		RAL 		; ДВУХ СТАРШИХ БИТОВ
0130 	89 		ADC С 		; 	7=>1,  6=>CY,
0131 	E601 		AHI 1 		;	1 БИТ+CY+0 (ИЗ РЕГ.С)
0133 	C0 		RNZ 		; 	3F<КОД<С0
0134 	7А 		MOV A.D
0135 	E6E7 		AHI 0E7H
0137 	FE02 		CPI 2
0139 	С8 		RZ 		; 	STAX И LDAX (B=1, C=0)
013A 	7A 		MOV A,D
013В 	E6CF 		ANI 0CFH
013D 	FEC1 		CPI 0C1H
013F 	C8 		RZ 		; 	POP (B=1, C=0)
0140 	0603 		MVI B,3
0142 	FE01 		CPI 1
0144 	С8 		RZ 		; 	LXI (B=3, C=0)
0145 	0С 		INR С
0146 	7А 		MOV A,D
0147 	FEC3 		CPI 0С3Н
0149 	С8 		RZ 		; 	JMP (B=3, C=1)
014A 	FECD 		CPI 0CDH
014C 	C8 		RZ		; 	CALL (B=3, C=1)
014D 	0D 		DCR С
014E 	41 		MOV В,С
014F 	E6CF 		ANI 0CFH
0151 	FECD 		CPI 0CDH 	; 	КОДЫ DD-FD (B=0, C=0)
0153 	С8 		RZ 		; 	НЕТ КОМАНД
0154 	04 		INR В
0155 	E607 		ANI 7
0157 	FE05 		CPI 5
0159 	С8 		RZ 		; 	DCR, DCX, PUSH (B=1, C=0)
015A 	FE07 		CPI 7
015C	C8 		RZ 		; 	RST, СДВИГ И Т.Д. (В=1, С=0)
015D 	04 		INR В
015E 	FE06 		CPI 6 		; 	MVI, ADI, SUI, ORI
0160 	C8 		RZ 		; 	и т.д. (B=2, C=0)
0161 	04 		INR В
0162 	0С 		INR С
0163 	FE02 		CPI 2 		; 	УСЛОВНЫЕ ПЕРЕХОДЫ, SHLD.
0165 	C8 		RZ 		; 	LHLD, STA, LDA (В=3, С=1)
0166 	7А 		MOV A,D
0167 	Е6С7 		ANI 0С7Н
0169 	FEC4 		CPI 0C4H 	; 	УСЛОВНЫЙ ВЫЗОВ
016В 	С8 		RZ 		; 	ПОДПРОГРАММЫ (В=З, С=1)
016С 	0D 		DCR С
016D 	41 		MOV В,С
016Е 	7A 		MOV A,D
016F 	Е6С7 		AHI 0C7H 	; 	КОДЫ 10-30, 08-З8 (В=0, С=0)
0171 	С8 		RZ 		; 	НЕТ КОМАНД
0172 	04 		INR В
0173 	FEC0		CPI 0C0H
0175 	C8 		RZ 		; 	ВОЗВРАТ ПО УСЛОВИЯМ (В=1, С=0)
0176 	7А 		MOV A,D
0177 	FE40 		CPI 40H
0179 	D8 		RС 		; 	КОД<40(В=1, С=0)
017A 	FEE0 		CPI 0Е0Н
017C 	D8 		RNС 		; 	КОД>ВF (В=1, С=0)
017D 	FEC9 		CPI 0С9Н
017F	С8 		RZ 		; 	RET (B=1, C=0)
0180 	04 		INR В
0181 	E6F7 		ANI 0F7H
0183 	FED3 		CPI 0D3H
0105 	C8 		RZ 		; 	IH, OUT (B=2, C=0)
0106 	41 		MOV В,С 	; 	КОДЫ D9, СВ (В=О, С=0)
0187 	С9 		RET 		; 	НЕТ КОМАНД
 	; ПРИМЕЧАНИЕ :
 	; С АДРЕСА ZZZZ (МЕТКА ХХХХ) ПРЕДВАРИТЕЛЬНО
 	; ЗАНОСЯТСЯ СЛЕДУЮЩИЕ КОМАНДЫ:
 	; ZZZZ 	ЕЗ ХХХХ:XTHL 	; ВЫЧИСЛЕНИЕ АБСОЛЮТООГО
 	; 	EB 	XCHG 	; АДРЕСА НАЧАЛА П/П
 	; 	19 	DAD D 	; (СМЕЩЕНИЕ ЗАДАНО В DE)
 	; 	ЕВ 	XCHG 	; С СОХРАНЕНИЕН РЕГИСГРА HL
 	; 	ЕЗ 	XTHL
 	; 	D5 	PUSH D 	; АДРЕС НАЧАЛА П/П В СТЕК
 	; 	С9 	RET 	; ПЕРЕХОД К ПОДПРОГРАММЕ

Описываемый фрагмент состоит из собственно подпрограммы определения количества байт в машинной команде, назовем ее NB, и обращения к ней. Обращение находится в адресах 120Н—126Н, а далее, начиная с адреса 127Н (хотя адрес и не имеет значения), расположена подпрограмма NB, с которой и начнем анализ.

Характерной чертой подпрограммы является полное отсутствие условных переходов, замененных из соображений перемещаемости возвратом по условию. Проверка в этом случае происходит в следующей последовательности: задаются выходные значения регистров В и С, соответствующие той или иной группе команд; выделяются характерные для этой группы биты; операциями ANI или СРI устанавливаются признаки и при выполнении необходимого условия происходит выход из подпрограммы. В противном случае анализ кода продолжается аналогичным образом.

Рассмотрим несколько примеров. Команда 127 заносит в ВС константу, соответствующую однобайтовой операции, и если в ОЗУ по адресу, записанному в регистре HL, находится NOP (код 0), то происходит выход из подпрограммы (адреса 12СН и 12DH). Затем выделяется вся средняя часть таблицы команд микропроцессора КР580ВМ80 (коды в диапазоне 40H—BFH), содержащая однобайтовые команды. Это сделать труднее, так как проверить сразу два условия по принятой методике нельзя. Внимательное изучение кодов команд показывает, однако, что можно обойтись и одной проверкой: при попадании в указанный диапазон два старших бита кода различны, а в противном случае они одинаковы (читатели могут убедиться в этом самостоятельно). Для сравнения старших битов производятся два циклических сдвига влево через бит переноса CY. При этом седьмой (старший) бит оказывается в нулевом бите аккумулятора, а шестой попадает в CY. По команде ADC С (адрес 130Н) интересующие нас биты складываются, и если они были различны, дают единицу (не забывайте, что в регистре С записан 0, и он не влияет на результат сложения). Если же при сложении в младшем бите получился 0, то анализ необходимо продолжить. Команды 134—139 «распознают» операции LDAX и STAX, в коде которых характерными битами являются три младших (с 0 по 2) и три старших (с 5 по 7). Трем младшим соответствует комбинация 010, а трем старшим — 000. Нетрудно убедиться, что после сброса битов 3 и 4 (команда 135) результат А-2 гарантирует, что мы имеем дело именно с этой группой команд.

Дальнейший анализ происходит аналогично. Следует только иметь в виду, что перед переходом к выявлению команды с другим количеством байт необходимо каждый раз предварительно изменять выходные параметры в регистрах В и С. Если коду не соответствует команда микропроцессора КР580ВМ80, то в регистровую пару ВС подпрограмма выдает 0.

Таким образом, мы убедились, что достаточно сложная в логическом отношении программа не содержит ни одного явно заданного адреса, а значит, полностью перемещаема. Как же к ней обратиться, если команда CALL требует задать абсолютный адрес подпрограммы? Один из возможных вариантов обращения использован в нашем примере (адреса 120Н—126Н). По пред полагаемому адресу рабочей области памяти (в таблице он заменен символами ZZZZ, ему соответствует метка Х XXX) должен быть предварительно занесен небольшой фрагмент приведенный в примечании таблице. При обращении к нему происходит вычисление абсолютного адреса начала подпрограммы по смещению заданному в регистровой паре DE (в нашем случае адрес определяется как 126+1=127).

Коды рассмотренной программы можно перемещать по памяти без единого изменения, при этом работоспособность программы полностью сохраняется. Требуется, правда, выделить 7 байтов в рабочей области, адреса которых заданы «жестко», но, представляется, это незначительная плата за полную перемещаемость программы (особенно удобно, если указанные 7 команд размещены в ПЗУ).

Автор желает успеха начинающим программистам и надеется, что описанные приемы разработки перемещаемых программ будут полезны владельцам «Радио-86РК», «Микроши» и других микрокомпьютеров на процессоре КР580ВМ80.


Е. ЕРЕМИН, г. Пермь.

Отсканировано с журнала Радио № 12 1991 г.
Отредактировано Лесных Ю.