Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
33_Metodicheskie_ukazania_po_laboratornym_rabot...doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
706.56 Кб
Скачать

Лабораторная работа № 7. Тестирование и контроль оперативной памяти.

Цель работы: изучение методов тестирования оперативной памяти.

Алгоритм определения объёма оперативной памяти.

Ставший уже классическим метод определения ее объема заключается в следующем принципе: Если что-то записать по несуществующему физически адресу, а потом прочитать что-то с этого же адреса - записанное и прочитанное значения естественно не совпадут (в 99,(9) процентах случаев прочитаются нули). Сам алгоритм такой:

  1. Инициализировать счетчик.

  2. Сохранить в регистре значение из памяти по адресу [счетчик]

  3. Записать в память тестовое значение (в нашем случае это будет AAh)

  4. Прочитать из памяти.

  5. Восстановить старое значение по этому адресу.

  6. Сравнить записанное и прочитанное значение

  7. Если равны – счетчик=счетчик+1, если нет – выход из цикла.

  8. JMP пункт 2

На первый взгляд все очень просто, при практической же реализации  приведенного алгоритма возникает множество проблем: во-первых сама программа считающая память расположена в этой самой памяти и рано или поздно она сама себя перезапишет тестовым значением. Этот нюанс обычно решается так: программа выполняется в реальном режиме в пределах первого мегабайта, счет же начинается с адресов выше мегабайта.

Этот метод порождает другую проблему – в реальном режиме непосредственно доступен только этот самый один мегабайт. Эта проблема решается путем применения «нереального» режима, он же Big real-mode.

Как известно в процессоре каждый сегментный регистр имеет скрытые или теневые (shadow parts) части в которых в защищенном режиме кэшируется дескриптор сегмента, для программиста они невидимы. В защищенном режиме эти части обновляются всякий раз когда в сегментный регистр загружается новое значение, в реальном же режиме обновляются только поля базового адреса сегмента. Если в защищенном режиме создать сегмент с лимитом в 4Гб и загрузить в сегментный регистр такой селектор, после чего переключиться в реальный режим, и, не следуя рекомендациям интел, оставить предел равным 4Гб  – значение лимита сегмента сохранится позволяя использовать 32-битные смещения. Алгоритм перехода в нереальный режим:

  1. Создать дескриптор с базой равной 0

  2. Установить предел сегмента в 4Гб

  3. Переключиться в защищенный режим

  4. Загрузить селектор сегмента в какой-либо сегментный регистр

  5. Переключиться в реальный режим

После этих действий можно в реальном режиме использовать конструкции типа:

 мov ax,word ptr fs:[edx]

