Справочник программиста на персональном компьютере фирмы IBM. Системные ресурсы
Страница 8. Ревизия количества памяти


 

1.1.7 Ревизия количества памяти.

Вопрос: "Сколько имеется памяти?",- может иметь три смысла.
О каком количестве памяти сообщают переключатели, установленные
на системной плате? Сколько микросхем памяти реально установлено
в машине? И, наконец, сколько остается свободной памяти, которую
DOS может использовать для выполнения Ваших программ? Машина
может иметь 10 банков памяти по 64K, но переключатели могут ука-
зывать на наличие только 320K, оставляя половину памяти для ка-
ких-либо специальных целей. А как может Ваша программа узнать,
сколько из доступных 320K она может использовать, учитывая, что
другое программное обеспечение может быть загружено резидентным в
верхнюю или нижнюю часть памяти?
Ответ на каждый вопрос можно получить своим способом. Для PC и
XT установка переключателей может быть просто прочитана через
порт B микросхемы интерфейса с периферией 8255. В пункте [1.1.1]
описано как это делается. BIOS хранит двухбайтную переменную по
адресу 0040:0013, которая сообщает число килобайт используемой
памяти. Для PCjr бит 3 порта 62H (порт C микросхемы 8255) равен
нулю, когда машина имеет добавочные 64K памяти. AT дает особо
полную информацию о памяти. Регистры 15H (младший) и 16H (стар-
ший) микросхемы информации о конфигурации говорят сколько памяти
установлено на системной плате (возможны три значения: 0100H -
для 256K, 0200H - для 512K и 0280H для 512K плюс 128K на плате
расширения). Память канала ввода/вывода для AT сообщается регист-
рами 17H и 18H (с инкрементом 512K). Память сверх 1 мегабайта
доступна через регистры 30H и 31H (опять с инкрементом 512K,
вплоть до 15 мегабайт). Если AT имеет 128K на плате расширения,
то установлен бит 7 регистра 33. Во всех случаях надо сначала
послать номер регистра в порт 70H, а затем прочитать значение из
порта 71H.
Легко написать программу, которая прямо тестирует наличие
памяти через определенные интервалы адресного пространства. Пос-
кольку минимальная порция памяти 16 килобайт, то достаточно про-
верить одну ячейку памяти в каждом 16-килобайтном сегменте, чтобы
убедиться, что все 16K присутствуют. Когда данная ячейка памяти
отсутствует, то при чтении из нее получаем значение 233. Для
проверки можно записать в ячейку произвольное число, отличное от
233 и сразу же считать его. Если вместо посланного числа возвра-
щается 233, то соответствующий банк памяти отсутствует. Не приме-
няйте этот способ на AT, где при попытке писать в несуществующую
память вступает в действие встроенная обработка несуществующей
памяти. Диагностика AT настолько хороша, что Вы можете целиком
положиться на системную информацию о конфигурации.
Память постоянно занимается частями операционной системы,
драйверами устройств, резидентными программами обработки прерыва-
ний и управляющими блоками MS DOS. При проверке банков памяти Вы
не должны вносить необратимых изменений в содержимое памяти.
Сначала надо сохранить значение, хранящееся в тестируемой ячейке,
затем проверить ее и восстановить первоначальное значение.
Имеется еще одна проблема. Если Ваша процедура хотя бы времен-
но модифицирует свой код, то это может привести к краху. Поэтому
для проверки надо выбирать такую ячейку из блока 64K, которая не
будет занята текстом Вашей процедуры. Для этого поместите проце-
дуру тестирования впереди программы, а для тестирования выберите
ячейку со смещением равным смещению для кодового сегмента. Напри-
мер, если регистр кодового сегмента содержит 13E2, то сегмент
начинается со смещения 13E2 во втором 64K-байтном блоке памяти.
Поскольку Ваша подпрограмма проверки не может находиться по этому
адресу, то Вы можете безопасно проверять значение 3E2 в каждом
блоке. Запрет прерываний [1.2.2] позволяет не беспокоиться о
модификации кода из-за аппаратных прерываний, которые могут
происходить во время проверки.
Определение количества памяти реально доступной операционной
системе также требует некоторого фокуса. Когда программа первый
раз получает управление, то DOS отводит ей всю доступную память,
включая верхнюю область памяти, содержащую нерезидентную часть
DOS (которая автоматически перезагружается, если она была модифи-
цирована). Для запуска другой программы из текущей или для того,
чтобы сделать программу подходящей для многопользовательсой сис-
темы, необходимо урезать программу до требуемого размера. В пунк-
те [1.3.1] описано как это сделать с помощью функции 4AH прерыва-
ния 21H.
Эта же функция может быть использована для расширения отведен-
ной памяти. Поскольку программе отводится вся доступная память
при загрузке, то такое расширение невозможно при старте. Если Вы
попробуете сделать это, то будет установлен флаг переноса, в
регистре AX появится код ошибки 8, а в регистре BX будет возвра-
щено максимальное число доступных 16-байтных параграфов. Эта
информация как раз и нужна. Значит надо выдать запрос со слишком
большим значением в регистре BX ( скажем, F000H параграфов), а
затем выполните прерывание. Позаботьтесь о том, чтобы выполнить
эту функцию в самом начале программы, пока регистр ES еще имеет
начальное значение.

