- •Лабораторная работа контроллер нжмд
- •Вопросы к теме «нжмд»
- •Функции основных регистров кнжмд?
- •Что такое команды ата?
- •Как осуществляется обмен информацией между контроллером и диском?
- •Физическое устройство винчестера.
- •Что такое парковка головок?
- •Что такое контроллер нжмд?
- •Как физически хранится информация да диске?
- •Какие могут быть использованы интерфейсы?
Лабораторная работа контроллер нжмд
Цель работы: Изучить принцип работы контроллеров накопителей на жестком магнитном диске (НЖМД); разобраться, как происходит работа с жесткими дисками по стандарту АТА; научиться писать программы, выполняющие заданные действия в системе НЖМД-ОП.
Работа с накопителями на низком уровне
Если возникает потребность в выполнении низкоуровневых операций, то в случае с гибкими дисками удобнее и безопаснее работать через функции BIOS (они более стандартны, чем контроллеры дисководов, разработанные разными фирмами), а с жесткими дисками, наоборот, гораздо проще взаимодействовать напрямую (по стандарту АТА).
С регистрами контроллера жёсткого диска необходимость работать напрямую возникает в следующих случаях:
- при переключении процессора в защищенный режим (прерывания DOS и BIOS становятся недоступными);
- при работе с дисками большого (свыше 8 Гбайт) объема или нестандартного (не DOS) формата;
- в измерительных системах и системах управления в реальном времени (для ускорения операций ввода-вывода);
- в системах с повышенными требованиями к защите информации (для предотвращения перехвата управления на уровне прерываний, например, компьютерным вирусом).
Стандарт АТА позволяет подключать к каждому каналу (то есть к одному кабелю) по два устройства. Наличие на материнской плате двух каналов для подключения АТА – устройств, фактически, стало стандартом. Для этих каналов жестко закреплен диапазон адресов ввода-вывода и номера используемых прерываний.
Для адресации данных на диске с интерфейсом АТА можно использовать либо режим LBA, либо режим CHS, причем назначение регистров контроллера зависит от используемого режима адресации. Все регистры, за исключением регистра данных, 8-разрядные, а регистр данных — 16-разрядный.
Рассмотрим основные регистры контроллера НЖМД.
Регистр данных (DR - 1F0h) используется при выполнении операции чтения или записи сектора в программном режиме ввода-вывода. Этот регистр недоступен, пока не начнется операция чтения или записи. Нельзя обращаться к регистру, когда происходит обмен информацией между диском и памятью в режиме прямого доступа (DMA). Передача данных через регистр осуществляется 16-разрядными словами. Этот 16-разрядный регистр и его адресное пространство перекрывают следующий за ним регистр ошибок.
Регистр ошибок (ER – 1F1h) доступен только для чтения. Он определяет состояние адаптера после выполнения операции. Содержимое этого регистра нужно проверять в двух случаях:
- после выполнения любой команды, если установлен бит ошибки ERR в регистре состояния;
- после выполнения команды «диагностика» или после выполнения внутренней диагностики адаптера по системному сбросу.
Если при выполнении команды ошибок не было, то все разряды регистра ошибок содержат нули. Если при выполнении команды происходит какая-либо ошибка, то соответствующий разряд регистра устанавливается в “1”.
В регистр счетчика секторов (SC – 1F2h) заносится количество секторов, которое должно быть считано или записано (при записи 0 в этот регистр происходит обработка 256 секторов) на носитель. Значение этого регистра уменьшается на единицу после обработки каждого сектора. При выполнении мультисекторной операции секторы должны располагаться на диске последовательно, друг за другом (то есть область данных должна быть непрерывной). Регистр SC доступен не только для записи, но и для считывания. В случае возникновения ошибки при выполнении операции чтения или записи в этом регистре будет находиться число секторов, оставшихся необработанными.
В регистр номера сектора (SN – 1F3h) в режиме CHS загружается стартовый номер сектора при операциях чтения/записи. После обработки каждого сектора в этот регистр автоматически заносится номер следующего сектора, подлежащего обработке. Регистр доступен для чтения и для записи. После выполнения команды он содержит номер последнего обработанного сектора. В режиме LBА регистр номера сектора содержит младший байт линейного адреса сектора (разряды 0-7).
Регистры младшего (CL – 1F4h) и старшего (СН – 1F5h) байтов номера цилиндра в режиме CHS определяют стартовый цилиндр для выполнения команды. Регистры доступны для чтения и для записи. После выполнения команды они содержат текущий адрес цилиндра. В режиме LBA регистр CL содержит разряды 8-15, а регистр СН — разряды 16-23 линейного адреса сектора.
Регистр состояния (SR – 1F7h) отображает состояние устройства и доступен только для чтения.
Регистр команд (CR – 1F7h) используется для загрузки кода выполняемой команды. Запись кода команды должна проводиться в последнюю очередь, т.е. только после того, как в остальные регистры занесены все необходимые для ее выполнения данные. Выполнение команды начинается сразу после записи кода в этот регистр.
Регистр выбора НЖМД /номера головки (1F6h) содержит биты D3-D0 для выбора головки, бит D4 для выбора НЖМД и биты D6 и D5, задающие размер сектора (01-512 байт).
Команды АТА
В соответствии со стандартом команды интерфейса АТА делятся на три основные группы:
- обязательные команды;
- дополнительные команды;
- специфические команды.
В [1] (Глава “Работа с дисками”) дано описание команд, необходимых для работы с современными дисководами, и, потому, обязательных для всех выпускаемых устройств.
Команда контроллера НЖМД (КНЖМД) состоит из одного байта и выполняется сразу после занесения в регистр команд (1F7h). Вследствие этого, необходимо предварительно загрузить параметры в соответствующие порты КНЖМД, если он находится в состоянии “не занят” (бит D7 регистра состояния равен нулю). Перечень команд КНЖМД приведен в таблице 1.
Таблица 1
Команда |
Биты |
|||||||
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
Поиск |
0 |
1 |
1 |
1 |
R3 |
R2 |
R1 |
R0 |
Чтение секторов |
0 |
0 |
1 |
0 |
0 |
0 |
L |
T |
Запись секторов |
0 |
0 |
1 |
1 |
0 |
0 |
L |
T |
Верификация секторов |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
T |
Инициализация параметров НЖМД |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
Диагностика |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
Обозначение:
L = 0 – нормальный режим; L = 1 – длинный режим; T = 0 – разрешение повтора; T = 1 – запрет повтора; R3-R0 – скорость позиционирования: 0000 – 35 мкс/шаг…. 1111 – 16 мкс/шаг.
Режимы и протоколы передачи информации
Обмен информацией между жестким диском, обозначенным в стандарте термином Device (устройство), и компьютером, обозначенным как Host (хост), должен выполняться по строго определенным правилам.
Для обмена данными между диском и контроллером используются 16-разрядные слова в пакетах по 256 штук. При работе с современными жесткими дисками может применяться один из двух основных режимов передачи данных: режим программного ввода-вывода (PIO) через процессор или режим прямого доступа к памяти (DMA). Оба режима постоянно совершенствуются и в настоящее время имеют несколько вариантов реализации, отличающихся все более высокой скоростью передачи данных между контроллером и устройством. Сравнительный анализ режимов приведён в [1].
В программах, предназначенных для работы в MS-DOS, можно ограничиться простыми протоколами ввода-вывода РIO, поскольку значительно более сложный для реализации протокол DMA дает выигрыш по скорости только в многозадачном режиме.
Лабораторное задание
1. Ознакомиться с литературой и разобраться с работой программ.
2. Ознакомиться с внутренним устройством и общими принципами функционирования жестких дисков.
3. Изучить функциональное назначение регистров контроллера жесткого диска и режимы адресации данных.
4. Ознакомиться с обязательными командами интерфейса АТА.
5. Запустить демонстрационный пример , разобраться в его работе.
6. Написать на Ассемблере программу, которая бы выполняла чтение определенного сектора или верификацию сектора; чтение состояния НЖМД или внутреннюю диагностику; чтение регистра ошибок или чтение регистра состояния НЖМД, т.е. программную реализацию соответствующих функций BIOS.
Листинг программы 1:
;Поиск подключённых жёстких дисков по каналам
;1 и 2
; Автор текста программ Кулаков Владимир ;Геннадьевич.
IDEAL
P386
LOCALS
MODEL MEDIUM
; подключить файл мнемонических обозначений
; кодов управляющих клавиш
include "lst_2_03.inc"
include "lst_2_05.inc"
DATASEG
; текстовое сообщение
Txt1 DB LIGHTCYAN,0,26,"ИДЕНТИФИКАЦИЯ ЖЕСТКИХ ДИСКОВ",0
DB YELLOW,24,35,"Ждите ...",0
Txt2 DB 2,27,"На канале найден диск .",0
DB 4,25,"Параметры обнаруженного диска:",0
DB 6,22,"общая информация:",0
DB 7,12,"число логических цилиндров:",0
DB 8,14," число логических головок:",0
DB 9,13," число логических секторов:",0
DB 10,24,"серийный номер:",0
DB 11,32,"модель:",0
DB 12,8,"макс.кол-во секторор за сеанс:",0
DB 13,27, "возможности:",0
DB 14,10,"текущее число лог.цилиндров:",0
DB 15,12," текущее число лог.головок:",0
DB 16,11," текущее число лог.секторов:",0
DB 17,13,"текущая ёмкость секторов:",0
DB 18,11,"число секторов в режиме LBA:",0
DB 19,13,"поддерживаемые режимы DMA:",0
DB 20,17,"улучшенные режимы PIO:",0
Txt3 DB LIGHTGREEN
DB 12,24,"Поиск завершён, больше нет дисков",0
AnyK DB YELLOW,24,29,"Нажмите любую клавишу",0
ENDS
SEGMENT sseg para stack 'STACK'
DB 400h DUP(?)
ENDS
CODESEG
;*****************************
;* основной модуль программы *
;*****************************
PROC IdentifyDevices
mov AX,DGROUP
mov DS,AX
; установить текстовый режим и очистить экран
mov AX,3
int 10h
; Скрыть курсор
mov [ScreenString],25
mov [ScreenColumn],0
call SetCursorPosition
; Вывести текстовые сообщения на экран
mov SI,offset Txt1
call ShowColorString
call ShowColorString
; Цикл опроса каналов
mov [ChannelNumber],1
; Опросить Master-диск
@@AskMaster:
call ClearPrevInfo
mov [HDDNumber],0
call ReadHDD_ID
cmp [HDDErrorCode],0
jne @@AskSlave
call ShowHDD_ID
; опросить Slave-диск
@@AskSlave:
call ClearPrevInfo
mov [HDDNumber],1
call ReadHDD_ID
cmp [HDDErrorCode],0
jne @@NextCannel
call ShowHDD_ID
@@NextCannel:
inc [ChannelNumber]
cmp [ChannelNumber],3
jb @@AskMaster
@@End: ; выдать сообщение о завершении поиска
call ClearPrevInfo
mov SI,offset Txt3
call ShowColorString
call ShowColorString
call GetChar
; переустановить текстовый режим
mov ax,3
int 10h
; выход в DOS
mov AH,4Ch
int 21h
ENDP IdentifyDevices
;************************************
; РАСШИФРОВКА ИДЕНТИФИКАТОРА ДИСКА*
;************************************
PROC ShowHDD_ID near
pushad
mov [TextColorAndBackground],LIGHTGREEN
mov CX,17
mov SI,offset Txt2
@@NextStr:
call ShowString
loop @@NextStr
mov SI,offset AnyK
call ShowColorString
; “бв ®ўЁвм ЎҐ«л© 梥⠨ зҐал© д®
mov [TextColorAndBackground],WHITE
; вывести номер канала и номер диска
mov [ScreenString],2
mov [ScreenColumn],37
mov AX,[ChannelNumber]
call ShowDecWord
mov [ScreenColumn],51
mov AL,[HDDNumber]
call ShowDecByte
; вывести отдельные поля идентификатора
mov [ScreenString],6
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer]
call ShowBinWord
; — число лог.цилиндров
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+1*2]
call ShowDecWord
; число лог.головок
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+3*2]
call ShowDecWord
; число логюсекторов
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+6*2]
call ShowDecWord
;серийный номер
mov AX,0B800h
mov ES,AX
mov SI,offset SectorDataBuffer
add SI,10*2
mov DI,(10*80+40)*2
mov AH,[TextColorAndBackground]
mov CX,10
@@NextWord1:
mov DX,[SI]
mov AL,DH
stosw
mov AL,DL
stosw
add SI,2
loop @@NextWord1
; Ќ®¬Ґа ¬®¤Ґ«Ё
mov SI,offset SectorDataBuffer
add SI,27*2
mov DI,(11*80+40)*2
mov AH,[TextColorAndBackground]
mov CX,20
@@NextWord2:
mov DX,[SI]
mov AL,DH
stosw
mov AL,DL
stosw
add SI,2
loop @@NextWord2
; Њ Єб. Є®«-ў® ᥪв®а®ў § ᥠб
add [ScreenString],3
mov [ScreenColumn],40
mov AL,[SectorDataBuffer+47*2]
call ShowDecByte
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+49*2]
call ShowBinWord
test [word ptr SectorDataBuffer+53*2],1
jz @@NotValid5458
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+54*2]
call ShowDecWord
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+55*2]
call ShowDecWord
; ’ҐЄг饥 зЁб«® «®ЈЁзҐбЄЁе ᥪв®а®ў
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[word ptr SectorDataBuffer+56*2]
call ShowDecWord
; ’ҐЄгй п Ґ¬Є®бвм, ᥪв®а®ў
inc [ScreenString]
mov [ScreenColumn],40
mov EAX,[dword ptr SectorDataBuffer+57*2]
call ShowDecDWord
@@NotValid5458:
; —Ёб«® ᥪв®а®ў ў ०Ё¬Ґ LBA
mov [ScreenString],18
mov [ScreenColumn],40
mov EAX,[dword ptr SectorDataBuffer+60*2]
call ShowDecDWord
inc [ScreenString]
mov [ScreenColumn],40
mov AL,[SectorDataBuffer+63*2]
call ShowByteBinCode
test [word ptr SectorDataBuffer+53*2],10b
jz @@NotValid6470
inc [ScreenString]
mov [ScreenColumn],40
mov AL,[SectorDataBuffer+64*2]
call ShowByteBinCode
@@NotValid6470:
; ожидать нажатия клавиши
call GetChar
popad
ret
ENDP ShowHDD_ID
;**************************************
;* ОЧИСТИТЬ ЭКРАН И ВЫВЕСТИ ЗАГОЛОВКИ*
;**************************************
PROC ClearPrevInfo near
pushad
call ClearScreen
; ВЫВЕСТИ ТЕКСТОВОЕ СООБЩЕНИЕ
mov SI,offset Txt1
call ShowColorString
call ShowColorString
popad
ret
ENDP ClearPrevInfo
ENDS
include "lst_2_02.inc"
include "lst_3_05.inc"
include "lst_7_07.inc"
END
Результат программы:
Вывод: данная программа организует поиск подключённых жёстких дисков по каналам 1 и 2. На экран выводятся обнаруженного диска.
Листинг программы 2:
; Просмотр секторов «ведущего» жёсткого диска
; канала 1 в режиме LBA
;
IDEAL
P386
LOCALS
MODEL MEDIUM
include "lst_2_03.inc"
include "lst_2_05.inc"
DATASEG
; Тукстовые сообщения
Txt1 DB LIGHTCYAN,0,16,"Просмотр секторов "
DB "жесткого диска в ASCII-кодах",0
DB LIGHTGREEN,5,8,"сектор N :",0
DB LIGHTCYAN,17,8,"управляющие клавиши:",0
DB YELLOW,24,27,"Нажмите управляющую клавишу",0
Txt2 DB 19,8,"стрелка вниз-следующий сектор",0
DB 20,8,"стрелка вверх-предыдущий сектор",0
DB 21,8,"Esc - выход.",0
Err1 DB LIGHTRED,12,21
DB "Master-диск на канале 1 не обнаружен.",0
Err2 DB LIGHTRED,12,24
DB "Диск не поддерживает режим LBA.",0
PBut DB YELLOW,24,29,"Нажмите любую клавишу",0
ENDS
SEGMENT sseg para stack 'STACK'
DB 400h DUP(?)
ENDS
CODESEG
;*****************************
;* Основной модуль программы*
;*****************************
PROC ShowHDDSector
mov AX,DGROUP
mov DS,AX
; установить текстовый режим и очистить экран
mov AX,3
int 10h
; скрыть курсор
mov [ScreenString],25
mov [ScreenColumn],0
call SetCursorPosition
; опросить Master-диск канала 1
mov [ChannelNumber],1
mov [HDDNumber],0
call ReadHDD_ID
; диск подключен?
cmp [HDDErrorCode],0
jne @@DiskNotFound
; режим LBA поддерживается?
cmp [dword ptr SectorDataBuffer+60*2],0
je @@LBANotSupported
; вывести текстовые сообщения на экран
mov CX,4
mov SI,offset Txt1
@@Txt1: call ShowColorString
loop @@Txt1
; установить зеленый цвет и черный цвет фона
mov [TextColorAndBackground],LIGHTGREEN
mov SI,offset Txt2
call ShowString
call ShowString
call ShowString
; инициализируем переменные
mov [HDDNumber],0
mov [dword ptr SectorAddress],0
mov AX,0B800h
mov ES,AX
; ВНЕШНИЙ ЦИКЛ
@@ReadSector:
mov [ScreenString],5
mov [ScreenColumn],17
mov EAX,[SectorAddress]
call ShowHexDword
call ReadHDDSector
mov DI,7*160+8*2
mov SI,offset SectorDataBuffer
mov AH,LIGHTCYAN+BLUE*16
mov DX,8 ;бзҐвзЁЄ бва®Є
@@OutNextString:
mov CX,64 ;бзҐвзЁЄ бЁ¬ў®«®ў ў бва®ЄҐ
@@OutNextChar:
lodsb
stosw
loop @@OutNextChar
add DI,16*2
dec DX
jnz @@OutNextString
@@GetCommand:
; ОЖИДАЕМ ВВОДА СЛЕДУЮЩЕЙ команды
call GetChar
cmp AL,0
je @@TestCommandByte
call Beep
jmp short @@GetCommand
@@TestCommandByte:
cmp AH,B_Esc ;"Выход"
je @@End
@@TestDn:
cmp AH,B_DN ;"Стрелка вниз"
jne @@TestUp
; Увеличить на 1 номер сектора
inc [dword ptr SectorAddress]
jmp @@ReadSector
@@TestUp:
cmp AH,B_UP
jne @@CommandError
cmp [dword ptr SectorAddress],0
je @@CommandError
; Уменьшить на 1 номер счектора
dec [dword ptr SectorAddress]
jmp @@ReadSector
@@CommandError:
call Beep
jmp @@GetCommand
@@DiskNotFound:
mov SI,offset Err1
call ShowColorString
mov SI,offset PBut
call ShowColorString
call GetChar
jmp short @@End
@@LBANotSupported:
; Сообщение»Диск не поддерживает» LBA"
mov SI,offset Err2
call ShowColorString
mov SI,offset PBut
call ShowColorString
call GetChar
@@End: ; переустановить текстовый режим
mov ax,3
int 10h
; ‚л室 ў DOS
mov AH,4Ch
int 21h
ENDP ShowHDDSector
ENDS
include "lst_2_02.inc"
include "lst_7_07.inc"
END
Результат программы:
Вывод: данная программа обеспечивает просмотр секторов «ведущего» жёсткого диска канала 1 в режиме LBA. Просмотр секторов жесткого диска происходит в ASCII-кодах. На экране отображаются управляющие клавиши.
Листинг программы 3:
; Просмотр в режиме LBA параметроа логических дисков
; на «ведущем» жестком диске канала 1.
IDEAL
P386
LOCALS
MODEL MEDIUM
include "lst_2_03.inc"
include "lst_2_05.inc"
DATASEG
; Текстовые сообщения
Txt00 DB YELLOW,24,29,"Нажмите любую клавишу",0
Txt01 DB YELLOW,0,30
DB "MASTER-диск канала 1
DB YELLOW,1,22
DB "ТАБЛИЦА РАЗДЕЛОВ ЛОГИЧЕСКОГО ДИСКА
Txt02 DB 8,1,"N",0
DB 8,4,"Тип
DB 8,9,"Призн9,9,"Акт.
DB 8,16," Начало раздела ",0
DB 9,17,"Цил.",0,9,24, "Сект",0,9,31,"‘ҐЄв.",0
DB 8,37," Конец раздела ",0
DB 9,38,"Гол..",0,9,45,"Цил.",0,9,52,"Сект.",0
DB 8,58,"Номер нач.",0
DB 9,58,"сектора ",0
DB 8,70,"размер",0
DB 9,70,"секторов",0
Txt11 DB YELLOW,0,19
DB "ЗАГРУЗОЧНАЯ ЗАПИСЬ ЛОГИЧЕСКОГО ДИСКА N",0
Txt12 DB 2,12,"ид.изгот:",0
DB 3,22,"Байтов на сектор:",0
DB 4,19,"Секторов в кластере:",0
DB 5,14,"Число резервных секторов:",0
DB 6,23,"Число копий FAT:",0
DB 7,6,"„Дескрипторов в корневом каталоге:",0
DB 8,14,"Число секторов в ращзделе:",0
DB 9,15,"Тип носителя инф:",0
DB 10,1,"Число секторов, занимаемы копией FAT:",0
DB 11,13,"число секторов на дорожке:",0
DB 12,1,"Количество рабочих поверхностей диска:",0
DB 13,16,"Число скрытых секторов:",0
Txt13 DB 14,23,"№дисковола :",0
DB 15,15,"№ лог диска :",0
DB 16,27,"Метка диска :",0
DB 17,9,"Аббревиатура файловой системы:",0
Txt14 DB 14,20,"№ активной FAT:",0
DB 15,22,"Номер версии FAT:",0
DB 16,0
DB "Номер на.кластера :",0
DB 17,8," FSINFO:",0
DB 18,4," Boot:",0
DB 19,23,"Номер дисковода:",0
DB 20,15,"номер лог д :",0
DB 21,27,"ЊҐвЄ ¤ЁбЄ :",0
DB 22,9," Аббревиатура файловой системы:",:",0
Err1 DB LIGHTRED,12,22
DB "Master-диск на канале ",0 не обнаружен
Err2 DB LIGHTRED,12,25
ENDS
SEGMENT sseg para stack 'STACK'
DB 400h DUP(?)
ENDS
CODESEG
;*****************************
;* ОСНОВНОЙ МОДУЛЬ ПРОГРАММЫ *
;*****************************
PROC SearchLogicalDisks
mov AX,DGROUP
mov DS,AX
; УСТАНОВКА ТЕКСТОВОГО РЕЖИМА
mov AX,3
int 10h
; скрыть курсор
mov [ScreenString],25
mov [ScreenColumn],0
call SetCursorPosition
mov [ChannelNumber],1
mov [HDDNumber],0
call ReadHDD_ID
cmp [HDDErrorCode],0
cmp [dword ptr SectorDataBuffer+60*2],0
je @@LBANotSupported
mov [LogicalDriveNumber],0
mov [CurrentDrive_StartSector],0
mov [dword ptr SectorAddress],0
call ReadHDDSector
;Отобразить таблицу разделов
call ShowPartitionTable
;найти и записать номера нач.секторов;
mov [NextDrivePresent],0
mov SI,offset SectorDataBuffer
add SI,1BEh ;смещение первойзаписи
mov AL,[SI+4]
;проверить код основного раздела
cmp AL,01h
je @@PrimPartFound
cmp AL,04h
je @@PrimPartFound
cmp AL,06h
je @@PrimPartFound
cmp AL,0Bh
je @@PrimPartFound
cmp AL,0Eh
jne @@PrimPartNotFound
@@PrimPartFound:
; найден основной раздел
mov EAX,[SI+8] ;извлечь адрес сектора
mov [PriDOS_StartSector],EAX
add SI,10h ;смещение второй записи
mov AL,[SI+4] ;извлечь тип раздела
cmp AL,05h
je @@ExtPartFound
cmp AL,0Ch
je @@ExtPartFound
cmp AL,0Fh
jne @@NextDriveNotPresent0
@@ExtPartFound:
;имеется расширенный раздел
mov EAX,[SI+8]
mov [ExtDOS_StartSector],EAX
mov [NextDrivePresent],1
@@NextDriveNotPresent0:
; прочитать BOOT-сектор основного раздела
mov EAX,[PriDOS_StartSector]
mov [SectorAddress],EAX
call ReadHDDSector
; отобразить данные BOOT-сектора
call DecodeBootSector
;имеетмся след.диск?
cmp [NextDrivePresent],0
je @@End
mov EAX,[ExtDOS_StartSector]
mov [CurrentDrive_StartSector],EAX
;ЦИКЛ ОПРОСА ЛОГИЧЕСКИХ ДИСКОВ РАСШИРЕННОГО РАЗДЕЛА
@@ReadSMBR:
inc [LogicalDriveNumber]
mov EAX,[CurrentDrive_StartSector]
mov [BootSector],EAX
mov [SectorAddress],EAX
call ReadHDDSector
call ShowPartitionTable
mov [NextDrivePresent],0
mov SI,offset SectorDataBuffer
add SI,1BEh
mov EAX,[SI+8]
add [BootSector],EAX
add SI,10h
mov EAX,[SI+8]
cmp EAX,0
je @@NextDriveNotPresent1
add EAX,[ExtDOS_StartSector]
mov [CurrentDrive_StartSector],EAX
; УСТАНОВИТЬ ПРИЗНАК НАЛИЧИЯ СЛЕД.ДИСКА
mov [NextDrivePresent],1
@@NextDriveNotPresent1:
mov EAX,[BootSector]
mov [SectorAddress],EAX
call ReadHDDSector
; Ћв®Ўа §Ёвм ¤ лҐ BOOT-ᥪв®а
call DecodeBootSector
cmp [NextDrivePresent],0
je @@End
jmp @@ReadSMBR
; обработка ошибок
@@DiskNotFound:
; сообщение «диск не найден»
mov SI,offset Err1
jmp short @@AllErr
@@LBANotSupported:
mov SI,offset Err2
jmp short @@AllErr
@@PrimPartNotFound:
mov SI,offset Err3
@@AllErr:
;общая часть обр.ошибок
call ShowColorString
mov SI,offset PBut
call ShowColorString
call GetChar
@@End:
mov ax,3
int 10h
; выход в DOS
mov AH,4Ch
int 21h
ENDP SearchLogicalDisks
;*****************************************
;* ПРОЧИТАТЬ НУЛЕВОЙ СЕКТОР И ОТОБРАЗИТЬ НА ЭКРАН ТУБЛИЦУ РАЗДЕЛОВ *
;*****************************************
PROC ShowPartitionTable near
pushad
push ES
call ClearScreen
mov SI,offset Txt00
call ShowColorString
mov SI,offset Txt01
call ShowColorString
call ShowColorString
mov [ScreenString],1
mov [ScreenColumn],57
mov [TextColorAndBackground],YELLOW
mov AL,[LogicalDriveNumber]
call ShowByteHexCode
mov AX,0B800h
mov ES,AX
mov DI,8*80*2
mov AH,LIGHTBLUE
mov AL,0B3h
mov DX,7
push DI
add DI,3*2
mov [ES:DI],AX
add DI,5*2
mov CX,8
@@ac1: mov [ES:DI],AX
add DI,7*2
loop @@ac1
add DI,4*2
mov [ES:DI],AX
pop DI
add DI,80*2
dec DX
jnz @@ac0
; Уст.зеленый цвет
mov [TextColorAndBackground],LIGHTGREEN
mov CX,16
mov SI,offset Txt02
@@NextStr1:
call ShowString
loop @@NextStr1
; ЦИКЛ ВВОДА ДВННЫХ
mov [TextColorAndBackground],WHITE
mov [PartitionNumber],1
mov SI,offset SectorDataBuffer
add SI,1BEh
mov [ScreenString],11
@@ShS0: mov AL,[PartitionNumber]
mov [ScreenColumn],0
call ShowByteHexCode
lodsb
mov [ScreenColumn],11
call ShowByteHexCode
; НОМЕР НАЧ. ПОВЕРХНОСТИ
lodsb
mov [ScreenColumn],18
call ShowByteHexCode
lodsw
mov BL,AL
shr AL,6
xchg AL,AH
mov [ScreenColumn],24
call ShowHexWord
mov AL,BL
and AL,0111111b
mov [ScreenColumn],32
call ShowByteHexCode
mov [ScreenColumn],5
lodsb
call ShowByteHexCode
mov [ScreenColumn],39
lodsb
call ShowByteHexCode
lodsw
mov BL,AL
shr AL,6
xchg AL,AH
mov [ScreenColumn],45
call ShowHexWord
mov AL,BL
and AL,0111111b
mov [ScreenColumn],53
call ShowByteHexCode
; отобразить код признака активного разжела
mov [ScreenColumn],59
mov EAX,[SI]
add SI,4
call ShowHexDWord
mov [ScreenColumn],70
mov EAX,[SI]
add SI,4
call ShowHexDWord
inc [ScreenString]
inc [PartitionNumber]
cmp [PartitionNumber],5
jb @@ShS0
call GetChar
pop ES
popad
ret
ENDP ShowPartitionTable
;**********************************************
;* ОТОБРАЗИТЬ ИНФОРМАЦИЮ ЗАГРУЗОЧНОГО СЕКТОРА*
;**********************************************
PROC DecodeBootSector near
pushad
push ES
call ClearScreen
mov SI,offset Txt00
call ShowColorString
mov SI,offset Txt11
call ShowColorString
mov [ScreenString],0
mov [ScreenColumn],58
mov [TextColorAndBackground],YELLOW
mov AL,[LogicalDriveNumber]
call ShowByteHexCode
mov [TextColorAndBackground],LIGHTGREEN
mov CX,12
mov SI,offset Txt12
@@NextStr1:
call ShowString
loop @@NextStr1
BPB_TotSec32
call ShowHexWord
@@UseTotSec32:
inc [ScreenString]
mov [ScreenColumn],40
mov AL,[SI+15h]
call ShowByteHexCode
; ЧИСЛО СЕКТОРОВ
mov [ScreenString],8
mov [ScreenColumn],40
mov EAX,[SI+20h]
cmp EAX,0
je @@UseTotSec16 ;ЁбЇ®«м§®ў вм BPB_TotSec16
call ShowHexDWord
@@UseTotSec16:
mov CX,9
mov SI,offset Txt14
@@NextStr3:
call ShowString
loop @@NextStr3
mov SI,offset SectorDataBuffer
; число секторов FAT32
mov [ScreenString],10
mov [ScreenColumn],40
mov EAX,[SI+24h]
call ShowHexDWord
mov [ScreenString],14
mov [ScreenColumn],40
mov AX,[SI+28h]
call ShowHexWord
; число секторов FAT
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[SI+2Ah]
call ShowHexWord
inc [ScreenString]
mov [ScreenColumn],40
mov EAX,[SI+2Ch]
call ShowHexDWord
; FSINFO
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[SI+30h]
call ShowHexWord
inc [ScreenString]
mov [ScreenColumn],40
mov AX,[SI+32h]
call ShowHexWord
; отобр.№дисковода
inc [ScreenString]
mov [ScreenColumn],40
mov AL,[SI+40h]
call ShowByteHexCode
; от.№ ЛОГ.ДИСКА
inc [ScreenString]
mov [ScreenColumn],40
mov EAX,[SI+43h]
call ShowHexDWord
; от.метку диска
inc [ScreenString]
mov [ScreenColumn],40
mov BX,47h
mov CX,11
call ShowASCIIField
; ОТОБР.АБ.
inc [ScreenString]
mov [ScreenColumn],40
mov BX,52h
mov CX,8
call ShowASCIIField
@@End: call GetChar
pop ES
popad
ret
ENDP DecodeBootSector
;**********************************************
;ВЫВОД НА ЭКРАН ТЕКСТОВОГО ПОЛЯ ДАННЫХ
;**********************************************
PROC ShowASCIIField near
pusha
push ES
mov AX,0B800h
add SI,BX
; вычислить начальную позицию
mov AX,[ScreenString]
mov DI,160
mul DI
add AX,[ScreenColumn]
add AX,[ScreenColumn]
mov DI,AX
mov AH,[TextColorAndBackground]
@@NextChar:
lodsb
stosw
loop @@NextChar
pop ES
popa
ret
ENDP ShowASCIIField
ENDS
include "lst_7_07.inc"
END
Результат программы:
Вывод: данная программа обеспечивает просмотр в режиме LBA параметров логических дисков на «ведущем» жестком диске канала 1.На экран выводятся и начало раздела, и конец раздела, а также номер начального сектора и размер секторов.
Листинг программы 4:
;Программа, которая ищет в корневом каталоге
; «ведущего» диска канала 1 файл AUTOEXEC.BAT,
; считывает его и отображает на экране
IDEAL
P386
LOCALS
MODEL MEDIUM
include "lst_2_03.inc"
include "lst_2_05.inc"
;размер RootDirSize equ 32
FATAreaAddress equ 110000h
DATASEG
; Текстовые сообщения
Txt00 DB YELLOW,24,29,"Нажмите ",0
Txt20 DB YELLOW,0,25," FAT:",0
Txt30 DB YELLOW,0,23
DB "Сп ф корневого каталога :",0
Txt40 DB YELLOW,0,16,"Просмотр нач "
DB "гз бвЄ д ©« AUTOEXEC.BAT:",0
Err1 DB LIGHTRED,12,21
DB "Master-диск на канале 1 не обнаружен.",0
Err2 DB LIGHTRED,12,24
DB "Диск не поддерживает режим LBA.",0
PBut DB YELLOW,24,29,"Нажмите люб кл",0
; Номер раздела
PartitionNumber DB ?
PriDOS_StartSector DD ?
BootSector DD ?
FATType DB ?
NextDrivePresent DB ?
SectorsInCluster DW ?
RSects DD ?
FATsOnDisk DW ?
FATSize DW ?
HiddenSectors DD ?
ENDS
SEGMENT sseg para stack 'STACK'
DB 400h DUP(?)
ENDS
CODESEG
;*****************************
;* Основной МОДУЛЬ *
;*****************************
PROC SearchAutoexecBat
mov AX,DGROUP
mov DS,AX
; текстовый режим
mov AX,3
int 10h
call Initialization
mov [ScreenString],25
mov [ScreenColumn],0
call SetCursorPosition
; опросить Master-диск
mov [ChannelNumber],1
mov [HDDNumber],0
call ReadHDD_ID
cmp [HDDErrorCode],0
jne @@DiskNotFound
cmp [dword ptr SectorDataBuffer+60*2],0
je @@LBANotSupported
mov [dword ptr SectorAddress],0
call ReadHDDSector
; зап номер нач сектора
mov SI,offset SectorDataBuffer
add SI,1BEh
mov EAX,[SI+8]
mov [PriDOS_StartSector],EAX
; определить тип FAT
mov [FATType],1
mov EAX,[PriDOS_StartSector]
mov [SectorAddress],EAX
call ReadHDDSector
mov SI, offset SectorDataBuffer
movzx AX,[byte ptr SI+0Dh]
mov [SectorsInCluster],AX
movzx EAX,[word ptr SI+0Eh]
mov [RSects],EAX
movzx AX,[byte ptr SI+10h]
mov [FATsOnDisk],AX
mov AX,[SI+16h]
mov [FATSize],AX
; число скрытых секторов
mov EAX,[SI+1Ch]
mov [HiddenSectors],EAX
; ПРОЧИТАТЬ И ПОКАЗАТЬ FAT
call ClearScreen
mov SI,offset Txt20
call ShowColorString
mov SI,offset Txt00
call ShowColorString
mov EAX,[PriDOS_StartSector]
add EAX,[RSects]
mov [FATStartSect],EAX
mov [SectorAddress],EAX
mov EDI,FATAreaAddress
mov DX,[FATSize] ;бзҐвзЁЄ ᥪв®а®ў FAT
@@NextFATSector:
call ReadHDDSector
inc [dword ptr SectorAddress]
mov SI, offset SectorDataBuffer
mov CX,512
@@NextFATSectByte:
lodsb
mov [GS:EDI],AL
inc EDI
loop @@NextFATSectByte
dec DX
mov [ScreenString],2
mov [ScreenColumn],0
mov EDI,FATAreaAddress
mov CX,256
@@FAT: mov AX,[GS:EDI]
call ShowHexWord
inc [ScreenColumn]
add EDI,2
loop @@FAT
call GetChar
movzx EAX,[FATSize]
movzx EDX,[FATsOnDisk]
mul EDX
add EAX,[FATStartSect]
mov [RootDirStartSect],EAX
mov [SectorAddress],EAX
mov EDI,RootDirAddress
mov DX,RootDirSize
@@NextRootSector:
@@NextRootByte:
lodsb
mov [GS:EDI],AL
inc EDI
loop @@NextRootByte
dec DX
jnz @@NextRootSector
mov AX,0B800h
mov ES,AX
mov DI,160*2
mov ESI,RootDirAddress
mov AH,WHITE
mov DX,100 ;бзҐвзЁЄ § ЇЁбҐ©
@@NextFileName:
mov CX,11
@@NextNameByte:
mov AL,[GS:ESI]
stosw
inc [ScreenColumn]
inc ESI
loop @@NextNameByte
add DI,(16-11)*2
add ESI,32-11
dec DX
jnz @@NextFileName
call GetChar
call ClearScreen
mov SI,offset Txt40
call ShowColorString
mov SI,offset Txt00
call ShowColorString
; найти в корневом каталоге AUTOEXEC.BAT
mov ESI,RootDirAddress
mov CX,512 @@NextElement:
cmp [dword ptr GS:ESI],'OTUA'
jne @@NotAutoexec
cmp [dword ptr GS:ESI+4],'CEXE'
jne @@NotAutoexec
cmp [word ptr GS:ESI+8],'AB'
jne @@NotAutoexec
cmp [byte ptr GS:ESI+10],'T'
je @@AutoexecFileFound
@@NotAutoexec:
add ESI,32
loop @@NextElement
add EAX,[RootDirStartSect]
add EAX,RootDirSize
mov [FileStartSect],EAX
mov [SectorAddress],EAX
mov EDI,FileBufferAddress
mov DX,[SectorsInCluster]
@@NextFileSector:
call ReadHDDSector
inc [dword ptr SectorAddress]
mov SI, offset SectorDataBuffer
mov CX,512
@@NextFileByte:
lodsb
mov [GS:EDI],AL
inc EDI
loop @@NextFileByte
dec DX
jnz @@NextFileSector
mov AX,0B800h
mov ES,AX
mov DI,160*2
mov ESI,FileBufferAddress mov ECX,[FileSize mov DX,0 ;счетчик строк
mov BX,0 ; счетчик колонок
mov AH,LIGHTGREEN
@@Out1:
mov AL,[GS:ESI]
inc ESI
cmp AL,0Dh
jz @@Out2
; проверка символа
cmp AL,0Ah
jz @@Out3
; вывести символ на экран
stosw
inc BX
cmp BX,80
jb @@Out3
@@Out2: add DI,160
sub DI,BX
sub DI,BX
mov BX,0
inc DX
cmp DX,22
ja @@OutEnd
@@Out3: dec ECX
jnz @@Out1
@@OutEnd:
call GetChar
jmp short @@End
@@DiskNotFound:
mov SI,offset Err1
call ShowColorString
mov SI,offset PBut
call ShowColorString
call GetChar
jmp short @@End
@@LBANotSupported:
mov SI,offset Err1
call ShowColorString
mov SI,offset PBut
call ShowColorString
call GetChar
mov ax,3
int 10h
mov AH,4Ch
int 21h
ENDP SearchAutoexecBat
ENDS
include "lst_7_07.inc"
END
Результат программы:
Вывод: данная программа обеспечивает поиск в корневом каталоге «ведущего» диска канала 1 файл AUTOEXEC.BAТ,считывает его и отображает на экране. На экран выводится начальная область первой FAT, список файлов корневого каталога, просмотр начального участка файла AUTOEXEC.BAТ.
Листинг программы 5:
; Программа, выполняющая считывание загрузочного
; сектора Master-диска канала 1 в режиме DMA
IDEAL
P386
LOCALS
MODEL MEDIUM
include "lst_2_05.inc"
DATASEG
; Текстовые сообщения
Txt0 DB LIGHTCYAN,0,17
DB "ТЕСТИРОВАНИЕ РЕЖИМА DMA MASTER-ДИСКА КАНАЛА1",0
DB YELLOW,5,8,"Содержимое загрузочного сектора "
DB "Master-диск канала 1:",0
AnyK DB YELLOW,24,29,"нажмите клавишу",0
NoPCI DB LIGHTRED,12,18
DB "не поддерживается PCI BIOS",0
NoIDEC DB LIGHTRED,12,26
DB "Контроллер PCI IDE не найден,0
BadReg DB LIGHTRED,12,28,"неверный номер регистра ",0
NoHDD DB LIGHTRED,12,21
DB "Master-диск на канаое 1 не обнаружен",0
NoLBA DB LIGHTRED,12,24
DB "Диск не поддердивает LBA.",0
DErr1 DB LIGHTRED,12,8,"Тайм-аут "
DErr4 DB LIGHTRED,12,27,"неправильный номер канала.",0
DErr5 DB LIGHTRED,12,26," неправильный номер диска.",0
DErr6 DB LIGHTRED,12,17," неправильный номер головки"
DB "Ошибка при выполнении.",0
ENDS
; буфер для работы с диском в режиме DMA
SEGMENT DMA_BUF para public 'DATA'
DB 8000h DUP(?)
ENDS
; буфер для таблицы PRD
SEGMENT PRD_Table para public 'DATA'
DB 1024 DUP(?)
ENDS
SEGMENT sseg para stack 'STACK'
DB 400h DUP(?)
ENDS
CODESEG
;*****************************
;* ОСНОВНОЙ МОДУЛЬ ПРОГРАММЫ*
;*****************************
PROC IDE_DMA_Test
mov AX,DGROUP
mov DS,AX
; ТЕКС.РЕЖИМ
mov AX,3
int 10h
; скрыть курсор
mov [ScreenString],25
mov [ScreenColumn],0
call SetCursorPosition
; вывести заголовок на экран
mov SI,offset Txt0
call ShowColorString
call ShowColorString
; задать номер канала и номер диска
mov [ChannelNumber],1
mov [HDDNumber],0
call HDD_Presence_Test
call SearchBusMasterIDEContr
mov AX,PRD_Table
mov ES,AX
xor EAX,EAX
mov AX,DMA_BUF
shl EAX,4
mov [ES:0],EA ; записать кол-во передаваемых байтов
mov [word ptr ES:4],512
mov [word ptr ES:6],8000h
xor EAX,EAX
mov AX,PRD_Table
shl EAX,4
; вычислить адрес регистра контроллера
mov DX,[IDEContrRegsBaseAddr]
add DX,04h
out DX,EAX
call ReadBootSector
; окончание работы
@@End: mov AX,3
int 10h
; ‚л室 ў DOS
mov AH,4Ch
int 21h
ENDP IDE_DMA_Test
;**********************************************
;НАЙТИ КОНТРОЛЛЕР PCI И ОТОБРАЗИТЬ НА ЭКРАН
; СОДЕРЖИМОЕ РЕГИСТРОВ КОНФИГУРАЦИОННОГО ПРОСТРАНСТВА
;*********************************************
PROC SearchBusMasterIDEContr near
pushad
; проверить наличие PCI BIOS
mov AX,0B101h
int 1Ah
jc @@PCIBIOSNotFound
cmp EDX,20494350h
jne @@PCIBIOSNotFound
;найти контроллер Bus Master IDE по Клоду класса
mov AX,0B103h
mov ECX,010180h ;первый вариант кода
mov SI,0
int 1Ah
jnc @@ReadPCIRegisters
mov AX,0B103h
mov ECX,010185h ; второй вариант
mov SI,0
int 1Ah
jnc @@ReadPCIRegisters
mov AX,0B103h
mov ECX,01018Ah ; третий
mov SI,0
int 1Ah
jc @@DeviceNotFound
; устройство обнаружено, его координаты на PCI
mov AX,0B10Ah ;читать двойное слово
mov DI,20h ;смещение слова
int 1Ah
jc @@BadRegisterNumber
and CX,0FFF0h
mov [IDEContrRegsBaseAddr],CX
popad
ret
; неверный номер регистра
@@BadRegisterNumber:
mov SI,offset BadReg
call FatalError
@@DeviceNotFound:
mov SI,offset NoIDEC
call FatalError
@@PCIBIOSNotFound:
; не поддерживается PCI BIOS
mov SI,offset NoPCI
call FatalError
ENDP SearchBusMasterIDEContr
;**********************************************
;ПРВЕРИТЬ ПРИСУТСТВИЕ ДИСКА И НАЛИЧИК ПОДДЕРЖКИ LBA
;**********************************************
PROC HDD_Presence_Test near
pusha
cmp [HDDErrorCode],0
jne @@DiskNotFound
cmp [dword ptr SectorDataBuffer+60*2],0
je @@LBANotSupported
popa
ret
; обработка ошибок
@@DiskNotFound:
mov SI,offset NoHDD
call FatalError
@@LBANotSupported:
mov SI,offset NoLBA
call FatalError
ENDP HDD_Presence_Test
;*********************************************
;ПРОЧИТАТЬ ЗАГРУЗОЧНЫЙ СЕКТОР В РЕЖИМЕ DMA ;*********************************************
PROC ReadBootSector near
pushad
mov DX,[IDEContrRegsBaseAddr]
add DX,02h
mov AL,110b
out DX,AL
mov DX,[IDEContrRegsBaseAddr]
mov AL,0
out DX,AL
mov AL,1000b
out DX,AL
mov [ATAAddressMode],1
mov [dword ptr SectorAddress],0
mov [dword ptr ATASectorNumber],0
mov [ATAFeatures],0
mov [ATASectorCount],1
mov EAX,[SectorAddress]
; ПОСЛАТЬ КОМАНДУ ДИСКУ
mov [ATACommand],0C8h
call SendCommandToHDD
cmp [HDDErrorCode],0
jne @@
mov DX,[IDEContrRegsBaseAddr]
mov AL,1001b
out DX,AL
; ОЖИДАТЬ ГОТОВНОСТЬ ДАННЫХ HDD
mov AX,0
mov ES,AX
mov DX,[HDDBasePortAddr]
add DX,7
@@WaitCompleet:
; проверить время выполнения команды
mov EAX,[ES:046Ch]
sub EAX,[HDDTime]
cmp EAX,MaxHDDWaitTime
ja @@Err1
in AL,DX
test AL,88h
jnz @@WaitCompleet
; ожидать конца цикла DMA
mov DX,[IDEContrRegsBaseAddr]
add DX,02h
@@WaitDMAOperationEnd:
in AL,DX
test AL,1
jnz @@WaitDMAOperationEnd
; сбросить упр.регистр канала 1 DMA
mov DX,[IDEContrRegsBaseAddr]
mov AL,0
out DX,AL
; отобразить на экран содержимое прочитанного сектора
; в ASCII-кодах
push DS
mov AX,DMA_BUF
mov DS,AX
mov AX,0B800h
mov ES,AX
mov DI,7*160+8*2
xor SI,SI
mov DX,8 ;бзҐвзЁЄ бва®Є
@@OutNextString:
mov CX,64 ; счетчик символов в строке
@@OutNextChar:
lodsb
stosw
loop @@OutNextChar
add DI,16*2
dec DX
jnz @@OutNextString
pop DS
mov SI,offset AnyK
call ShowColorString
call GetChar
popad
ret
; обработка ошибок
@@Error:
cmp [HDDErrorCode],1
je @@Err1
cmp [HDDErrorCode],2
je @@Err2
cmp [HDDErrorCode],3
je @@Err3
cmp [HDDErrorCode],4
je @@Err4
cmp [HDDErrorCode],5
je @@Err5
cmp [HDDErrorCode],6
je @@Err6
@@Err1: mov SI,offset DErr1
call FatalError
@@Err2: mov SI,offset DErr2
call FatalError
@@Err3: mov SI,offset DErr3
call FatalError
@@Err4: mov SI,offset DErr4
call FatalError
@@Err5: mov SI,offset DErr5
call FatalError
@@Err6: mov SI,offset DErr6
call FatalError
ENDP ReadBootSector
;**********************************************
; ФАТАЛЬНАЯ ОШИБКА
; ВЫДАТЬ СООБЩЕНИЕ И ВЫЙТИ ИЗ ПРОГРАММЫ
;**********************************************
PROC FatalError near
; вывести сообщение об ошибке
call ClearScreen
call ShowColorString
mov SI,offset AnyK
call ShowColorString
call GetChar
; аварийный выход
mov AH,4Ch
int 21h
ENDP FatalError
ENDS
include "lst_2_02.inc"
include "lst_7_07.inc"
END
Результат программы:
Вывод: данная программа выполняет считывание загрузочного сектора Master-диска канала 1 в режиме DMA. Но контроллер PCI не найден.
Листинг программы 6:
; Выполняем верификацию сектора (0-0-1)
; и диагностику с последующим анализом регистра ошибок
Ideal
Model Small
CodeSeg
StartUpCode ; основной модуль
mov dx, offset message0
call str_out ; вывод строки message0
call verify ; вызов процедуры верификации
call delay ; подождем немного
call diags ; вызов процедуры диагностики
call delay ; подождем немного
call read_status ; вызов процедуры чтения кода ошибки
call error_out ; вызов процедуры вывода на экран
; информации об ошибке
ExitCode ; конец основного модуля
;------------------------пауза--------------------------
proc delay
push cx bx
mov cx, 0ffffh
m1:
mov bx, 1000
m2:
dec bx
jnz m2
loop m1
pop bx cx
ret
endp
;----------------------команда запуска диагностики-------------
proc diags
mov dx, 1F7h ; регистр команд
mov al, 90h ; код команды диагностики
out dx, al ; передаем в порт
ret
endp
;---------------------верификация сектора 1 головки 0 цилиндра 0-------
proc verify
mov dx, 1F2h ; регистр кол-ва секторов
mov al, 1 ; проверяем сектор 1
out dx, al ; передаем в порт
mov dx, 1F3h ; регистр номера сектора
mov al, 1 ; сектор 1
out dx, al ; передаем в порт
mov dx, 1F4h ; регистр номера цилиндра старшая часть
xor al, al ; al = 0
out dx, al ; передаем в порт
mov dx, 1F5h ; регистр номера цилиндра младшая часть
xor al, al ; al = 0
out dx, al ; передаем в порт
mov dx, 1F6h ; регистр устройства и номера головки
xor al, al ; al = 0
out dx, al ; передаем в порт
mov dx, 1F7h ; регистр команд
mov al, 40h ; команда верификации с разрешением повтора
out dx, al ; передаем в порт
ret
endp
;-------------------чтение состояния КНЖМД--------------------------
;вход:
;выход: al - код ошибки
proc read_status
mov dx, 1F1h ; регистр ошибок
in al, dx ; al = код ошибки
ret
endp
;-----------------вывод ошибки на экран-----------------
;вход - al - код ошибки
proc error_out
mov dx, offset message1 ; смещение сообщения
call str_out ; вывод на экран
cmp al, 6 ; если код ошибки больше 6
ja m3 ; переходим на m3
dec al ; код ошибки уменьшили на 1,
; теперь al - индекс строк
mov dl, 32 ; длина текстового сообщения
mul dl ; получаем смещение нужной строки
; относительно первой
mov dx, offset err01 ; начало текстовых строк
add dx, ax ; получаем смещение нужной строки
; относительно начала сегмента данных
call str_out ; выводим на экран
jmp end_out
m3:
mov dx, offset err06 ; в dx - смещение строки err06
call str_out ; вывод строки на экран
end_out: ret
endp
;---------------вывод строки на экран--------------------
; вход - ds:dx - адрес строки для вывода
proc str_out
push ax
mov ah, 09h ; функция вывода строки на экран
int 21h ; вызываем
pop ax
ret
endp
DataSeg
message0 db "Идет диагностика КНЖМД...", 10, 13, '$'
message1 db "После операции диагностики регистр ошибок :",10, 13, '$'
;размер каждой строки - 32 байта
;это для правильной индексации при выводе строки об ошибке
err01 db "01h - нет ошибки ", 13, 10, '$'
err02 db "02h - ошибка КНЖМД ", 13, 10, '$'
err03 db "03h - ошибка буфферной памяти", 13, 10, '$'
err04 db "04h - ошибка схемы ECC ",13, 10, '$'
err05 db "05h - ошибка П ",13, 10, '$'
err06 db "??h - неизвестная ошибка (возможно запущен Windows)", 13, 10, '$'
END
Результат программы:
Вывод:данная программа Выполняет верификацию сектора (0-0-1) и диагностику с последующим анализом регистра ошибок. (01h – нет ошибки).