На главную Назад
Добро пожаловать, уважаемый посетитель!

Применениепрерывания 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

представлен листинг ассемблирования двух подпрограмм. Первая

подпрограмма осуществляет инициализацию и загрузку драйвера

устройства. Вторая подпрограмма является собственно драйвером

устройства. Позже станет ясным, почему удобнее было разделить эту

программу на две части.

 

A
Microsoft (R) Macro Assembler Version 5.00 1/1/80 01:21:50

Фиг. 10.2(а) Загрузчик для создания псевдо-дискаPage1-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

ASSUMECS:CODE,DS:ABS0

7C00 ORG 7C00H

7C008C C8 MOV AX,CS

7C028E D8 MOV DS,AX

7C048E C0 MOV ES,AX

7C068D 36 7C00 R LEA SI,BOOT_RECORD

7C0A8D 3E 7A00 R LEA DI,BOOT_RECORD-200H; Место,на которое переносится

7C0EB9 0200 MOV CX,512 ;загрузчик ДОС

7C11F3/ A4 REP MOVSB ; Перенесение загрузчика

7C13E9 7A16 R JMP NEXT_LOCATION-200H

7C16 NEXT_LOCATION:

 

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

7C1683 06 0410 R 40 ADD EQUIPMENT,40H; Увеличение числа дисководов

7C1BA1 0413 R MOV AX,MEMORY_SIZE

7C1E2D 00A0 SUB AX,DISK_SIZE

7C21A3 0413 R MOV MEMORY_SIZE,AX ; Уменьшение доступной ДОС памяти,необхо-

7C24B1 06 MOV CL,6;димое для размещения псевдо-диска

7C26D3 E0 SHL AX,CL; Умножение на 1024/16

7C288E C0 MOV ES,AX; Сегментная часть адреса нового диска

7C2AB8 0201 MOV AX,201H; Чтение сектора в эту область

7C2DBB 0000 MOV BX,0

7C30B9 0002 MOV CX,2

7C33BA 0000 MOV DX,0

7C36CD 13 INT 13H

7C3872 1A JC BOOT_ERROR

ASSUMEES:NEW_DISK

7C3AA1 004C R MOV AX,DISK_VECTOR

7C3D26: A3 0003 R MOV OLD_VECTOR,AX

7C41A1 004E R MOV AX,DISK_VECTOR+2; Сохранение старого вектора пре-

7C4426: A3 0005 R MOV OLD_VECTOR+2,AX;рывания 13h

7C48C7 06 004C R 0000 MOV DISK_VECTOR,0; Установка вектора прерывания 17h

7C4E8C 06 004E R MOV DISK_VECTOR+2,ES;на новое место

7C52EB 07 JMP SHORT REBOOT ; Чтение загрузчика с другой дискеты

7C54 BOOT_ERROR:

7C548D 36 7A93 R LEA SI,ERROR_MSG-200H; Печать сообщения об ошибке

7C58E8 7C81 R CALL PRINT_MSG

7C5B REBOOT:

7C5B8D 36 7AA5 R LEA SI,BOOT_MSG-200H; Печать сообщения о загрузке ДОС

7C5FE8 7C81 R CALL PRINT_MSG

7C62 WAIT_BOOT:

7C62B4 00 MOV AH,0

7C64CD 16 INT 16H ; Ожидание ввода с клавиатуры

7C663C 20 CMP AL,' '; Ожидается ввод пробела

7C6875 F8 JNE WAIT_BOOT

7C6AB8 0201 MOV AX,201H

7C6DBB 7C00 MOV BX,7C00H

7C70B9 0001 MOV CX,1

7C73BA 0000 MOV DX,0

7C768E C2 MOV ES,DX; Ввод на стандартное место загрузчика

7C78CD 13 INT 13H

7C7A72 D8 JC BOOT_ERROR

7C7CEA 7C00 ---- R JMP BOOT_RECORD

 

7C81 PRINT_MSG PROC NEAR

7C812E: 8A 04 MOV AL,CS:[SI]; Взять символ для печати

7C8446 INC SI

7C853C 24 CMP AL,'$'; Проверка на символ конца вывода

7C8775 01 JNE OUTPUT

7C89C3 RET

7C8A OUTPUT:

7C8AB4 0E MOV AH,14

7C8CBB 0000 MOV BX,0

7C8FCD 10 INT 10H ; Вывод на дисплей через BIOS

7C91EB EE JMP PRINT_MSG

