10.3. Загрузка в верхнюю часть памяти

Применение прерывания DOS INT 27H является предпочтительным способом включения в систему постоянных функций типа драйверов устройств. Это - удобный способ сделать программу постоянной частью системы. Пользователь может включить программу в файл AUTOEXEC.BAT, тогда она будет загружаться автоматически. Такую автоматическую загрузку можно использовать, когда в вашей системе имеется специальное устройство ввода-вывода. DOS будет загружать драйвер этого устройства при каждой загрузке системы. Вы можете даже предпочесть собственную версию процедуры буферизации печати, поскольку вы хотите, чтобы она постоянно загружалась в систему.

Однако выход в DOS с фиксацией программы в ОЗУ работает не всегда. Фирма IBM предлагает три операционные системы для персональных ЭВМ: DOS, которая и рассматривается в данной книге, CP/M-86 фирмы Digital Research и UCSD p-System фирмы SofTech Microsystems. Кроме указанных систем, предлагаемых фирмой IBM, несколько независимых разработчиков распространяют свои системы. Чтобы создать драйвер устройства, который работал бы со всеми этими системами, нужно использовать нечто отличного от метода, применяемого для DOS.

Допустим, у вас имеется специализированное устройство печати, которое вы хотите продавать как приспособление к IBM PC. Поскольку ваш принтер - отноительно дешевое устройство, для него потребуется больше управления со стороны BIOS, чем для принтера фирмы IBM. Вы конструируете принтер и устройство подсоединения и пишете BIOS программу для поддержки его работы. Если вы пользуетесь прерыванием INT 27H, то ваше устройство можно передавать только пользователям, имеющим на своей персональной ЭВМ DOS. Необходим такой способ загрузки драйвера устройства, который бы работал во всех операционных системах.

Способ загрузки, годный не только для DOS, называется загрузкой в верхние адреса оперативной памяти. При этом управление системой перехватывается непосредственно после процедуры самоконтроля при включении питания. Это может быть реализовано при помощи специальной дискеты загрузки. Программа будет записана на дискету, которая вставляется в дисковод перед включением питания. Подпрограмма загрузки, входящая в BIOS, загружает драйвер устройства с дискеты в верхнюю часть оперативной памяти. Затем можно изменить размер области данных сообщаемый BIOS в соответствии с имеющимся объемом оперативной памяти. При загрузке программы в верхние адреса размер доступной оперативной памяти уменьшается. Если после этого загрузить стандартную операционную систему, будет восстановлено нормальное функционирование ЭВМ. Все операционные системы фирмы IBM учитывают объем памяти BIOS при определении границ оперативной памяти. Указанные системы не затрагивают программ, загруженных в верхние адреса. Если система удовлетворяет указанным требованиям, то можно пользоваться загрузкой в верхние адреса оперативной памяти.

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


Microsoft (R) Macro Assembler Version 5.00                  1/1/80 04:03:56
Фиг. 10.2(а) Загрузчик для создания псевдо-диска                  Page  1-1
PAGE  ,132
                         TITLE    Фиг. 10.2(а) Загрузчик для создания псевдо-диска

0000                     NEW_DISK SEGMENT
0000                     DISK_BIOS     LABEL         FAR
0003                              ORG     3
0003                     OLD_VECTOR    LABEL         WORD
0003                     NEW_DISK ENDS

0000                     ABS0     SEGMENT   AT 0
004C                              ORG       13H*4
004C                     DISK_VECTOR        LABEL WORD
0410                              ORG       410H
0410                     EQUIPMENT          LABEL WORD
0413                              ORG       413H
0413                     MEMORY_SIZE        LABEL WORD
        = 00A0           DISK_SIZE          EQU    160
7C00                              ORG       7C00H  ; Место,в которое заносится загрузчик ДОС
7C00                     BOOT_RECORD        LABEL FAR
7C00                     ABS0     ENDS

0000                     CODE     SEGMENT

                                  ASSUME    CS:CODE,DS:ABS0
7C00                              ORG       7C00H
7C00    8C C8                     MOV       AX,CS
7C02    8E D8                     MOV       DS,AX
7C04    8E C0                     MOV       ES,AX
7C06    8D 36 7C00 R >            LEA       SI,BOOT_RECORD
7C0A    8D 3E 7A00 R >            LEA       DI,BOOT_RECORD-200H 
                                                          ; Место,на которое переносится