Высокий уровень.

Интерпретатор Бейсика использует только 64K (хотя операторы
PEEK и POKE позволяют доступ к памяти за пределами 64K). Доля
памяти доступная в настоящий момент возвращается функцией FRE.
Эта функция имеет фиктивный аргумент, который может быть числовым
или символьной строкой. BYTES = FRE(x) передает в BYTES число
свободных байтов. BYTES = FRE(x$) делает то же самое. Но строко-
вый аргумент вынуждает очистку области данных перед тем как возв-
ратить число байтов. Заметим, что если размер рабочей области
устанавливается с помощью оператора CLEAR, то количество памяти,
сообщаемое функцией FRE будет на от 2.5 до 4 килобайт меньше
из-за потребностей рабочей области интерпретатора.
Транслятор Бейсика не накладывает ограничение 64K на суммарный
объем кода и данных. Но сам компилятор ограничен тем количеством
памяти, которое он может использовать при компиляции. Если этого
пространства недостаточно, то уничтожьте все ненужные номера
строк при помощи ключа компиляции /N. Можно также использовать
более короткие имена переменных.
Средний уровень.
Прерывание 12H BIOS проверяет установку переключателей и возв-
ращает в AX количество килобайт памяти в системе. Эта величина
вычисляется из установки регистров микросхемы 8255 или, для AT,
микросхемы конфигурации/часов. Входных регистров нет. Имейте
ввиду, что установка переключателей может быть неверной, что
ограничивает достоверность такого подхода.
Для определения числа 16-байтных параграфов, доступных для
DOS, используйте функцию 4AH прерывания 21H. ES должен иметь то
же значение, что при старте задачи:
;---определение числа параграфов доступных для DOS
MOV AH,4AH ;указываем нужную функцию
MOV BX,0FFFFH ;требуем слишком большую память
INT 21H ;BX содержит число доступных параграфов
AT использует функцию 88H прерывания 15H для проверки наличия
расширенной памяти, которая ищет память вне адресного пространст-
ва процессора в обычном режиме адресации. Говорят, что она ищет
память за отметкой 1 мегабайта. При этом на системной плате дол-
жно быть от 512 до 640 килобайт памяти, чтобы эта функция рабо-
тала. Число килобайтных блоков расширенной памяти возвращается в
AX.

Низкий уровень.

Первый пример проверяет число банков памяти по 64K в первых
десяти 64-килобайтных сегментах памяти. Если Вы будете проверять
старшие 6 банков памяти, то имейте ввиду, что имеются видеобуфер,
начиная с B000:0000 (и, возможно, A000:0000) и ПЗУ, начиная с
F000:0000 (и, возможно, C000:0000).
;---проверка каждого банка памяти:
CLI ;запрет аппаратных прерываний
MOV AX,CS ;получаем значение кодового сегмента
AND AX,0FFFH ;сбрасываем старшие 4 бита
MOV ES,AX ;помещаем указатель в ES
MOV DI,0 ;DI считает число банков памяти
MOV CX,10 ;будем проверять 10 банков
MOV BL,'X' ;для проверки используем 'X'
NEXT:
MOV DL,ES:[0] ;сохраняем значение тестируемой ячейки
MOV ES:[0],BL ;помещаем 'X' в эту ячейку
MOV DH,ES:[0] ;читаем тестируемую ячейку
MOV ES:[0],DL ;восстанавливаем значение
CMP DH,'X' ;совпадает с тем, что писали?
JNE GO_AHEAD ;если нет, то банк отсутствует
INC DI ;увеличиваем число банков
GO_AHEAD:
MOV AX,ES ;готовим увеличение указателя
ADD AX,1000H ;указываем на следующие 64K
MOV ES,AX ;возвращаем указатель в ES
LOOP NEXT ;обрабатываем следующий банк
STI ;разрешаем аппаратные прерывания

 
« Предыдущая статья   Следующая статья »