
- •Введение
- •Лабораторная работа № 1. Создание программы определения характеристик центрального процессора.
- •Определение параметров процессора на аппаратном уровне.
- •Лабораторная работа № 2.
- •Конфигурация персонального компьютера
- •Cmos-память и конфигурация компьютера
- •32H Текущее столетие
- •Использование bios для определения конфигурации
- •Лабораторная работа 3. Тестирование оптических накопителей.
- •Использование I/o Control Codes.
- •Использование Windows Management Instrumentation (wmi).
- •Порты контроллера накопителей на гибких дисках
- •Порт 3f2h.
- •Порт 3f4h.
- •Команды управления накопителями
- •Перечень команд контpоллеpа нгмд
- •Структура байтов состояния
- •Формат дорожки
- •Отличия контроллера для ат-подобных пэвм
- •Порт 3f7h.
- •Лабораторная работа № 5. Диагностика контроллера накопителей на жестких дисках.
- •Контроллер жестких дисков для хт-подобных пэвм
- •Порты ввода-вывода
- •Порт 320h.
- •Порт 321h.
- •Порт 322h.
- •Порт 323h.
- •Общий формат команды и терминология
- •Описание команд Проверка готовности накопителя (класс 0, опкод 0).
- •Рекалибровать (класс 0, опкод 1).
- •Запрос состояния (класс 0, опкод 3).
- •Форматирование накопителя (класс 0, опкод 4).
- •Проверка секторов (класс 0, опкод 5).
- •Форматирование дорожки (класс 0, опкод 6).
- •Форматирование дефектной дорожки (класс 0, опкод 7).
- •Чтение секторов (класс 0, опкод 8).
- •Запись секторов (класс 0, опкод 0Ah).(*)
- •Поиск цилиндра по номеру (класс 0, опкод 0Ch).(*)
- •Чтение внутреннего озу контроллера (класс 0, опкод 0Eh).(*)
- •Запись внутреннего озу контроллера (класс 0, опкод 0Fh).(*)
- •Диагностика внутреннего озу контроллера (класс 7,опкод 0).(*)
- •Тест устройства (класс 7, опкод 3).
- •Расширенный тест контроллера (класс 0, опкод 4).
- •Считывание без контроля (класс 7, опкод 5).
- •Запись без контроля (класс 7, опкод 6).
- •Разметка диска
- •Контроллер жестких дисков для ат-подобных пэвм
- •Описание портов ввода-вывода Порт 1f0h
- •Порт 1f1h.
- •Система команд
- •Лабораторная работа №6. Программное тестирование портов для работы с клавиатурой
- •Аппаратное прерывание клавиатуры
- •Средства bios для работы с клавиатурой
- •Чтение символа с ожиданием
- •Проверка буфера на наличие в нем символов
- •Получение состояния переключающих клавиш
- •Установка временных характеристик клавиатуры
- •Запись символов в буфер клавиатуры
- •Чтение символа с ожиданием для 101-клавишной клавиатуры
- •Проверка буфера на наличие в нем символов для 101-клавишной клавиатуры
- •Получение состояния переключающих клавиш для 101-клавишной клавиатуры
- •Лабораторная работа № 7. Тестирование и контроль оперативной памяти.
- •Алгоритм определения объёма оперативной памяти.
- •Сущность тестирования памяти.
- •Алгоритм диагностирования памяти в тесте Memtest86.
- •Лабораторная работа № 8. Программирование принтера. Цель работы: изучение методов программирования принтера.
- •Средства ms-dos для работы с принтером
- •Программирование режимов принтера
- •Установка атрибутов/цветов символов.
- •Сдвиг экрана и страницы.
- •Вертикальный сдвиг текстового экрана.
- •Сдвиг текстового экрана горизонтально.
- •Переключение между текстовыми страницами.
- •Сдвиг между страницами текста.
- •Использование wmi.
- •Аналогичным образом могут использоваться свойства и других классов.
Лабораторная работа № 7. Тестирование и контроль оперативной памяти.
Цель работы: изучение методов тестирования оперативной памяти.
Алгоритм определения объёма оперативной памяти.
Ставший уже классическим метод определения ее объема заключается в следующем принципе: Если что-то записать по несуществующему физически адресу, а потом прочитать что-то с этого же адреса - записанное и прочитанное значения естественно не совпадут (в 99,(9) процентах случаев прочитаются нули). Сам алгоритм такой:
Инициализировать счетчик.
Сохранить в регистре значение из памяти по адресу [счетчик]
Записать в память тестовое значение (в нашем случае это будет AAh)
Прочитать из памяти.
Восстановить старое значение по этому адресу.
Сравнить записанное и прочитанное значение
Если равны – счетчик=счетчик+1, если нет – выход из цикла.
JMP пункт 2
На первый взгляд все очень просто, при практической же реализации приведенного алгоритма возникает множество проблем: во-первых сама программа считающая память расположена в этой самой памяти и рано или поздно она сама себя перезапишет тестовым значением. Этот нюанс обычно решается так: программа выполняется в реальном режиме в пределах первого мегабайта, счет же начинается с адресов выше мегабайта.
Этот метод порождает другую проблему – в реальном режиме непосредственно доступен только этот самый один мегабайт. Эта проблема решается путем применения «нереального» режима, он же Big real-mode.
Как известно в процессоре каждый сегментный регистр имеет скрытые или теневые (shadow parts) части в которых в защищенном режиме кэшируется дескриптор сегмента, для программиста они невидимы. В защищенном режиме эти части обновляются всякий раз когда в сегментный регистр загружается новое значение, в реальном же режиме обновляются только поля базового адреса сегмента. Если в защищенном режиме создать сегмент с лимитом в 4Гб и загрузить в сегментный регистр такой селектор, после чего переключиться в реальный режим, и, не следуя рекомендациям интел, оставить предел равным 4Гб – значение лимита сегмента сохранится позволяя использовать 32-битные смещения. Алгоритм перехода в нереальный режим:
Создать дескриптор с базой равной 0
Установить предел сегмента в 4Гб
Переключиться в защищенный режим
Загрузить селектор сегмента в какой-либо сегментный регистр
Переключиться в реальный режим
После этих действий можно в реальном режиме использовать конструкции типа:
мov ax,word ptr fs:[edx]
Где EDX может изменяться от нуля до 4Гб не вызывая никаких исключений защиты (в «настоящем» реальном режиме превышение 64Кб вызывает исключение GP#) Фактически EDX=целевой адрес, поскольку база сегмента в FS=0.
В защищенном режиме при включенной страничной адресации считать память этим методом бесполезно потому что кроме основной памяти будет считаться еще и файл подкачки на винчестере, и в перспективе можно всегда получать значение около 4Гб (зависит от ОС).
Здесь есть еще один тонкий момент: в книгах М.Гука и В.Юрова пишется, что в качестве «нереального» сегментного регистра надо использовать FS или GS так как другие регистры часто перезагружаются и процессор якобы сбрасывает лимит в 64Кб после перезагрузки сегментного регистра в реальном режиме. На практике оказывается совсем не так. Процессор НЕ ТРОГАЕТ поля лимитов в реальном режиме.
Во избежание дополнительных проблем будут приведены примеры с регистром FS.
Возвращаясь к главному, а именно к оперативной памяти.
Алгоритм:
Установить «нереальный режим»
Открыть старшие адресные линии (GateA20)
Установить счетчик в 1048576 (1Mb)
Цикл записи-чтения
Вывести значение счетчика
Закрыть вентиль A20
Выход
Пример листинга:
.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.