7C0E    B9 0200  >                MOV       CX,512        ; загрузчик ДОС
7C11    F3/ A4                    REP       MOVSB         ; Перенесение загрузчика
7C13    E9 7A16 R >               JMP       NEXT_LOCATION-200H
7C16                     NEXT_LOCATION:
7C16    83 06 0410 R 40           ADD       EQUIPMENT,40H ; Увеличение числа дисководов
7C1B    A1 0413 R >               MOV       AX,MEMORY_SIZE
7C1E    2D 00A0  >                SUB       AX,DISK_SIZE
7C21    A3 0413 R >               MOV       MEMORY_SIZE,AX ; Уменьшение доступной ДОС памяти,
7C24    B1 06                     MOV       CL,6          ; необходимое для размещения 
                                                          ; псевдо-диска
7C26    D3 E0                     SHL       AX,CL         ; Умножение на 1024/16
7C28    8E C0                     MOV       ES,AX         ; Сегментная часть адреса нового диска
7C2A    B8 0201  >                MOV       AX,201H       ; Чтение сектора в эту область
7C2D    BB 0000  >                MOV       BX,0
7C30    B9 0002  >                MOV       CX,2
7C33    BA 0000  >                MOV       DX,0
7C36    CD 13                     INT       13H
7C38    72 1A                     JC        BOOT_ERROR

                                  ASSUME    ES:NEW_DISK
7C3A    A1 004C R >               MOV       AX,DISK_VECTOR
7C3D    26: A3 0003 R >           MOV       OLD_VECTOR,AX
7C41    A1 004E R >               MOV       AX,DISK_VECTOR+2 ; Сохранение старого вектора 
7C44    26: A3 0005 R >           MOV       OLD_VECTOR+2,AX  ; прерывания 13h
7C48    C7 06 004C R 0000         MOV       DISK_VECTOR,0    ; Установка вектора прерывания 17h
7C4E    8C 06 004E R >            MOV       DISK_VECTOR+2,ES ; на новое место
7C52    EB 07                     JMP       SHORT REBOOT  ; Чтение загрузчика с другой дискеты
7C54                     BOOT_ERROR:
7C54    8D 36 7A93 R >            LEA       SI,ERROR_MSG-200H  ; Печать сообщения об ошибке
7C58    E8 7C81 R >               CALL      PRINT_MSG
7C5B                     REBOOT:
7C5B    8D 36 7AA5 R >            LEA       SI,BOOT_MSG-200H ; Печать сообщения о загрузке ДОС
7C5F    E8 7C81 R >               CALL      PRINT_MSG
7C62                     WAIT_BOOT:
7C62    B4 00                     MOV       AH,0
7C64    CD 16                     INT       16H           ; Ожидание ввода с клавиатуры
7C66    3C 20                     CMP       AL,' '        ; Ожидается ввод пробела
7C68    75 F8                     JNE       WAIT_BOOT
7C6A    B8 0201  >                MOV       AX,201H
7C6D    BB 7C00  >                MOV       BX,7C00H
7C70    B9 0001  >                MOV       CX,1
7C73    BA 0000  >                MOV       DX,0
7C76    8E C2                     MOV       ES,DX         ; Ввод на стандартное место загрузчика
7C78    CD 13                     INT       13H
7C7A    72 D8                     JC        BOOT_ERROR
7C7C    EA 7C00 ---- R >          JMP       BOOT_RECORD
7C81                     PRINT_MSG          PROC    NEAR
7C81    2E: 8A 04 >               MOV       AL,CS:[SI]    ; Взять символ для печати
7C84    46                        INC       SI
7C85    3C 24                     CMP       AL,'$'        ; Проверка на символ конца вывода
7C87    75 01                     JNE       OUTPUT
7C89    C3                        RET
7C8A                     OUTPUT:
7C8A    B4 0E                     MOV       AH,14
7C8C    BB 0000  >                MOV       BX,0
7C8F    CD 10                     INT       10H           ; Вывод на дисплей через BIOS
7C91    EB EE                     JMP       PRINT_MSG
7C93    8E E8 A8 A1 AA A0 20      ERROR_MSG DB 'Ошибка загрузки',13,10,'$'
        A7 A0 A3 E0 E3 A7 AA
        A8 0D 0A 24
