ZX-Ревю 1993 №1-2 1992 г.

Секреты TR-DOS - выполнение команд TR-DOS из машинного кода.


ВЫПОЛНЕНИЕ КОМАНД TR-DOS ИЗ МАШИННОГО КОДА.

Трудно переоценить значение этих сведений для программиста, поэтому сразу к делу.

В фирменном руководстве по TR-DOS описан способ выполнения команд TR-DOS из машинного кода. Суть его в двух словах в следующем. Где-то в памяти Спектрума размещается фрагмент Бейсик-программы - некоторая фиктивная Бейсик-строка, содержащая команду TR-DOS. Формат записи этой Бейсик-строки такой же, каким он является в обычной Бейсик-программе. Затем в регистры процессора и системные переменные Бейсика заносится адрес, в котором находится новый фрагмент "фиктивной" Бейсик-программы. Затем происходит запуск интерпретатора Бейсика для выполнения этой фиктивной строки. Такой способ выполнения машинного кода при помощи Бейсика настолько громоздок и несуразен, что может иметь разве что чисто теоретическое значение и вряд ли кем-то может восприниматься серьезно. Но главное в том, что он выполняет только то, что может быть выполнено из обычного Бейсика и не более того.

Для выполнения команд из машинного кода в TR-DOS существуют специальные возможности. Основная из них - использование подпрограммы TR-DOS с точкой входа 15635 (#3D13). С этого адреса в конечном счете осуществляется переход к подпрограмме 10300 (#283C), которая в зависимости от кода, содержащегося в регистре C процессора передает управление соответствующей процедуре системы TR-DOS. Практически фрагмент выполнения команды TR-DOS из машинного кода может выглядеть следующим образом:

LD C, ...

CALL #3D13

Кроме регистра C может потребоваться предварительная установка других регистров процессора.

Рассмотрим кратко основные процедуры, выполняемые в зависимости от содержимого регистра С.

С=0. Восстановление, сброс контроллера, при котором головка отводится на нулевую дорожку и ожидается появление сигнала INTRQ. Выход из режима ожидания может быть произведен при нажатии клавиши BREAK на клавиатуре.

С=1. Инициализация дисковода. Предварительно в регистре A должен быть задан номер накопителя 0...3. Здесь надо сказать, что если TR-DOS стартует при открытом кармане дисковода или без дискеты, то по адресам 23802...23805 заносятся числа 255. Это означает, что дисководы не инициализированы. В результате работы этой процедуры устанавливается время перемещения головки дисковода - заносится число 8 по одному из адресов 23802...23805 в зависимости от номера дисковода. Далее определяется количество дорожек дисковода и результат заносится по одному из адресов 23752...23755 в соответствии с номером накопителя (первоначальное значение также 255). Если дисковод имеет 40 дорожек, то записывается 0, если 80 дорожек, то 128 (устанавливается 7-и бит). Далее задается номер дисковода для временной операции (берется из регистра А) и это значение заносятся по адресу 23798. По адресу 23830 помещается копия системного регистра.

Если время перемещения головки (ячейки 23802...23805) уже установлено, то операции по инициализации дисковода не производятся.

C=2. Позиционирование. Предварительно в регистр A помещается номер дорожки, на которую должна быть установлена головка. При двустороннем дисководе первому физическому треку соответствуют номера 0 и 1, второму - 2 и 3 и т. д.

С=3. Эта процедура помещает содержимое регистра A по адресу 23807, задавая, таким способом номер сектора.

С=4. Процедура помещает содержимое регистра HL по адресу 23808 (2 байта), задавая таким способом адрес буфера.

С=5. Очень важная подпрограмма. Она позволяет читать блок секторов. Для этого необходимо подготовить начальные параметры в регистрах процессора. В регистр B помещается количество читаемых подряд секторов. В том случае, если B=0, то с диска считывается только область заголовка, считывание сектора в память не производится. В регистровую пару DE помещается начало считываемого блока секторов: в D - дорожка, а в Е - сектор. В регистре HL должен быть задан адрес начала буфера в памяти Спектрума, куда будет производиться загрузка блока секторов.

С=6. Процедура записи на диск блока секторов. Все параметры аналогичны тем, которые были в предыдущей процедуре.

C=7. Вывод каталога диска (аналогично команде CAT TR-DOS). В регистре A должен быть задан канал для вывода каталога. Для вывода на дисплей, например, в регистре A должно быть 2 (кстати, при этом будет очищен экран). Для вывода на принтер - 3. Следует также сказать, что перед выполнением этой подпрограммы можно задать номер накопителя для временной операции, поместив его по адресу 23798. Эта процедура предварительно выполняет процедуру при C=22 - загрузку системного регистра (см. ниже).

С=8. Чтение заголовка файла. В регистре A должен быть номер интересующего файла (с 0 по 127). Из каталога диска 16 байт заголовка файла будут помещены в память, начиная с адреса 23773. Это может быть и удаленный файл, так как не проверяется, есть ли такой файл в действительности.

С=9. Запись в каталог заголовка файла. 16 байт из памяти, начиная с адреса 23773, переписываются в каталог диска на место заголовка файла, номер которого задается в регистре A аналогично предыдущей процедуре.

С=10. Процедура поиска файла. В каталоге диска ищется файл, который по имени и типу совпадает с тем, что задано в памяти, начиная с адреса 23773. Количество байт, на которые ведется поиск, задается по адресу 23814. Начальное значение - 9. В том случае, если файл найден, то его номер будет находиться в регистре C, а также в ячейке 23838. Если файл не найден, то в регистре C будет 128 (7-й бит установлен в 1), содержимое 23838 не изменяется, а в ячейке 23823 будет 255.

C=11. Запись кодового файла. При этом с адреса 23773 задается имя и тип файла, в регистре HL - адрес начала файла в памяти, в регистре DE - длина файла. Эта процедура

выполняет действия аналогичные команде TR-DOS:

SAVE "name" CODE Start, Length.

С=12. Запись Бейсик-программы. С адреса 23773 должны быть заданы имя и тип файла. В том случае, если тип файла отличается от "В", то файл записывается под именем "boot" <B>.

С=14. Загрузка или верификация файла. Имя и тип файла должны быть помещены по адресу 23773. Здесь есть несколько вариантов, в зависимости от значения регистра A. При A=0 адрес загрузки и длина файла берутся из каталога. При A=3 загрузка происходит с адреса, который задается в регистре HL, причем длина загрузки определяется значением регистра DE. При A=255 адрес загрузки берется из HL, а длина загружаемого файла - из каталога диска. Значение по адресу 23801 определяет команду: 0 - LOAD, 255 - VERIFY.

С=18. Удаление файла. Имя и тип файла должны быть заданы с адреса 23773. При этом удаляются все файлы с такими данными. Как уже говорилось выше, если файл не последний, первый символ имени файла заменяется кодом 01.

С=19. Эта процедура перебрасывает 16 байт информации с адреса, указанного в HL в адрес 23773.

С=20. Процедура, обратная предыдущей. 16 байт перебрасываются с адреса 23773 в адрес, указанный в HL.

С=22. Процедура загружает системный регистр интерфейса. Код - в аккумулятор (регистре A), при загрузке к содержимому аккумулятора добавляется #3C.

Для других значений C в различных источниках приводятся противоречивые или весьма смутные сведения, поэтому на них не будем останавливаться. Для любителей покопаться в ПЗУ TR-DOS привожу входные адреса процедур, соответствующие различным значениям регистра C.

C=0

C=1

C=2

C=3

C=4

C=5

C=6

C=7

C=8

C=9

C=10

C=11

C=12

#3D98

#3DCB

#3E63

#3F02

#3F06

#1E3D

#1E4D

#28D8

#165C

#1664

#1CF0

#28FB

#28F2

C=13 C=14 C=15 C=16 C=17 C=18 C=19 C=20 C=21 C=22 C=23 C=24

#01D3 #290F #01D3 #01D3 #01D3 #2926 #28E0 #28E3 #2739 #1FEB #1FF6 #0405

Для выполнения команд TR-DOS из машинного кода существует еще один способ. Он позволяет обращаться сразу же непосредственно в теневое ПЗУ TR-DOS, в любую его точку. Вы спросите, как же это практически сделать, ведь обратившись, например, по одному из тех адресов, которые приведены выше, мы попадем всего лишь в основное ПЗУ Спектрума. Для этого в системе TR-DOS имеется специальная точка входа с адресом 15663 (#3D2F). Там находится всего лишь одна команда NOP, после чего сразу же идет RET. Дело в том, что при обращении по адресу 15663 селектор адреса БЕТА-ДИСК интерфейса подключает

теневое ПЗУ, а выполнение команды RET приведет к переходу программы на адрес, записанный на стеке. Поэтому если перед обращением к 15663 на стек поместить нужный адрес, то можно осуществить переход на этот заданный адрес теневого ПЗУ командой: JP 15663.

В качестве практического примера использования машинного кода для выполнения команд TR-DOS приведу простую программу "DIR", которая позволяет выводить на экран параметры файлов (имя, тип, адрес загрузки, длина и т. п.), содержащиеся в каталоге диска. Кроме теоретического, эта программа представляет определенный практический интерес, так как выводит кроме обычной информации еще и данные о начале файлов на диске (команда LIST TR-DOS эту информацию не выводит).

Программа "DIR".

Машиннокодовая часть программы выглядит следующим образом (адрес размещения - произвольный):

21

00

AB

LD

HL,#AB00

(1)

11

00

00

LD

DE,#0000

(2)

06

08

LD

B,#08

(3)

0E

05

LD

C,#05

(4)

CD

13

3D

CALL

#3D13

(5)

C9

RET

(6)

В регистре HL задается (1) адрес буфера, куда будет производиться чтение каталога диска (#АВ00=43776). В регистрах D и Е задаются начальные дорожка и сектор (2): чтение будет начинаться с 0 сектора 0 дорожки. Число считываемых подряд секторов задается (3) равным 8, столько занимает каталог диска. Затем задается (4) параметр, определяющий процедуру: С=5, то есть чтение блока секторов и далее (5) выполнение подпрограммы TR-DOS. После чего (6) - возврат в вызывающую программу.

После того, как содержимое нулевой дорожки считано в буфер, его можно рассмотреть более подробно. Этим уже займется Бейсик. Программа выглядит следующим образом:

2 BORDER 1: PAPER 7: INK 1: aEAR 39999

3 RESTORE : FOR a=40000 TO 40013: READ b: POKE a, b: NEXT a: DATA 33,0,171,17,0,0,6,8,14,5,

205,19,61,201

4 GO TO 100

5 RANDOMIZE USR 15619: REM : SAVE "DIR"

6 STOP

20 PRINT AT 0,0; PAPER 6; INK 2;"Name "; PAPER 2; INK 7; "Type" ; PAPER 3; INK 0; " Start

Length " ; PAPER 4; "Beginn"; PAPER 5;" Len" 22 PRINT BRIGHT 1: INVERSE 1; " ASCII "; INVERSE 0; " B у t e s "; INVERSE 1;"Trk"; INVERSE

0; " Sector" 24 RETURN

30 FOR a=a TO a+7: LET n$=n$+CHR$ PEEK a: NEXT a: REM name

31 LET t$ = CHR$ PEEK a: REM type

32 LET a=a+1: LET st=PEEK a+256*PEEK (a+1): REM start

33 LET a=a+2: LET len=PEEK a+256*РЕEК (a+1): REM length

34 LET a=a+2: LET q=PEEK a: REM length SEC

35 LET a=a+1: LET sec=PEEK a: REM benin SEC

36 LET a=a+1: LET tr=PEEK a: REM begin TRK

37 LET a=a+1: RETURN 100 RANDOMIZE USR 40000 200 LET a=43776

300 GO SUB 20: LET j=2: BEEP .01, j+10 1000 LET n$="": GO SUB 30

1010 PRINT AT i,j; PAPER 6; INK 2; n$; PAPER 2; INK 7; t$;

1020 PRINT PAPER 3; INK 0; TAB 10; st; TAB 16; len; TAB 22; PAPER 4; INK 0; TAB (22+(tr<100)); tr; TAB 26; sec; TAB 28; PAPER 5; INK 0; TAB 29; q; TAB 32; 1030 LET j=j+1: BEEP .01,.j+10: IF J>=22 THEN PAUSE 0: CLS : GO TO 300 1040 IF a<43776+256*8 THEN GO TO 1000

2000 PRINT #0; INVERSE 1; "DIR O.K.": BEEP .1,26: BEEP .1,20: РАUSE 0: CLS : GO TO 200

После набора программы сделайте RUN 5 - это запись программы на диск. Нет необходимости записывать программу на диск с автостартом. Любой загрузчик ("boot") запускает программу с начальной строки. При этом строка 2 формирует в памяти необходимый кодовый блок, после чего происходит чтение восьми секторов нулевой дорожки (строка 100). Считанная информация размещается с адреса 43776 (#AB00). GO SUB 20 в строке 300 - это распечатка "шапки". Переменная j - это номер строки экрана для вывода последующей информации.

Со строки 1000 расположена программа распечатки одного экрана информации. Подпрограмма GO SUB 30 производит расчет параметров для каждого заголовка файла. Первые 8 байт - имя программы (n$, строка 30). Затем тип (t$, строка 31). Следующие 2 байта определяют параметр START (st, строка 32). Затем 2 байта - длина файла (len, строка 33). Потом идет 1 байт - длина файла в секторах (q, строка 34). Следующая пара байт начало файла на диске - сектор и дорожка (соответственно sec и tr в строках 35 и 36).

Строки 1010 и 1020 - это распечатка полученных данный по одному заголовку - 16 байтам нулевой дорожки. Строка 1030 - завершающие операции по распечатке заголовка и проверка на достижение конца экрана. Если он достигнут, то очистка экрана и распечатка следующего (со строки 300).

Строка 1040 проверяет, не достигнут ли конец каталога (8 секторов по 256 байт). Если нет, то переход к расчету и печати информации о следующем файле (со строки 1000). Иначе - завершение работы переходом на строку 2000, где программа зацикливается, возобновляя вывод информации с первого заголовка файла.

Теперь предположим, что Вы запустили эту программу, вставив в дисковод какую-нибудь дискету. После того, как на экран будет выведена информация о всех существующих файлах (при этом удаленные файлы будут начинаться со знака "?"), если на дискете больше нет файлов, то вся последующая часть каталога будет состоять из нулей. Чтобы не "прокручивать" вхолостую весь каталог, можно добавить в программу такую строку:

1035 IF PEEK а=0 THEN GO ТО 2000

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

Как еще можно усовершенствовать программу? Ну, например, можно в конце добавить вывод информации по диску, его имя, число файлов, наличие свободного места и т.д., в общем, все то, что можно "выудить" из восьмого системного сектора. Для этого надо чтобы с нулевой дорожки было считано не 8 секторов, а 9. Для этого в строке 3 после DATA число 8 должно быть заменено на 9. Теперь заодно с каталогом в память будет считан и системный сектор. Попробуйте сами сделать такое усовершенствование, если хотите, расположив эту часть программы, начиная со строки 2000. Вся необходимая информация по расшифровке системного сектора приведена выше.

Для того, чтобы просмотреть новый диск, можно нажать BREAK, затем сделать RUN. Используя блок кодов "ON ERROR GO TO" (см. ZX-РЕВЮ N 5-6 за 1992 год, стр.113), Вы можете еще более усовершенствовать программу: она будет перезапускаться с начальной строки при нажатии BREAK для того, чтобы можно было просмотреть новый диск.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Calendar
Иcтина, где-то там... - Версии внеземнои жизни.
По полочкам - Vel своей читалке ты так круто на нас наехал, что мы все чуть не обосрались от страха. Какой ты, оказывается, крутой и навороченный, самый известный в Коврове...
Demo Party - Про Fun Top и всех-всех-всех... (запоздалый репортаж Serzh'a в 5-ти частях)
Всякая всячина - Разговор на тему.

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