Пакет документации о рестартах iS-DOS 1969 г.

Исходники IS-DOS - исходники uni_Clas.sys, uni_Chic.sys, HDD_boot.


 


 

uni_Clas.sys

 

Файл uni_Clas.sys является файлом загрузчика системы iS-DOS Classic с винчестера. Этот файл загружается в память компьютера с адреса #6100 загрузчиком из ПЗУ TR-DOS и запускается на выполнение. Программа uni_Clas.sys использует процедуру загрузчика по адресу #5E03 для чтения файла системы в память. В теле программы располагаются системные переменные TR-DOS и BASIC.

Дизассемблер программы:

 

ORG #6100

 

JR BEGIN                           ;переход на начало программы

 

DEFW SYSP-#6100            ;по адресу +2 от начала программы лежит смещение начала

                                        ;системных переменных от начала программы

 

BEGIN        LD SP,#5DC0                      ;устанавливаем стек

LD IY,#5C3A                       ;стандартное значение IY

LD A,#10                            ;включаем банк 0 расширенной памяти

LD BC,#7FFD

OUT (C),A

 

LD HL,(BUFER+#20+12)      ;адрес загрузки файла is_dos.sys (берём из описателя is_dos.sys в 0-м

LD A,L                                ;блоке

OR H                                  ;проверка его на 0

RET Z                              ;если равен 0, то что-то не так, поэтому возврат обратно

LD DE,(BUFER+#20+17)     ;номер начального блока файла is_dos.sys

LD A,E                               ;проверка на 0

OR D

RET Z

LD A,H                               ;за длину is_dos.sys в блоках берём разницу между концом памяти и

CPL                                    ;адресом загрузки, т.е. инвертируем старший байт адреса загрузки

INC A                                  ;и прибавляем 1

LD B,A                               ;получаем длину файла в блоках

CALL READ                        ;читаем файл системы в память

RET C                              ;если была ошибка чтения, то выход

 

LD A,(BUFER+#20+22)        ;вектор прерывания хранится в описателе по смещению +22

LD I,A

 

LD HL,SYSP                       ;устанавливаем системные переменные

LD DE,#5C00

LD BC,#0200

LDIR

 

LD C,#10                            ;читаем вектор конфигурации ядра

RST #10

EXX

LD BC,#FFFA                     ;по смещению -6 лежит размер электронного диска в блоках

ADD HL,BC

LD A,(HL)                           ;читаем размер электронного диска

 

LD C,0                                ;создаём электронный диск

RST #10

JR C,ERROR                      ;теперь мы уже в системе, поэтому можно по ошибке выходить прямо

                                        ;в систему

 

LD C,#45                            ;читаем адрес внутреннего буфера командной строки

RST #10

EXX

DEC HL                            ;по смещению -3 и -2 лежит дата

DEC HL

LD DE,(BUFER+30)            ;берём дату из 0-го блока устройства

LD (HL),D                           ;и устанавливаем её в систему

DEC HL

LD (HL),E

 

LD A,#53               ;устройство "S"

LD C,#4A            ;преобразуем логическое имя устройства в физическое

RST #10

LD B,A                  ;получаем № канала блочного устройства

LD C,#1C            ;переключаемся на устройство "S"

RST #10

JR C,ERROR

LD C,#20               ;открываем устройство и главный каталог

RST #10

JR C,ERROR

LD C,#93               ;$shexe - выходит в оболочку с запуском autoexec.bat, т.е. управления он уже не

                          ;отдаст

IM 2                      ;перед выходом включаем IM2

JR NC,RUN           ;если не было ошибок то выполнение рестарта

LD C,#84               ;выход в оболочку с сообщением об ошибке

RUN           EI

RST #10

ERROR       LD C,#84                ;сюда попадаем при ошибке и выходим в оболочку с сообщением об ошибке

RST #10

 

READ           EQU #5E03          ;адрес процедуры чтения с винчестера (кусок загрузчика, который находится в

                                              ;ПЗУ TR-DOS

;Вход: HL - куда читать, DE - номер первого блока файла, B - сколько блоков читать

;Выход: флаг C - ошибка чтения

BUFER         EQU #6000          ;адрес буфера, где находится 0-й блок устройства

SYSP           DEFS #0200        ;тут должны находиться системные переменные

uni_Chic.sys

Файл uni_Chic.sys является файлом загрузчика системы iS-DOS Chic с винчестера. Этот файл загружается в память компьютера с адреса #6100 загрузчиком из ПЗУ TR-DOS и запускается на выполнение. Программа uni_Clas.sys использует процедуру загрузчика по адресу #5E03 для чтения файла системы в память. В теле программы располагаются системные переменные TR-DOS и BASIC. Файл почти полностью аналогичен программе uni_Clas.sys.

Дизассемблер программы:

 

ORG #6100

 

JR BEGIN                           ;переход на начало программы

 

DEFW SYSP-#6100            ;по адресу +2 от начала программы лежит смещение начала

                                        ;системных переменных от начала программы

 

BEGIN        LD SP,#5DC0                      ;устанавливаем стек

LD IY,#5C3A                       ;стандартное значение IY

LD A,#10                            ;включаем банк 0 расширенной памяти

LD BC,#7FFD

OUT (C),A

LD B,#1F                            ;записываем #11 в #1FFD (для Profi - LD B,#DF)

LD A,#11                            ;т.е. подставляем банк 0 вместо ПЗУ, а банк 8 в адреса #C000-#FFFF

 

LD DE,(BUFER+#40+17)     ;адрес загрузки файла is_dos.rom

LD A,E                               ;проверка на 0

OR D

RET Z

 

LD HL,0                            ;загружаем файл is_dos.rom в адрес 0

LD B,#40

CALL READ

RET C

 

LD HL,(BUFER+#20+12)      ;адрес загрузки файла is_dos.sys (берём из описателя is_dos.sys в 0-м

LD A,L                                ;блоке

OR H                                  ;проверка его на 0

RET Z                              ;если равен 0, то что-то не так, поэтому возврат обратно

LD DE,(BUFER+#20+17)     ;номер начального блока файла is_dos.sys

LD A,E                               ;проверка на 0

OR D

RET Z

LD A,H                               ;за длину is_dos.sys в блоках берём разницу между концом памяти и

CPL                                    ;адресом загрузки, т.е. инвертируем старший байт адреса загрузки

INC A                                 ;и прибавляем 1

LD B,A                               ;получаем длину файла в блоках

CALL READ                        ;читаем файл системы в память

RET C                              ;если была ошибка чтения, то выход

 

LD A,(BUFER+#20+22)        ;вектор прерывания хранится в описателе по смещению +22

LD I,A

 

LD C,#10                            ;читаем вектор конфигурации ядра

RST #10

EXX

LD BC,#FFFA                     ;по смещению -6 лежит размер электронного диска в блоках

ADD HL,BC

LD A,(HL)                           ;читаем размер электронного диска

 

LD C,0                                ;создаём электронный диск

RST #10

JR C,ERROR                      ;теперь мы уже в системе, поэтому можно по ошибке выходить прямо

                                        ;в систему

 

LD C,#45                            ;читаем адрес внутреннего буфера командной строки

RST #10

EXX

DEC HL                            ;по смещению -3 и -2 лежит дата

DEC HL

LD DE,(BUFER+30)            ;берём дату из 0-го блока устройства

LD (HL),D                           ;и устанавливаем её в систему

DEC HL

LD (HL),E

 

LD A,#53               ;устройство "S"

LD C,#4A            ;преобразуем логическое имя устройства в физическое

RST #10

LD B,A                  ;получаем № канала блочного устройства

LD C,#1C            ;переключаемся на устройство "S"

RST #10

JR C,ERROR

LD C,#20               ;открываем устройство и главный каталог

RST #10

JR C,ERROR

 

LD HL,SYSP                       ;устанавливаем системные переменные

LD DE,#5C00

LD BC,#0200

LDIR

 

LD C,#93               ;$shexe - выходит в оболочку с запуском autoexec.bat, т.е. управления он уже не

                          ;отдаст

IM 2                      ;перед выходом включаем IM2

JR NC,RUN           ;если не было ошибок то выполнение рестарта

LD C,#84               ;выход в оболочку с сообщением об ошибке

RUN           EI

RST #10

ERROR       LD C,#84                ;сюда попадаем при ошибке и выходим в оболочку с сообщением об ошибке

RST #10

 

READ           EQU #5E03          ;адрес процедуры чтения с винчестера (кусок загрузчика, который находится в

                                             ;ПЗУ TR-DOS

;Вход: HL - куда читать, DE - номер первого блока файла, B - сколько блоков читать

;Выход: флаг C - ошибка чтения

BUFER         EQU #6000          ;адрес буфера, где находится 0-й блок устройства

SYSP           DEFS #0200        ;тут должны находиться системные переменные

HDD_boot

Программа HDD_boot является загрузчиком системы, который должен находиться в ПЗУ TR-DOS, откуда может вызываться для запуска системы с винчестера. Загрузчик копируется из ПЗУ в память по адресу #5E00 и запускается на выполнение по этому же адресу. В процессе работы загрузчик сканирует на винчестере сектор 0, головку 0 треки от 0 до 255 в поисках признака "KAY" по смещению #7D от начала блока. После этих трёх букв по смещению #80 находится описатель файла uni_boot.sys, который загружается в память и запускается на выполнение, откуда уже непосредственно запускается система iS-DOS.

Дизассемблер загрузчика:

 

ORG #5E00

 

;Перед запуском загрузчика необходимо запретить прерывания!!!

 

;2 точки входа в загрузчик:

;#5E00 - сканирование винчестера в поисках загрузчика uni_boot.sys

;#5E03 - процедура чтения с винчестера

 

JP SCAN        ;#5E00

JP READ       ;#5E03

 

;тут находится кусок заголовка драйвера винчестера, где расположены параметры самого винчестера

;изначально тут ничего нет. После выполнения сканирования винчестера сюда будет перенесена информация

;о винчестере

 

HEAD           DEFB 0           ;количество головок

SEC              DEFB 0           ;количество секторов

DEFW 0         ;не используется

HS2            DEFW 0        ;HEAD·SEC·2

DEFW 0         ;не используется

TRK            DEFW 0        ;начальный трек текущего устройства

SDH             DEFB #A0       ;маска для регистра SDH винчестера (#B0 - для чтения с устройства Slave)

 

;процедура RESET осуществляет программный сброс винчестера и его рекалибровку

 

IN A,(#F0)                ;назначение этого куска программы неясно, т.к. его не вызывает ни одна

CP #50                    ;процедура. Скорее всего, этот кусок кода был началом процедуры RESET.

RET Z

 

RESET       LD A,(SDH)            ;маска SDH

OUT (#D0),A          ;заносим в SDH-регистр

LD A,%00001100   ;устанавливаем бит SRST - бит программного сброса накопителя

OUT (#C8),A          ;заносим в Fixed disk register

LD B,0                    ;делаем паузу

DJNZ $

LD A,%00001000   ;сбрасываем бит SRST

OUT (#C8),A

RES1          IN A,(#F0)               ;проверка готовности накопителя

RLCA                      ;проверяем бит BSY

JR C,RES1

LD A,#10                 ;команда Recalibrate

OUT (#F0),A

RES2          IN A,(#F0)               ;ждём готовности после рекалибровки

BIT 7,A

JR NZ,RES2

CP #50                    ;проверка на нормальное завершение

RET Z

JR RESET               ;если что-то было не так, то повторяем процедуру сброса

 

;процедура READ осуществляет чтение блоков с винчестера

;Вход:      HL - куда читать блоки

                DE - с какого блока читать

                B - сколько блоков читать

                в TRK - номер трека, от которого будет вестись отсчёт

Выход:       C - ошибка

                NC - ОК

 

READ           CALL CALC          ;вычисляем номер трека и головки

JR C,READ3         ;если читаем один блок с начала сектора

READ1         CALL C_SEC       ;высчитываем, сколько секторов на треке надо прочитать и откуда читать

PUSH BC              ;количество секторов за пределами трека, которые ещё надо прочитать

CALL MLTRD        ;читаем на текущем треке нужные сектора

POP BC

RET C                 ;по ошибке выходим

LD A,B                  ;если больше не надо читать сектора

OR A

JR Z,READ2         ;то переход

CALL SET             ;переход на следующую головку и трек

JR READ1            ;читаем снова

 

READ2         CALL CHECK         ;проверяем, не надо ли дочитывать ещё полсектора

RET Z                 ;не надо

 

;дочитываем полсектора

 

READ3         LD A,E                ;номер текущего сектора

INC A                    ;в HDD нумерация секторов начинается с 1

OUT (#70),A        ;заносим в регистр сектора

LD A,1                  ;читаем 1 сектор

OUT (#50),A        ;Sector counter

LD A,#21               ;команда Read sector(s)

OUT (#F0),A        ;Command register

CALL READY        ;ожидаем готовности накопителя

RET C                 ;если была ошибка

LD B,0                  ;256 байт

READ4         LD C,#10                ;читаем

INI

INC C

INI

JR NZ,READ4

READ5         IN A,(#10)             ;остальные 256 байт, которые нам не надо, читаем "вхолостую"

IN A,(#F0)

BIT 3,A                  ;пока DRQ не сбросится в 0

JR NZ,READ5

RRCA                 ;бит ERR загоняем в флаг C

RET                      ;выходим

 

;процедура CALC выполняет подсчёт номера трека, номера головки.

Вход:       DE - номер блока, с которого надо читать

              B - сколько блоков надо читать

Выход   флаг C - читаем 1 блок (256 байт) с начала сектора

                           E - номер сектора винчестера, с которого надо начать чтение

                           A - то же самое

              флаг NC - A≠#FF   1) читаем чётное количество блоков с начала сектора

                               2) читаем нечётное количество блоков со второй половины сектора

                               E - номер блока (256 байт) с начала дорожки, с которого надо читать

                               A - номер сектора винчестера, с которого надо начать чтение

                               в этом случае B - реальное количество целых секторов, которое надо почитать

                             A=#FF    1) читаем нечётное количество блоков с середины сектора

                                           2) читаем чётное количество блоков с начала сектора

            E - номер блока (256 байт) с начала дорожки, с которого надо читать

   в этом случае B - количество секторов, которые надо прочитать (без последней половинки)

HL - сохраняется

 

CALC          PUSH DE            ;нам надо номер блока

EXX                      ;остальное сохраняем

POP DE

LD HL,(HS2)        ;Block/(HEAD·SEC·2)=номер трека

EX DE,HL

XOR A

LD B,A

LD C,A

CALC1        SBC HL,DE       ;делим

INC BC

JR NC,CALC1

DEC BC              ;BC - номер трека

ADD HL,DE        ;HL - остаток от деления

LD A,(SEC)

RLCA

LD E,A

XOR A

LD D,A               ;DE - количество секторов на дорожку

CALC2        SBC HL,DE       ;остаток делим на DE

INC A

JR NC,CALC2

DEC A                ;номер головки

ADD HL,DE

EX DE,HL           ;DE - остаток от деления

LD D,A               ;номер головки

LD HL,(TRK)

ADD HL,BC        ;суммируем с начальным треком текущего устройства

LD A,E               ;номер блока (256 байт) от начала дорожки

EX AF,AF'

CALL SET1         ;заносим номер дорожки и головки в регистры винчестера

EX AF,AF'

SRL B              ;проверка B на 1 (а заодно и делим на 2 - получаем сколько надо прочитать

                        ;целых секторов на винчестере

LD E,A

JR Z,CALC7        ;если надо прочитать 1 блок, то переход

JR C,CALC6     ;если надо прочитать нечётное количество блоков

RRCA               ;делим номер блока на 2 (проверка на чётность)

JR C,CALC4     ;если номер блока был нечётным, т.е. читаем со второй половины сектора

CALC3        LD A,#FF           ;тот случай, когда читаем чётное количество блоков с начала сектора

CALC4        LD (CHECK+1),A    ;установка признака чтения

CALC5        OR A                 ;установка NC

RET

 

;обработка случая, когда читаем нечётное количество блоков

 

CALC6        RRCA                  ;делим номер блока от начала дорожки на 2 (проверка на чётность)

JR NC,CALC4   ;если читаем нечётное количество блоков от начала сектора

INC B                  ;тут получаем целое количество секторов, которое надо прочитать

JR CALC3           ;установка признака #FF

 

;если читаем только один блок

 

CALC7        INC B                ;после деления у нас B=0, поэтому увеличиваем B до 1 сектора

RRCA               ;проверка на чётность читаемого блока (заодно делим номер блока на 2)

JR C,CALC3     ;читаем с середины сектора

 

;тут читаем 1 блок с начала сектора

 

LD E,A               ;номер сектора, с которого читаем

SCF                    ;установка признака того, что читаем 1 блок с начала сектора

RET


 

;процедура C_SEC определяет, откуда читать очередной блок - с начала сектора или со второй его половины. Также процедура определяет, сколько секторов нужно прочитать до конца трека.

;Вход:      E - номер блока длиной 256 байт (с начала трека), откуда надо начать чтение

                B - сколько секторов (512 байт) надо прочитать

;Выход       C - начинать чтение со второй половины сектора

                NC - начинать чтение с начала сектора

                A - с какого сектора начинать чтение

                E - сколько секторов до конца дорожки надо прочитать

                B - сколько секторов останется прочитать после этого трека

;процедура, исходя из номера блока, с которого надо начинать чтение и количества секторов для чтения определяет, сколько секторов до конца дорожки можно прочитать и сколько секторов останется ещё прочитать после этой дорожки. Дело в том, что файл читается блоками по несколько секторов (в пределах дорожки).

 

C_SEC       SRL E                  ;делим номер блока на 2 - получаем номер сектора, с которого надо читать

LD A,E                  ;если блок чётный (начало сектора), то получаем NC, если блок нечётный

                          ;(вторая половина сектора), то получаем C

PUSH AF            ;сохраняем флаговый регистр

LD A,(SEC)           ;количество секторов на дорожку

SUB E                  ;сколько секторов еще осталось на треке

LD E,A

LD A,B                 ;сколько секторов надо прочитать

SUB E                  ;сколько секторов надо прочитать за пределами трека

JR NC,C_SEC1   ;если читать секторов надо больше, чем осталось на треке

 

;тот случай, когда все сектора, которые надо прочитать, находятся на одном треке

 

XOR A                  ;за пределами трека ничего не надо читать (0 сектров)

LD E,B                  ;сколько надо прочитать секторов

C_SEC1      LD B,A                ;сколько секторов надо прочитать за пределами трека

POP AF                ;восстанавливаем флаг C

RET

 

;процедура SET осуществляет переход на следующий трек и номер головки (в том случае, если все сектора на треке уже прочитаны)

;Вход:      D' - текущий номер головки

                HL' - номер трека

 

SET            LD E,0            ;через передаётся номер блока на винчестере, а так как на треке все блоки уже

;прочитаны, то переходим на новый трек, а нумерация блоков на треке начинается

;с нуля

EXX                 ;в альтернативном наборе хранятся номер трека и номер головки

INC D               ;следующая головка

LD A,(HEAD)    ;количество головок винчестера

CP D                ;все головки на треке?

JR NZ,SET1      ;если не все, то устанавливаем новый номер головки, ничего больше не меняя

LD D,0             ;головка 0

INC HL              ;увеличиваем номер трека на 1

SET1          IN A,(#F0)        ;ожидаем готовности винчестера

CP #50

JR NZ,SET1

LD A,L             ;заносим номер трека в регистры винчестера

OUT (#90),A    ;регистр Cylinder low

LD A,H

OUT (#B0),A   ;регистр Cyinder high

LD A,(SDH)      ;маска SDH-регистра

OR D                ;накладываем на номер головки

OUT (#D0),A   ;заносим в SDH-регистр

EXX                 ;все параметры устанавливаем в альтернативный набор

RET


 

;Процедура CHECK проверяет, надо ли в конце файла читать только полсектора, а вторую половину пропустить.

;Выход:    Z - не надо ничего дочитывать

                NZ - надо дочитать ещё полсектора, при этом процедура сама переходит на тот сектор, половину которого надо дочитать.

 

CHECK         LD A,0               ;сюда записывается признак того, надо ли дочитывать полсектора

CP #FF               ;если было #FF, от не надо

RET Z               ;если ничего не надо дочитывать, то выход с флагом Z

IN A,(#70)            ;текущий сектор

LD E,A

LD A,(SEC)         ;количество секторов на трек

CP E                  ;текущий сектор является последним?

JR Z,SET          ;если да, то переходим на следующий сектор с помощью программы SET

RET                    ;выход с флагом NZ

 

;процедура MLTRD загружает с винчестера E секторов.

;Вход:        A - с какого сектора грузить (нумерация начинается с 0)

                  E - сколько секторов грузить (если у последнего сектора надо читать только половинку, то длина

даётся без последнего сектора)

                  HL - куда грузить сектора

                  NC - начинать с начала сектора

                  C - начинать со второй половины сектора

;Выход:      C - ошибка чтения с винчестера

;процедура грузит сектора только на текущей дорожке

 

MLTRD         PUSH AF             ;сохраняем флаг C

INC A                    ;увеличиваем номер сектора на 1, потому что у HDD сектора нумеруются с 1

OUT (#70),A        ;заносим номер сектора в Sector number

POP AF                ;восстанавливаем флаг C

LD A,E                  ;сколько секторов надо читать

OUT (#50),A        ;заносим в Sector count

LD A,#21               ;команда Read sector(s)

OUT (#F0),A        ;заносим в Command register

JR NC,MLT3        ;если начинаем чтение с начала сектора, то переход на чтение 512 байт

 

;Тут надо читать только вторую половину сектора, поэтому первые 256 байт сектора читаем "вхолостую"

 

CALL READY        ;ожидаем готовности накопителя

RET C                 ;по ошибке отваливаем с флагом C

LD B,#80               ;128 раз будем читать порт #10 - это равнозначно прочтению 256 байт

                          ;по чтению из порта #10 передаются два байта - один непосредственно в порт #10,

                         ;а второй - при чтении из порта #11, но его можно и не читать

MLT1          IN A,(#10)             ;читаем 128 раз порт #10

DJNZ MLT1

MLT2          LD C,#10                ;а тут читаем 256 байт второй половинки сектора

INI                         ;IN (#10)

INC C

INI                         ;IN (#11)

JR NZ,MLT2        ;если 512 байт не посчитаны, то читаем ещё

IN A,(#50)              ;все сектора почитали?

OR A                    ;если да, то выход

RET Z

 

;тут читаем весь сектор целиком

 

MLT3          CALL READY         ;ожидаем готовность накопителя

RET C                 ;по ошибке отваливаем

LD C,#10

MLT4          INI                       ;читаем

INC C

INI

DEC C

IN A,(#F0)              ;читаем до тех пор, пока винчестер не снимет сигнал DRQ, что означает, что он

BIT 3,A                  ;передал все данные

JR NZ,MLT4

IN A,(#50)              ;ещё надо читать сектора?

OR A

JR NZ,MLT3        ;если надо, то читаем снова

RET

 

;процедура READY ожидает готовности винчестера. В случае ошибки возвращается с флагом C и кодом ошибки -7 в регистре A

 

READY         IN A,(#F0)               ;читаем Status register

BIT 7,A                    ;проверка на BSY=0

JR NZ,READY         ;иначе ждём

BIT 3,A                    ;поверка на DRQ=1

JR Z,READY           ;иначе ждём

RRCA                   ;проверка на ERR=0

RET NC                 ;если так, то выход с NC

CALL RESET           ;если были ошибки, то пытаемся сбросить винчестер

LD A,7                    ;код ошибки - 7

SCF                        ;установка флага C

RET

 

;процедура SCAN осуществляет сканирование треков винчестера с номерами [0-255] в поисках загрузчика uni_boot.sys

;в случае обнаружения такового он загружается в память и запускается на выполнение, иначе сканирование продолжается. В случае завершения сканирования (все треки просканированы) процедура "зависает"

 

SCAN           LD SP,#5DC0

CALL CALC5              ;назначение этого вызова непонятно

SCAN1       LD A,1                     ;в процессе работы меняется цвет бордюра, начинаем с синего (просто как правило, загрузчик находится на системном устройстве, а оно в свою очередь - на треке 0 винчестера. В данном случае трек 0 будет найден первым, а система iS-DOS имеет синий цвет оболочки. Так что сразу же установится синий цвет при загрузке системы)

OUT (#FE),A

CALL ANALYS           ;загрузка трека в память и его анализ

 

;процедура ANALYS в случае обнаружения на треке загрузчика uni_boot.sys запускает его на выполнение, поэтому

;то факт, что она отдала управление обратно, говорит о том, что или загрузчик отсутствует или была какая-либо

;ошибка, поэтому продолжаем сканирование со следующего трека винчестера

 

LD HL,SCAN1+1        ;меняем цвет бордюра

INC (HL)

LD HL,TRK              ;номер трека для сканирования увеличиваем на 1

INC (HL)

JR NZ,SCAN1          ;если не было переполнения больше 255, то сканируем снова

HALT                         ;255 треков просканировано и ничего не найдено, поэтому "виснем"

 

;процедура ANALYS загружает трек с номером в TRK в память и производит его анализ на наличие на треке

;загрузчика uni_boot.sys. Если таковой имеется, то он запускается на выполнение

 

ANALYS     LD HL,BUFER          ;грузим в буфер 0-й блок на треке

LD B,1

LD DE,0

CALL READ

RET C                     ;была ошибка при загрузке, поэтому отваливаем обратно

 

LD HL,(BUFER+#7D)  ;проверка на наличие слова "KAY" по смещению #7D

LD DE,#414B             ;"KA"

LD A,(BUFER+#7F)

XOR #59                    ;"Y"

RET NZ                   ;последняя буква не "Y", поэтому выход

SBC HL,DE

RET NZ                   ;первые две буквы не совпали, поэтому выход


 

;раз слово 'KAY" обнаружено, то можно считать, что этот трек подходит нам.

;теперь из буфера надо взять информацию о конфигурации винчестера, которая была записана туда программой

;uni_con.com и перенести ее в загрузчик. Это надо для дальнейшей работы процедуры READ для загрузки файлов. Все значения проверяются на 0. Это сделано потому, что может быть это не тот блок, который нам надо. Вдруг на устройстве есть ещё дин такой блок с текстом "KAY" по смещению #7D, но без всех остальных данных. В этом случае есть вероятность, что по одному из нужных адресов будет 0. Вот это и проверяем.

 

LD HL,(BUFER+97)    ;данные о количестве головок винчестера хранятся в буфере

LD A,L                       ;прочитали информацию о HEAD и SEC

OR H                         ;проверка их значения на 0

RET Z

LD (HEAD),HL           ;заносим в сам загрузчик

LD HL,(BUFER+115)  ;HEAD·SEC·2

LD A,L                       ;проверка на 0

OR H

RET Z

LD (HS2),HL            ;сохраняем в загрузчике

 

;Теперь берём всю нужную информацию о файле uni_boot.sys и загружаем его в память, после чего запускаем на

;выполнение. Вся информация хранится в описателе файла uni_boot.sys по смещению #80 от начала буфера.

 

LD DE,(BUFER+#80+17)   ;номер блока, с которого будем грузить uni_boot.sys

LD A,E                             ;проверка на 0

OR D

RET Z

LD HL,(BUFER+#80+12)    ;адрес загрузки

LD A,L

OR H

RET Z

LD A,(BUFER+#80+15)     ;старший байт длины файла

OR A

RET Z

INC A                               ;увеличиваем на 1 - получаем длину в блоках

LD B,A

PUSH HL                       ;сохраняем стартовый адрес файла, чтобы потом запустить его на

;выполнение

CALL READ                     ;читаем файл uni_boot.sys

RET NC                          ;если не было ошибок, то делаем переход на начало файла

POP HL                         ;возвращаем на место HL, потому что была ошибка

RET                                 ;выход

 

BUFER         EQU #6000




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Учебник - "Ветви персика": Многотомное издание индийских монахов, которые пытаются научить духовной и плотской любви людей (продолжение).
Почти невинная история
B.B.S. Новости - О работе B.B.S.'ок.
Игры - Диззи с Бодуна - соЦиальная мини-новелла.
Четыре килобайта - между толкинистами и спектрумистами есть много общего...

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