7CA5    82 E1 E2 A0 A2 EC E2      BOOT_MSG  DB 'Вставьте новую дискету с ДОС',13,10
        A5 20 AD AE A2 E3 EE
        20 A4 A8 E1 AA A5 E2
        E3 20 E1 20 84 8E 91
        0D 0A
7CC3    A8 20 AD A0 A6 AC A8 >    DB      'и нажмите на пробел',10,13,'$'
        E2 A5 20 AD A0 20 AF
        E0 AE A1 A5 AB 0A 0D
        24
7CD9                     PRINT_MSG  ENDP
7CD9                     CODE     ENDS
                         END

                                  Фиг. 10.2(а) Загрузчик для создания псевдо-диска


Microsoft (R) Macro Assembler Version 5.00                  1/1/80 04:03:56
Фиг. 10.2(б) Программа обслуживания псевдо-диска                  Page  1-1
PAGE  ,132
                         TITLE    Фиг. 10.2(б) Программа обслуживания псевдо-диска

0000                     CODE     SEGMENT

                                  ASSUME    CS:CODE
                         ;--------------------------------------------
                         ; Эта программа находится в секторе 1 трека 0
                         ; псевдо-диска. Чтение и запись на устройство 2
                         ; переадресуется на эту программу
                         ;--------------------------------------------
0000                     DISK     PROC      FAR
        = 0140           DISK_SIZE          EQU    320    ; Размер псевдо-диска в сектрах
0000    EB 05 90 >                JMP       START_BIOS
0003    ????????         ORIGINAL_VECTOR    DD  ?
0007                          
                         START_BIOS:
0007    80 FA 02 >                CMP       DL, 2         ; Программа обрабатывает только 
000A    74 05                     JE        L1            ; обращения к устройству (дисководу) 2
000C                     OLD_BIOS:
000C    2E: FF 2E 0003 R          JMP       ORIGINAL_VECTOR ; Переход на стандартную программу
0011                     L1:
0011    3C 01                     CMP       AL, 1
0013    76 F7                     JBE       OLD_BIOS
0015    80 FC 04 >                CMP       AH, 4
0018    72 06                     JB        READ_WRITE    ; Обрабатываются только команду 
                                                          ; чтения и записи
001A                     OK_RETURN:
001A    B4 00                     MOV       AH, 0         ; Код возврата - 0
001C    F8                        CLC                     ; Сброс C-флага - нет ошибки
001D    CA 0002  >                RET       2
0020                     READ_WRITE:
0020    53                        PUSH      BX            ; Сохранение регистров
0021    51                        PUSH      CX
0022    52                        PUSH      DX
0023    56                        PUSH      SI
0024    57                        PUSH      DI
0025    1E                        PUSH      DS
0026    06                        PUSH      ES
                         ;-----   Вычисление адреса расположения требуемой записи в псевдо-диске
0027    50                        PUSH      AX            ; Сохранение кода требуемой операции
0028    B0 08                     MOV       AL, 8         ; Число секторов на треке
002A    F6 E5                     MUL       CH
002C    B5 00                     MOV       CH, 0
002E    03 C1                     ADD       AX, CX        ; Прибавление номера сектора
0030    80 FE 00 >                CMP       DH, 0         ; Проверка на номера стороны
0033    74 03                     JE        HEAD_0
0035    05 0140  >                ADD       AX, 320       ; Переключение на второю сторону
0038                          
HEAD_0:
0038    48                        DEC       AX
0039    3D 0140  >                CMP       AX, DISK_SIZE ; Вычисленное значение правильно?
003C    76 0E                     JBE       DISK_OK
003E                     RECORD_NOT_FOUND:
003E    58                        POP       AX            ; Восстановление регистров
003F    07                        POP       ES
0040    1F                        POP       DS
0041    5F                        POP       DI
0042    5E                        POP       SI
0043    5A                        POP       DX
0044    59                        POP       CX
0045    5B                        POP       BX
0046    B4 04                     MOV       AH, 4         ; Ошибка:
сектор не найден
0048    F9                        STC
0049    CA 0002  >                RET       2             ; Возврат с указанием об ошибке
004C                     DISK_OK:
004C    B1 05                     MOV       CL, 5
004E    D3 E0                     SHL       AX, CL        ; Определение расположения данных на
0050    8C C9                     MOV       CX, CS        ; псевдо-диске
0052    03 C8                     ADD       CX, AX        ; В регистре CX сегментная часть 
                                                          ; адреса данных на диске