Где EDX может изменяться от нуля до 4Гб не вызывая никаких исключений защиты (в «настоящем» реальном режиме превышение 64Кб вызывает исключение GP#) Фактически EDX=целевой адрес, поскольку база сегмента в FS=0.

В защищенном режиме при включенной страничной адресации считать память этим методом бесполезно потому что кроме основной памяти будет считаться еще и файл подкачки на винчестере, и в перспективе можно всегда получать значение около 4Гб (зависит от ОС).

Здесь есть еще один тонкий момент: в книгах М.Гука и В.Юрова пишется, что в качестве «нереального» сегментного регистра надо использовать FS или GS так как другие регистры часто перезагружаются и процессор якобы сбрасывает лимит в 64Кб после перезагрузки сегментного регистра в реальном режиме. На практике оказывается совсем не так. Процессор НЕ ТРОГАЕТ поля лимитов в реальном режиме.

Во избежание дополнительных проблем будут приведены примеры с регистром FS.

Возвращаясь к главному, а именно к оперативной памяти.

Алгоритм:

  1. Установить «нереальный режим»

  2. Открыть старшие адресные линии (GateA20)

  3. Установить счетчик в 1048576 (1Mb)

  4. Цикл записи-чтения

  5. Вывести значение счетчика

  6. Закрыть вентиль A20

  7. Выход

Пример листинга:

.586P

DESCRIPTOR STRUC ;Структура дескриптора сегмента для

;защищенного режима

limit dw 0

base_1 dw 0

base_2 db 0

attr db 0

lim_atr db 0

base_3 db 0

ENDS

GDT segment use16 ;Таблица GDT

empty dq 0

_code descriptor <0,0,0,0,0,0> ;Дескриптор для сегмента кода программы

_temp descriptor <0,0,0,0,0,0> ;"Нереальный" дескриптор

GDT ends

data segment use16

gdtr df 0 ;Поле для регистра GDTR

string db "Memory available: ",20 dup (0)

data ends

stck segment stack use16 ;Стек

db 256 dup (0)

stck ends

code segment use16

assume cs:code,ss:stck,ds:gdt

start: ;entry point

mov ax,gdt

mov ds,ax

mov _code.limit,65535 ;Лимит сегмента кода 64Кб

mov eax,code ;Получаем физический адрес и загружаем базу

shl eax,4

mov _code.base_1,ax

shr eax,8

mov _code.base_2,ah

mov _code.attr,09Ah ;Атрибуты - сегмент кода

mov _temp.limit,65535 ;Устанавливаем лимит в максимальное значение

mov _temp.attr,092h ;Атрибуты - сегмент данных, доступ чтение\запись

mov _temp.lim_atr,08Fh ;Устанавливаем старшие биты лимита и бит G

assume ds:data ;Получаем физический адрес таблицы GDT

mov ax,data

mov ds,ax

mov eax,gdt

shl eax,4

mov dword ptr [gdtr+2],eax ;загружаем лимит и адрес таблицы GDT

mov word ptr gdtr,23

cli ;Запрет прерываний

mov al,80h ;Запрет NMI

mov dx,70h

out dx,al

lgdt gdtr ;Загружаем GDTR

mov eax,cr0 ;Переключаемся в защищенный режим

inc al

mov cr0,eax

db 0EAh ;Дальний JMP для загрузки CS селектором

dw offset protect

dw 08h

protect:

mov ax,10h ;Загружаем FS в защищенном режиме

mov fs,ax

mov eax,cr0 ;Идем назад в реальный режим

dec al

mov cr0,eax

db 0EAh

dw offset real

dw code

real: ;Открываем вентиль GateA20

mov dx,92h

in al,dx

or al,2

out dx,al

mov ecx,1048576 ;Начальное значение счетчика - 1 Мегабайт

mov al,0AAh ;Тестовое значение

count:

mov dl,byte ptr fs:[ecx] ;Сохраняем старое значение по адресу

mov byte ptr fs:[ecx],al ;пишем туда тестовое

mov al,byte ptr fs:[ecx] ;читаем с того же адреса

mov byte ptr fs:[ecx],dl ;востанавливаем старое значение

cmp al,0AAh ;прочитали то что записали?

jnz exit ;Нет - такого адреса физически не существует

inc ecx ;Да - увеличиваем счетчик и повторяем все еще раз

jmp count

exit: ;Разрешить прерывания

mov al,0

mov dx,70h

out dx,al

sti

mov dx,92h ;Закрыть вентиль A20

in al,dx

and al,0FDh

out dx,al

mov ax,cx ;процеруда преобразования числа в строку требует

shr ecx,16 ;чтобы значение располагалось в DX:AX

mov dx,cx ;Преобразуем DX:AX=ECX

push ds

pop es

lea di,string

add di,18 ;пропускаем строку "Memory available"

call DwordToStr ;преобразование в символьную форму

mov ah,9

mov dx,offset string ;вывод

int 21h

mov ax,4c00h ;Завершение работы

int 21h

code ends

end start

После запуска программы следует немного подождать, примерно в 2 раза больше  времени, чем то, за которое считает оперативку BIOS при загрузке.

Есть один способ многократного увеличения скорости программы. Дело в том, что этот исходник считает память с точностью до байта, такая точность вообще говоря не нужна, т.к. размер современной планки памяти не может быть некратным мегабайту, поэтому можно наращивать счетчик сразу прибавляя к нему значение 1048576, чего можно достичь заменив в цикле записи-чтения команду inc ecx на add ecx,1048576.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]