Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29202
Скачиваний: 1689
Глава 30. Работа с расширенной памятью
289
30.2. Программа XMSmem.asm.
Получение объема XMS-памяти
30.2.1. Подготовка к использованию расширенной
памяти и вывод объема XMS-памяти
Первое, что мы сделаем, — определим объем доступной XMS-памяти и выведем
количество килобайт на экран при помощи известной нам уже процедуры с исполь-
зованием сопроцессора (ее мы уже рассматривали в предыдущих главах).
Как уже отмечалось ранее, чтобы использовать расширенную память, необхо-
димо, чтобы в памяти был загружен специальный драйвер, который бы открыл
доступ к ней. В DOS/Windows такой файл называется himem.sys. Если загрузить
"чистую" DOS без этого драйвера, то программы смогут обращаться только к ос-
новной памяти (640 Кбайт). Следовательно, все файлы-приложения будут работать
только в том случае, если загружен указанный выше файл (или его аналог).
Первое, что нужно сделать, — проверить наличие драйвера himem.sys в памяти.
Это позволяет сделать функция
4300h
прерывания
2Fh
(табл. 30.1).
Таблица 30.1. Функция
4300h
прерывания
2Fh
: проверка на присутствие
в памяти драйвера himem.sys
Вход
Выход
ax = 4300h
al = 80h
— драйвер загружен
Рис. 30.1. Проверка драйвера himem.sys
Как провести проверку, показано в листинге 30.1 (во избежание недоразумений
проверка будет осуществляться во всех трех файлах-приложениях).
Часть III. Файловая оболочка, вирус, резидент
290
Листинг 30.1. Проверяем наличие файла himem.sys
...
;Проверим на наличие himem.sys в памяти...
mov ax,4300h
int 2Fh
cmp al,80h
je Himem_loaded
;Если al = 80h, то himem.sys загружен.
;Иначе выводим сообщение о том, что himem в памяти не обнаружен...
...
Если драйвер присутствует, то можно попробовать отвести блок расширенной
памяти. Для этого вызываем собственную процедуру
Prepare_XMS
, которая подго-
товится к работе с расширенной памятью, а также отведет блок памяти.
Все процедуры по управлению XMS-памятью вызываются не с помощью пре-
рываний (как функции DOS —
int 21h
), а с использованием команды "дальний
call
" и указанием после нее сегмента и смещения самой процедуры. Получить
точку входа (адрес) процедур по управлению XMS-памятью позволяет функция
4310h
прерывания
2Fh
(табл. 30.2).
Подобный принцип вызова процедур очень похож на вызов WinAPI.
Таблица 30.2. Функция
4310h
прерывания
2Fh
: получить точку
входа процедур управления XMS-памятью
Вход
Выход
ax = 4310h
es
= сегмент, bx = смещение
Рассмотрим это на примере.
После того как получили точку входа, все остальные обращения к процедурам
работы с XMS-памятью будут осуществляться следующим образом (естественно,
нужно предварительно загрузить необходимые данные в регистры или подготовить
массивы данных):
call dword ptr XMS_Addr
В листинге 30.2 показано, как получить адрес обработчика XMS-функций и ко-
личество килобайт расширенной памяти.
Листинг 30.2. Получаем адрес обработчика и объем свободной XMS-памяти
...
mov ax,4310h
int 2Fh
mov word ptr XMS_Addr,bx
mov word ptr XMS_Addr+2,es ;Сохраним обработчик XMS-функций
Глава 30. Работа с расширенной памятью
291
mov ah,88h ;Получить количество килобайт XMS-памяти
call dword ptr XMS_Addr
mov dword ptr Number_dec,edx ;Сохраним полученное число
...
Рис. 30.2. Получить объем XMS-памяти
Как видно из примера, функция возвращает количество килобайт (не байт!)
в 32-разрядный регистр
edx
.
Обращаем ваше внимание, что данная функция может работать некорректно
в Windows NT/2000/XP. В этом случае просто загрузите "чистую" MS-DOS 5.00
и выше и проверьте работоспособность этой функции. Более того, количество ки-
лобайт свободной XMS-памяти возвращает непосредственно операционная система,
которая берет информацию не из CMOS, а ведет учет самостоятельно. Это значит,
что информация, которую вернет функция, может не соответствовать действитель-
ности. DOS может указать не только реальный объем XMS-памяти, но и добавить
к нему размер SWAP-файла Windows либо наоборот показать меньший размер, чем
есть на самом деле, вычтя из реального объема размер памяти, отведенной под кэш.
Все зависит от версии DOS/Windows.
Теперь осталось только вывести полученный результат, используя написанную
и изученную нами процедуру вывода десятичного числа
Out_dec
.
30.3.
Программа XMSblock.asm. Чтение файла
в расширенную память и вывод его на экран
Рассматривать подготовку и отведение блока расширенной памяти мы уже не
будем. Для данного файла эти операции проводятся аналогично вышеописанным.
Единственное исключение в том, что мы еще и отводим блок расширенной памяти
Часть III. Файловая оболочка, вирус, резидент
292
при помощи функции
09h
процедуры управления XMS-памятью (рис. 30.3). При
этом регистр
dx
должен содержать размер отводимого блока памяти в килобайтах
(листинг 30.3).
Листинг 30.3. Отведение блока XMS-памяти
...
mov ah,9
mov dx,1024 ;Отводим 1024 Кбайт XMS-памяти
call dword ptr XMS_Addr
or ax,ax ;Ошибка?
jnz XMS_OK
...
XMS_OK:
mov XMS_id,dx ;Сохраним id отведенного блока
...
В случае если произошла ошибка (запрашиваемый блок больше имеющегося
в распоряжении и т. п.), то значение
ax
будет равно не нулю, а коду ошибки.
Рис. 30.3. Отводим блок расширенной памяти
Если ошибки не произошло, то
dx
будет содержать идентификационный номер
отведенного блока. В дальнейшем мы будем обращаться к отведенному блоку, ис-
пользуя этот номер. Принцип обращения к отведенному блоку аналогичен принци-
пу работы с файлами: при открытии файла функции
3Dh
прерывания
21h
возвраща-
ет номер открытого файла.
Глава 30. Работа с расширенной памятью
293
30.3.1. Работа с расширенной памятью
Как уже ранее отмечалось, загружать данные напрямую в XMS-память в DOS
невозможно. Для этого используется основная память (640 Кбайт). Сперва данные
загружаются в отведенный массив в основной памяти, затем при помощи специ-
альной процедуры пересылаются в расширенную. Пересылка осуществляется бло-
ками, но не более чем по 64 Кбайт.
В программе XMSblock.asm мы вначале читаем файл C:\autoexec.bat в отведен-
ный массив основной памяти и выводим его на экран. Затем перебрасываем прочи-
танные байты в расширенную память и обратно в основную, но уже по другому
адресу. И снова выводим то, что перебрасывали. Идентичность выводимой инфор-
мации подтверждает то, что программа не имеет ошибок: данные пересылаются
в XMS-память и обратно.
30.3.2. Структура массива при работе
с XMS-памятью
Для работы с XMS-памятью (пересылка данных) заведем специальный массив
(листинг 30.4). Для удобства зададим каждой переменной название. В дальнейшем
адрес данного массива будет загружаться в регистры
ds:si
перед вызовом специ-
альных подфункций функции управления XMS-памятью.
Листинг 30.4. Переменные для работы с расширенной памятью
...
;Количество байтов для пересылки
XMS_str dd 0
;Источник
XMS_src dw 0
;Смещение в блоке-источнике или адрес в основной памяти
XMS_offsrc dd 0
;Идентификатор приемника
XMS_rec dw 0
;Смещение в блоке-приемнике или адрес в основной памяти
XMS_offrec dd 0
...
Рассмотрим отдельно каждую переменную.
XMS_str
(два слова) — должна содержать количество байтов для пересылки из
основной памяти в XMS либо наоборот.