0054    51                        PUSH      CX
0055    8B D3                     MOV       DX, BX        ; В регистре DX адрес передачи
0057    B1 04                     MOV       CL, 4
0059    D3 EA                     SHR       DX, CL
005B    8C C1                     MOV       CX, ES
005D    03 D1                     ADD       DX, CX        ; В регистре DX сегментная часть
                                                          ; адреса передаваемых данных
005F    59                        POP       CX
0060    83 E3 0F >                AND       BX, 0Fh       ; Выделение младших 4 разрядов
0063    58                        POP       AX            ; Восстановление код требуемой
                                                          ; операции
0064    80 FC 02 >                CMP       AH, 2
0067    74 11                     JE        READ_OPN
0069                     WRITE_OPN:
0069    8C CE                     MOV       SI, CS
006B    3B CE                     CMP       CX, SI        ; Проверка на запись поверх 
                                                          ; этой программы
006D    74 1B                     JE        ALL_DONE
006F    8E C1                     MOV       ES, CX
0071    BF 0000  >                MOV       DI, 0
0074    8E DA                     MOV       DS, DX
0076    8B F3                     MOV       SI, BX        ; Установка параметров передачи
0078    EB 09                     JMP       SHORT DO_MOVE
007A                     READ_OPN:
007A    8E D9                     MOV       DS, CX
007C    BE 0000  >                MOV       SI, 0
007F    8E C2                     MOV       ES, DX
0081    8B FB                     MOV       DI, BX
0083                     DO_MOVE:
0083    8A E8                     MOV       CH, AL        ; Число слов в секторе
0085    B1 00                     MOV       CL, 0
0087    FC                        CLD
0088    F3/ A5                    REP       MOVSW         ; Пересылка данных
008A                     ALL_DONE:
008A    07                        POP       ES            ; Восстановление регистров
008B    1F                        POP       DS
008C    5F                        POP       DI
008D    5E                        POP       SI
008E    5A                        POP       DX
008F    59                        POP       CX
0090    5B                        POP       BX
0091    B4 00                     MOV       AH, 0         ; Нормальное окончание
0093    F8                        CLC
0094    CA 0002  >                RET       2
0097                     DISK     ENDP
0097                     CODE     ENDS
                         END

                               (b) Программа драйвера виртуального диска.

Драйвер устройства, приведенный в рассматриваемом примере, реализует модель диска в оперативной памяти. Мы возьмем 160К памяти системы и будем исполльзовать ее не как оперативную память, а как дискету. Мы выбрали именно 160К потому, что это минимальный объем дискеты фирмы IBM. Очевидно, при большем объеме оперативной памяти можно моделировать дискету большего объема. Подпрограмму псевдо-диска можно использовать для повышения производительности программ, производящих интенсивный обмен с диском. Например, если поместить на псевдо-диск ассемблер и исходный код программы, ассемблирование будет произведено не за минуты, а за секунды. Производительность некоторых программ может быть повышена более чем на порядок. Платой за такое повышение производительности являются 160K байт оперативной памяти, отводимые под псевдо-диск. Если в системе, которая в основном используется для редактирования и ассемблирования, имеется 256 кбайт памяти, то в действительности для ассемблера достаточно всего лишь 96 кбайт. Оставшиеся 160 кбайт можно использовать для моделирования диска в оперативной памяти. Следует помнить, что содержимое такого диска теряется при отключении питания, поэтому, прежде чем окончить работу, убедитесь, что информация скопирована на настоящую дискету.

Первая подпрограмма на Фиг. 10.2 - процедура загрузки. Ее код находится в секторе 1 дорожки 0 загрузочной дискеты. Как поместить программу туда, будет объяснено позже. Подпрограмма POST при завершении считывает содержимое сетора 1 дорожки 0 в память, по адресу 0:7C00H. Затем POST передает управление по первому адресу этой записи. Таким образом система фирмы IBM загружает в память DOS или любую другую операционную систему. А мы как раз и собираемся, загружать свою собственную простую операционную систему.