7C938E E8 A8 A1 AA A0 20 ERROR_MSG DB 'Ошибка загрузки',13,10,'$'

A7 A0 A3 E0 E3 A7 AA

A8 0D 0A 24

 

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

7CA582 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

7CC3A8 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

 

Microsoft (R) Macro Assembler Version 5.001/1/80 04:06:49

Фиг. 10.2(б) Программа обслуживания псевдо-дискаPage1-1

 PAGE ,132

TITLE Фиг. 10.2(б) Программа обслуживания псевдо-диска

0000 CODE SEGMENT

ASSUMECS:CODE

;--------------------------------------------

; Эта программа находится в секторе 1 трека 0

;псевдо-диска. Чтение и запись на устройство 2

;переадресуется на эту программу

;--------------------------------------------

0000 DISK PROC FAR

= 0140 DISK_SIZE EQU 320 ; Размер псевдо-диска в сектрах

0000EB 05 90 JMP START_BIOS

0003???????? ORIGINAL_VECTOR DD ?

 

0007 START_BIOS:

000780 FA 02 CMP DL, 2 ; Программа обрабатывает только обращения

000A74 05 JE L1 ;к устройству (дисководу) 2

000C OLD_BIOS:

000C2E: FF 2E 0003 R JMP ORIGINAL_VECTOR ; Переход на стандартную программу

0011 L1:

00113C 01 CMP AL, 1

001376 F7 JBE OLD_BIOS

001580 FC 04 CMP AH, 4

001872 06 JB READ_WRITE ; Обрабатываются только команду чтения и

;записи

001A OK_RETURN:

001AB4 00 MOV AH, 0 ; Код возврата - 0

001CF8 CLC ; Сброс C-флага - нет ошибки

001DCA 0002 RET 2

0020 READ_WRITE:

002053 PUSH BX ; Сохранение регистров

002151 PUSH CX

002252 PUSH DX

002356 PUSH SI

002457 PUSH DI

00251E PUSH DS

002606 PUSH ES

 

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

;-----Вычисление адреса расположения требуемой записи в псевдо-диске

 

002750 PUSH AX ; Сохранение кода требуемой операции

0028B0 08 MOV AL, 8 ; Число секторов на треке

002AF6 E5 MUL CH

002CB5 00 MOV CH, 0

002E03 C1 ADD AX, CX ; Прибавление номера сектора

003080 FE 00 CMP DH, 0 ; Проверка на номера стороны

003374 03 JE HEAD_0

003505 0140 ADD AX, 320 ; Переключение на второю сторону

0038 HEAD_0:

003848 DEC AX

00393D 0140 CMP AX, DISK_SIZE ; Вычисленное значение правильно?

003C76 0E JBE DISK_OK

003E RECORD_NOT_FOUND:

003E58 POP AX ; Восстановление регистров

003F07 POP ES

00401F POP DS

00415F POP DI

00425E POP SI

00435A POP DX

004459 POP CX

00455B POP BX

0046B4 04 MOV AH, 4 ; Ошибка: сектор не найден

0048F9 STC

0049CA 0002 RET 2 ; Возврат с указанием об ошибке

004C DISK_OK:

004CB1 05 MOV CL, 5

004ED3 E0 SHL AX, CL ; Определение расположения данных на

00508C C9 MOV CX, CS ;псевдо-диске

005203 C8 ADD CX, AX ; В регистре CX сегментная часть адреса

;данных на диске

005451 PUSH CX

00558B D3 MOV DX, BX ; В регистре DX адрес передачи

0057B1 04 MOV CL, 4

0059D3 EA SHR DX, CL

005B8C C1 MOV CX, ES

005D03 D1 ADD DX, CX ; В регистре DX сегментная часть адреса

;передаваемых данных

005F59 POP CX

006083 E3 0F AND BX, 0Fh ; Выделение младших 4 разрядов

006358 POP AX ; Восстановление код требуемой операции

006480 FC 02 CMP AH, 2

006774 11 JE READ_OPN

0069 WRITE_OPN:

00698C CE MOV SI, CS

006B3B CE CMP CX, SI ; Проверка на запись поверх этой программы

006D74 1B JE ALL_DONE

006F8E C1 MOV ES, CX

0071BF 0000 MOV DI, 0

00748E DA MOV DS, DX

00768B F3 MOV SI, BX ; Установка параметров передачи

0078EB 09 JMP SHORT DO_MOVE

007A READ_OPN:

007A8E D9 MOV DS, CX

 

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

