Глава
4
ЗАГРУЗЧИКИ В МАШИННЫХ
КОДАХ
для тех, кто
не знает, что такое машинный код
Несмотря
на то, что знание ассемблера не является обязательным для понимания того, о чем
я буду писать дальше, оно отнюдь не повредит. Еще более полезным является
умение пользоваться каким либо монитором-дизассемблером. Если Вы не знаете, что
такое дизассемблер, рекомендую воспользоваться программой из пакета Ultraviolet
/ Infrared. Это первые ассемблер и дизассемблер, появившиеся на рынке для ZX
Spectrum. Программа проста в обращении и вполне приемлема для решения тех
задач, которые будут разбираться в этой главе. Позднее Вам придется перейти к
чему-нибудь более серьезному (например, MONS4).
Изложить
последовательно и понятно организацию загрузки файлов из машинного кода для
неподготовленного пользователя — задача более чем сложная, но попробовать
можно.
Начнем
с самого простого. Предположим, что на ленте имеется программа, состоящая из
четырех файлов: файл на Бейсике, кодовый файл и два файла без заголовка. Изучив
бейсик-программу, Вы пришли к выводу, что она загружает кодовый файл и
запускает его с адреса 65000.
С
помощью копировщика Вы определили, что кодовый файл загружается с адреса 65000
и имеет длину 30 байт, длина файлов без заголовка равна соответственно 6912 и
32768 байт.
Теперь
загрузите кодовый файл туда, где ему положено, находиться, но запустите не его,
а Ваш дизассемблер. Дизассемблировать память необходимо, начиная с адреса запуска,
то есть с адреса 65000. Предположим, что дизассемблер показал следующее*:
65000 LD IX, 16384 ; стартовый адрес
65004 LD DE,6912 ; длина
65007 LD А,255
65009 SCF
65010 CALL 1366 ;вызов подпрограммы загрузки
65013 LD IX,25000 ;стартовый адрес
65017 LD DE,32768 ;длина
65020 LD А,255 ;вызов подпрограммы загрузки
65022 SCF
65023 CALL 1366
65026 JP 40000 ; запуск программы
65029 NOP
Не
берусь объяснять смысл всех этих закорючек. Если Вы знаете, что они обозначают
— Ваше счастье, если нет, то и Бог с Вами. Чтобы мало-мальски разбираться с
загрузчиками, необходимо запомнить, что после LD IX следует адрес
загрузки файла, после LD DE — его длина. Мнемоники LD А,255 и SCF
устанавливают системные регистры, a
CALL 1366
вызывает подпрограмму загрузки с ленты. Адрес после CALL может меняться
в зависимости от того, использует ли загрузчик стандартную подпрограмму
загрузки, расположенную в ПЗУ (как в данном примере), или свою собственную.
В
приведенном выше примере мы видим две группы команд, обеспечивающих загрузку
файла, и команду JP 40000. Последняя является аналогом оператора RANDOMIZE
USR 40000 в загрузчике на Бейсике, то есть запускает основную программу.
Таким
образом, мы узнали, что наш загрузчик загружает два файла, первый из которых
(длиной 6912 и адресом загрузки 16384), очевидно, — заставка, а второй (32768 и
25000 соответственно) — основной файл программы (обратите внимание, что данные
о длинах файла совпадают с данными, предоставленными копировщиком); кроме того,
мы узнали, что программа запускается с адреса 40000.
_______________________________________________________________
*
Прошу извинить, что я часто привожу числа в десятичной системе счисления:
сказывается застарелая привычка.
Получив
эти данные, можно приступить к адаптации программы.
Пожалуй,
самое сложное, что предстоит сделать, — это записать два файла без заголовков
на диск. Если у вас есть программа PCopier или PCopier Plus, то задача
несколько упростится. Достаточно будет скопировать файлы на диск, а затем
выполнить следующую программу:
10 RANDOMIZE USR 15619: REM :
LOAD "less 001 "CODE 16384
20 RANDOMIZE USR 15619: REM :
SAVE "screen"SCREEN$
30 RANDOMIZE USR 15619: REM :
LOAD "less 002"CODE 25000
40 RANDOMIZE USR 15619: REM : .
SAVE "main"CODE 25000,32768
Разумеется,
адреса и имена файлов пригодны только для данного примера.
Существует, однако, немало способов копирования файлов и без использования
специальных копировщиков. Приведу наиболее простой для данного примера метод (в
принципе, он пригоден для большинства случаев).
После
загрузки файлов загрузчик, как правило, запускает программу. Обычно для этого используется
уже упомянутая команда JP ХХХХХ, где ХХХХХ — адрес запуска
программы. Чтобы получить копию файла на диске, нужно загрузить файлы в память
с ленты и записать их на диск. Для этого можно воспользоваться уже готовым
загрузчиком, предварительно заменив инструкцию, запускающую программу, на инструкцию,
возвращающую управление бейсик-интерпретатору, то есть вместо мнемоники JP
нужно поставить RET, код которой — 201. В нашем примере этого можно
добиться, выполнив оператор РОКЕ 65026,201. Значение по адресу,
где расположена инструкция JP, изменится на 201 (команда RET),
что и обеспечит возврат в бейсик систему после загрузки обоих файлов.
Подготовив
кодовый загрузчик подобным образом, можно его запускать, не забыв обеспечить
запись файлов на диск непосредственно после завершения работы загрузчика. Удобно
набрать программу в несколько строк:
10 RANDOMIZE USR 65000: REM Запуск загрузчика
20 RANDOMIZE USR 15619: REM : SAVE "screen"SCREEN$
30 RANDOMIZE USR 15619: REM :
SAVE "main"CODE 25000,32768
Когда
на экране появится сообщение об успешном выполнении программы, Вам останется
только написать загрузчик с диска, с чем, я надеюсь, трудностей не возникнет.