Сегмент NEW_DISK определяет адрес подпрограммы-драйвера устройства, также представленной на втором листинге (см. Фиг. 10.2). Поскольку наши подпрограммы ассемблируются отдельно, этот сегмент для связи процедуры загрузки и драйвера устройства во время выполнения. Сегмент ABS0 локализует векторы прерываний, заменяемые в процедуре загрузки. В сегменте CODE, содержатся команды, загружаемые с дискеты. Сегмент CODE - единственная часть приведенной программы, находящаяся на загрузочной дискете.

Первое, что делает программа инициализации - пересылает себя по адресу 0:7A00H. Затем, в процессе инициализации, процедура перезагружает систему, чтобы загрузить настоящую операционную систему. Эта загрузка производится по адресу 0:7C00H. Если бы процедура инициализации не переносила себя на другое место, она бы считывала следующую запись загрузки в ту область памяти, где находится сама.

С адреса NEXT_LOCATION процедура инициализации инсталирует драйвер устройства. Она изменяют флаги оборудования для указания на наличие дополнительного дисковода по сравнению с установкой внешних переключателей. Это "убеждает" операционную систему, что диск в оперативной памяти является частью технического обеспечения. При инициализации значение MEMORY_SIZE уменьшается на 160 кбайт, которые резервируются для моделирования диска. Это предотвращает использование предназначенной для него памяти. Кроме того, программа подсчитывает значение сегмента для этой области в 160 кбайт, чтобы знать, куда загружать драйвер устройства. Когда это выполнено, подпрограмма инициализации загружает в зарезервированную память содержимое сектора 2 дорожки 0 загрузочной дискеты. Как поместить драйвер устройства в сектор 2 будет описано при размещении программы загрузки в секторе 1.

После чтения процедуры драйвера устройства, подпрограмма инициализации изменяет вектор прерывания BIOS дискеты BIOS (INT 13H), чтобы он указывал на новый драйвер устройства. Как и в предыдущем примере, эта процедура сохраняет старый вектор. Новому драйверу этот вектор нужен чтобы при необходимости считывать данные с настоящей дискеты, а не с ее модели. Наконец, наша программа загружает систему. Она предлагает пользователю вставить системную дискету, ждет утвердительного ответа и считывает запись загрузки. (Если бы процедура предварительно не произвела пересылку программы, то сейчас она была бы испорчена). Если все идет нормально, то процедура осуществляет переход по первому адресу записи загрузки, в результате чего управление получает стандартная операционная система.

Прежде чем двинуться дальше, рассмотрим, как поместить процедуру загрузки на новую загрузочную дискету. Во-первых, необходима пустая отформатированная дискета. Она и станет загрузочной. Листинг на Фиг. 10.3 показывает, что ассемблирование и редактирование связей процедуры загрузки происходят, как обычно. Вызовите программу DOS DEBUG и загрузите процедуру инициации. Она загружается со смещением 7C00H, установленным программой DEBUG. Регистры устанавливаются таким образом, чтобы использовать BIOS для записи одного сектора дискеты. Это выполняет трехбайтовая программа, находящаяся по адресу 200H. Если после записи нет состояния ошибки, то запись инициализации уже на дискете.

Для записи драйвера устройства в сектор 2 выполните следующие шаги, показанные на Фиг. 10.3. С помощью программы DEBUG мы загружаем в память драйвер псевдодиска. Команда записи программы DEBUG помещает код драйвера в сектор с относительным номером 1 (сектор 2 дорожки 0) дискеты, находящейся на дисководе A:. Аналогичный способ можно было бы применить и для занесения на дискету записи инициализации.

Такой способ формирования вызова BIOS в программе DEBUG для записи на дискету может использоваться почти для всех функций BIOS. Проследить, что именно происходит при вызове BIOS, можно с помощью программы DEBUG. Можно установить регистры для вызова и написать несложную трехбайтовую программу, осуществляющую программное прерывание и производящую возврат в DEBUG. Этот прием удобен также для тестирования собственного драйвера устройства.

Вернемся к процедуре драйвера псевдо-диска во второй части Фиг. 10.2. Заметим, что процедура загрузки сохранила исходный вектор дискеты (INT 13H) в этом сегменте со смещением 3. Подпрограммы- драйвера используют этот вектор для реализации всех функций дискеты, которые не реализуются псевдо-диском. В приведенной подпрограмме предполагается, что псевдо-диск находится на дисководе 2. На запрос любого другого дисковода процедура передает управление BIOS, используя приэтом сохраненный в ORIGINAL_VECTOR исходный вектор. Аналогично и запрос на смену дискеты передается BIOS. Если функция, запрашиваемая для псевдо-дисковода, не считывание и не запись, то драйвер псевдо-диска не производит никаких действий, и происходит возврат с нормальным кодом завершения. Псевдо-диск не требует форматирования, а поскольку у нас нет контроля ошибок, то не остается ничего проверять.