007CBE 0000 MOV SI, 0

007F8E C2 MOV ES, DX

00818B FB MOV DI, BX

0083 DO_MOVE:

00838A E8 MOV CH, AL ; Число слов в секторе

0085B1 00 MOV CL, 0

0087FC CLD

0088F3/ A5 REP MOVSW ; Пересылка данных

008A ALL_DONE:

008A07 POP ES ; Восстановление регистров

008B1F POP DS

008C5F POP DI

008D5E POP SI

008E5A POP DX

008F59 POP CX

00905B POP BX

0091B4 00 MOV AH, 0 ; Нормальное окончание

0093F8 CLC

0094CA 0002 RET 2

0097 DISK ENDP

0097 CODE ENDS

END

Фиг. 10.2 (а) Процедура загрузки для виртуального диска;

(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,

процедура инициализации должна форматировать дискету, записав

A

A>MASM BOOT,,,;

The IBM Personal Computer MACRO Assembler

Version 1.00 (C)Copyroght IBM Corp 1981

 

Warning Severe

ErrorsErrors

00

 

A>B:LINK BOOT,,,;

 

IBM Personal Computer Linker

Version 1.00 (C)Copyroght IBM Corp 1981

 

Warning: No STACK segment

 

Therhe was 1 error detected

 

A>MASM DISK,,,;

The IBM Personal Computer MACRO Assembler

Version 1.00 (C)Copyroght IBM Corp 1981

 

Warning Severe

ErrorsErrors

00

 A>B:LINK DISK,,,;

 

IBM Personal Computer Linker

Version 1.00 (C)Copyroght IBM Corp 1981

 

Warning: No STACK segment

 

Therhe was 1 error detected

 

A>DEBUG BOOT.EXE

-R

 

AX=0000BX=0000CX=7CD3DX=0000SP=0000BP=0000SI=0000DI=0000

DS=06D7ES=06D7SS=06E7CS=06E7IP=0000NVUP DI PL NZ NA PO NC

06E7:00000000 ADD[BX+SI],AL DS:0000=CD

-U7C007C05

06E7:7C00 8CC8MOVAX,CS

06E7:7C00 8CD8MOVDS,AX

06E7:7C00 8CC0MOVES,AX

-RAX

AX 0000

:301

-RBX

BX 0000

:7C00

-RCX

CX 7CD3

:1

-RDX

DX 0000

:

-RES

ES 06D7

:6E7

-E200

O6D7:0200OO.CD00.1300.CC ;*** Здесь вставьте загрузочную дискету

-g=100

 

AX=0000BX=7C00CX=0001DX=0000SP=0000BP=0000SI=0000DI=0000

DS=06D7ES=06D7SS=06E7CS=06E7IP=0102NVUP EI PL NZ NA PE NC

06E7:0102CCINT3

-NDISK.EXE ;*** Здесь вставьте программную дискету

-L

-UD 10

06E7:0000 EB05JMPS0007

06E7:0002 90NOP

06E7:00030000 ADD[BX+SI],AL

06E7:00050000 ADD[BX+SI],AL

06E7:000780FA02CMPDL,02

06E7:000A7405 CMP0011

06E7:000C2ESEGCS

06E7:000DFF2E0300JMPL,[0003];*** Здесь вставьте загрузочную дискету

-W0 0 1 1

-Q

A>

A

Фиг. 10.3 Шаги подготовки загрузки в верхние

адреса памяти

справочник и таблицу размещения файлов FAT. При нынешнем виде этой

процедуры после загрузки DOS вы должны "форматировать" диск C:. Для

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

FORMAT записывает таблицу FAT и каталог, необходимые для

функционирования DOS.

 

Эта процедура обеспечивает также сохранение процедуры-драйвера

устройства в псевдо-секторе 1 на дорожке 0. Система DOS не

использует указанный сектор дисковода C:, однако другие системы

могут это делать. Вы вооозможно, заметили, что программа псевдо-

диска предотвращает запись в смоделированный сектор дорожки 0, так

что программа по крайней мере не уничтожит саму себя.

 

Вообще говоря, метод загрузки в верхние адреса оперативной

памяти довольно сложен. Необходима загрузка с двух дискет, что

требует от оператора дополнительных манипуляций. Если не

предполагается использование программы в каких-либо других

системах, кроме DOS, то гораздо удобнее использовать прерывание INT

27H. В противном случае загрузка в верхние адреса оперативной

памяти может оказаться единственно возможным способом.


 

Mail.ru