Если запрашиваемой операцией является считывание или запись, драйвер вычисляет адрес соответствующего псевдо-сектора в памяти. При обращении за границу диска поцедура возвращает запись об ошибке отсуствия адреса. Код драйвера устанавливает регистры источника и назначения в соответствии с направлением операции. Наконец, команда REP MOVSW передает данные между псевдо-диском и буфером пользователя. Рассматриваемая программа всегда устанавливает нормальный код завершения и производит возврат в вызывающую программу.

Данный пример показывает, как реализовать моделирование диска, однако он не готов для продуктивного использования. Для того, чтобы стать утилитой общего назначения, эта программа должна быть преобразована для обеспечения работы с любым псевдо-устройством, а не только со вторым. Программу можно было бы изменить для работы с сектором любой длины, хотя обычно этого не требуется. Фактически, если моделирование диска применяется только при работе с DOS, процедура инициализации должна форматировать дискету, записав справочник и таблицу размещения файлов FAT. При нынешнем виде этой процедуры после загрузки DOS вы должны "форматировать" диск C:. Для псевдо-диска не требуеися физического форматирования, но утилита FORMAT записывает таблицу FAT и каталог, необходимые для функционирования DOS.


A>MASM BOOT,,,;

The IBM Personal Computer MACRO Assembler Version 1.00 (C)Copyroght IBM Corp 1981
    Warning   Severe
    Errors    Errors
    0         0
A>B:LINK BOOT,,,;

IBM Personal Computer Linker Version 1.00 (C)Copyroght IBM Corp 1981

Warning: No STACK segment
There was 1 error detected

A>DEBUG BOOT.EXE

-R AX=0000 BX=0000 CX=7CD3 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=06D7 ES=06D7 SS=06E7 CS=06E7 IP=0000 NV UP DI PL NZ NA PO NC 06E7:0000 0000 ADD [BX+SI],AL DS:0000=CD -U7C00 7C05 06E7:7C00 8CC8 MOV AX,CS 06E7:7C00 8CD8 MOV DS,AX 06E7:7C00 8CC0 MOV ES,AX -RAX AX 0000:301 -RBX BX 0000:7C00 -RCX CX 7CD3:1 -RDX DX 0000: -RES ES 06D7:6E7 -E200 O6D7:0200 OO.CD 00.13 00.CC ;*** Здесь вставьте загрузочную дискету -g=100 AX=0000 BX=7C00 CX=0001 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=06D7 ES=06D7 SS=06E7 CS=06E7 IP=0102 NV UP EI PL NZ NA PE NC 06E7:0102 CC INT 3 -NDISK.EXE ;*** Здесь вставьте программную дискету -L -UD 10 06E7:0000 EB05 JMPS 0007 06E7:0002 90 NOP 06E7:0003 0000 ADD [BX+SI],AL 06E7:0005 0000 ADD [BX+SI],AL 06E7:0007 80FA02 CMP DL,02 06E7:000A 7405 CMP 0011 06E7:000C 2E SEG CS 06E7:000D FF2E0300 JMP L,[0003] ;*** Здесь вставьте загрузочную дискету -W0 0 1 1 -Q A> Фиг. 10.3 Шаги подготовки загрузки в верхние адреса памяти

Эта процедура обеспечивает также сохранение процедуры-драйвера устройства в псевдо-секторе 1 на дорожке 0. Система DOS не использует указанный сектор дисковода C:, однако другие системы могут это делать. Вы возможно, заметили, что программа псевдо-диска предотвращает запись в смоделированный сектор дорожки 0, так что программа по крайней мере не уничтожит саму себя.

Вообще говоря, метод загрузки в верхние адреса оперативной памяти довольно сложен. Необходима загрузка с двух дискет, что требует от оператора дополнительных манипуляций. Если не предполагается использование программы в каких-либо других системах, кроме DOS, то гораздо удобнее использовать прерывание INT 27H. В противном случае загрузка в верхние адреса оперативной памяти может оказаться единственно возможным способом.