Главная » Ассемблер, Железо » Примеры программ, непосредственно работающих с контроллером жесткого диска

0

Листинг 6.7 содержит набор процедур, предназначенных для непосредственной работы с регистрами контроллера жесткого диска:

•          процедура ReadHDDSector считывает с заданный сектор с указанного диска, используя LBA и протокол ввода РЮ;

•          процедура SendCommandToHDD предназначена для посылки команды контроллеру диска (она является внутренней вспомогательной подпрограммой данного модуля и не должна вызываться из других модулей программы);

•          процедура ReadHDD_ID считывает идентификационный блок данных заданного диска, также используя протокол РЮ.

Указанные процедуры используют самые простые способы обмена данными с жестким диском — линейную адресацию LB А и программный ввод-вывод РЮ; прерывания, DMA и мультисекторная передача данных не применяются. Для определения готовности устройства к началу обмена информацией применяется метод циклического опроса регистра состояния: вначале проверяется бит занятости BSY (если устройство занято, то остальные разряды могут содержать недостоверную информацию), затем — бит ошибки, а в последнюю очередь — признаки готовности к приему команды DRDY или передаче данных DRQ. Несмотря на использование самых примитивных режимов, процедуры из листинга 6.7 являются достаточно эффективными при работе в однозадачном режиме DOS благодаря наличию у современных жестких дисков встроенной кэш-памяти большого объема. Обратите внимание на необходимость защиты от зависания по длительности выполнения операции, которая должна быть встроена в циклы опроса регистра состояния. В данном примере использовалось с указанной целью значение состояния системного таймера, которое периодически (18 раз в секунду) записывается операционной системой в область данных BIOS (в 32-разрядное слово по абсолютному адресу 46Ch). Длительность ожидания сигнала готовности устройства, вообще говоря, зависит от типа этого устройства — современные дисководы могут автоматически переходить в спящее состояние, для возврата из которого в рабочий режим может потребоваться несколько секунд (для разгона мотора дисковода). В данном случае задано предельное значение длительности ожидания, равное 10 тикам системного таймера, что соответствует примерно 0,5 с.

Листинг 6.7. Процедуры для непосредственной работы с контроллером жестких дисков АТА

; Максимальное время ожидания завершения операции

; (в "тиках") MaxHDDWaitTime equ 10

DATASEG

; Стандартные базовые адреса каналов 1 – 4 StandardHDDBases DW lFOh, 170h, lE8h, 168h : Номер канала ChannelNumber DW ?

: Базовый адрес группы портов контроллера HDD HDDBasePortAddr DW ? : Номер диска HDDNumber

DB ?

; Паранетры АТА-конанды ATAFeatures

DB ? :особенности ATASectorCount

DB ? ;количество обрабатываемых секторов ATASectorNumber

DB ? ;номер начального сектора ATACylinder DW ? ;номер начального цилиндра ATAHeadDB ? ;номер начальной головки

ATAAddressMode

DB ? ;режим адресации (0 – CHS, 1 – LBA) ATACommand

DB ? ;код команды, подлежащей выполнению

; Код ошибки (0 – нет ошибок, 1 – превышен допустимый

; интервал ожидания, 2 – неверный код режина адресации.

; 3 – неверный нонер канала, 4 – неверный нонер диска,

; 5 – неверный нонер головки, 6 – ошибка при выполнении

; конанды) HDDErrorCode

DB ?

; Момент начала очередной операции с диском HDDTime DD ?

; Адрес считываемого сектора в режине LBA SectorAddress DD 0

; Область паняти для хранения прочитанного сектора

SectorDataBuffer

DB 512 DUP (?)

ENDS

CDDESEG

;* ЧТЕНИЕ СЕКТОРА ЖЕСТКОГО ДИСКА В РЕЖИМЕ LBA*

;* Входные паранетры передаются через глобальные*

;* перененные:*

;* ChannelNumber – нонер канала (1-4);*

;* HDDNumber – номер диска на канале (0 или 1);*

;* SectorAddress – нонер считываеного сектора.*

;* Сектор считывается в основной сегмент данных,*

;* в массив SectorDataBuffer.*

PROC ReadHDDSector NEAR

Листинг 6.7 (продолжение)

pushad push ES

; Задать режим LBA

mov [ATAAddressMode],1

; Послать команду чтения сектора (с повторами)

mov [ATAFeatures].О

mov [ATASectorCount],1

mov EAX,[SectorAddress]

mov [dword ptr ATASectorNumber],EAX

mov [ATACommand],20h ca11 SendCommandToHDD cmp [HDDErrorCode],0

jne

@@End закончить, сохранив код ошибки

; Ожидать готовности данных HDD

mov АХ,0

mov ES.AX

mov DX.[HDDBasePortAddr]

add DX.7 ;адрес регистра состояния

@@WaitCompleet:

; Проверить время выполнения команды

mov ЕАХ,[ES:046Ch]

sub EAX,[HDDTime]

cmp EAX.MaxHDDWaitTime

ja

@@Errorl :ошибка тайм-аута

; Проверить готовность

in AL.DX

test AL,80h состояние сигнала BSY jnz

@@WaitCouipleet test AL,08h ;состояние сигнала DRQ jz

@@WaitCompleet

; Принять сектор

mov AX.[CS:MainDataSeg]

mov ES.AX

mov DI,offset SectorDataBuffer

mov DX,[HDDBasePortAddr] ;регистр данных

mov CX.256 ;число считываемых слов rep insw ;принять блок данных : Сбросить признак ошибки

mov [HDDErrorCode],0

jmp short

@@End : Записать номер ошибки

@@Errorl:

mov [HDDErrorCode].1 ;ошибка тайм-аута

jmp short

@@End

@@End: pop ES popad ret

ENDP ReadHDDSector

;*ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ*

;* Входные параметры передаются через глобальные *

;* переменные:*

;* Channel Number – номер канала (1-4);*

;* HDDNumber – номер диска (0 или 1);*

;* ATAFeatures – "особенности";*

;* ATASectorCount – количество секторов;*

;* ATASectorNumber – номер начального сектора;*

;* ATACylinder – номер начального цилиндра:*

;* ATAHead – номер начальной головки;* ;* ATAAddressMode – режим адресации (0-CHS, 1-LBA); *

;* ATACommand – код команды.*

;* После успешного выполнения функции:*

;* в SectorDataBuffer – прочитанный сектор:*

;* в HDDBasePortAddr – базовый адрес HDD;*

;* в HDDTime – момент начала выполнения команды;*

;* в HDDErrorCode – ноль.*

;* При возникновении ошибки в HDDErrorCode будет*

;* возвращен код ошибки.*

PROC SendCommandToHDD near pushad push ES

; Запомнить время начала операции с диском

; Загрузить в ES сегмент данных BIDS

mov АХ,О

mov ES.AX

; Запомнить текущее время

mov ЕАХ,[ES:046Ch]

mov [HDDTime],ЕАХ

; Проверить значение кода режима cmp [ATAAddressMode],1 ja

@@Error2

; Проверить корректность номера канала

mov ВХ,[Channel Number] cmp BX.l jb РРЕггогЗ cmp BX.4 ja

@@Error3 : Установить базовый адрес dec BX shl BX,1

mov AX,[BX+StandardHDOBases]

mov [HDDBasePortAddr],AX : Запретить прерывания от контроллера HDD

mov DX.[HDDBasePortAddr]

add DX,206h

mov AL,1010b out DX.AL

Листинг 6.7 (продолжение)

; Ожидать "освобождения" HDD

mov DX,[HDDBasePortAddr]

add DX,7 ;адрес регистра состояния

P@WaitNot8SY:

; Проверить время выполнения команды

mov ЕАХ,[ES:046Ch] sub ЕАХ,[HDDTime] cmp ЕАХ,MaxHDDWa itTi me ja

@@Errorl ;ошибка тайм-аута

; Проверить состояние сигнала BSY in AL.DX

test AL,80h -.состояние сигнала BSY jnz P@WaitNot8SY

; Ожидание готовности HDD к приему команды

; Выбрать нужный диск

mov DX.[HDDBasePortAddr]

add DX,6 :адрес регистра головок

mov AL,[HDDNumber] cmp AL,1 проверить номера диска ja

@@Error4 shl AL.4 or AL,10100000b out DX.AL

: Ожидать, пока Диск не будет готов

inc DX

@@WaitHDReady:

; Проверить время выполнения команды

mov ЕАХ,[ES:046Ch] sub ЕАХ.[HDDTime] cmp ЕАХ.MaxHDDWa i tTi me ja PPErrorl .-ошибка тайм-аута

; Проверить состояние BSY и DRDY in AL.DX

test AL,80h состояние сигнала BSY jnz PGWaitHDReady test AL,40h состояние сигнала DRDY jz

@@WaitHDReady

; Загрузить команду в регистры контроллера

movDX,[HDDBasePortAddr]

incDX;регистр "особенностей"

movAL,[ATAFeatures]

outDX.AL

incDX;счетчик секторов

movAL,[ATASectorCount]

outDX,AL

incDX;регистр номера сектора

movAL,[ATASectorNumber]

outDX.AL

inc DX;номер цилиндра (младший байт)

movАХ.[ATACyli nder]

outDX.AL

inc DX;номер цилиндра (старший байт)

movAL.AH

outDX.AL

incDX;номер головки/номер диска

movAL,[HDDNumber]

shlAL.4

cmp[ATAHead], OFh проверить номер головки

jaP@Error5

orAL,[ATAHead]

orAL.lOlOOOOOb

movAH.[ATAAddressMode]

shlAH.6

orAL.AH

outDX.AL

; Послать команду

movAL,[ATAComma nd]

incDX.-регистр команд

outDX.AL

; Сбросить признак ошибки

mov[HDDErrorCode],О

jmp short P@End

; Записать код ошибки PPErrorl:

mov [HDDErrorCode],1

jmp short P@End P@Error2:

mov [HDDErrorCode],2

jmp short PPEnd

@@Error3:

mov [HDDErrorCode],3

jmp short P@End

@@Error4:

mov [HDDErrorCode],4

jmp short P@End

@@Error5:

mov [HDDErrorCode],5

jmp short P@End P@End: pop ES popad ret

ENDP SendCommancfToHDO

;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА * ;* Входные параметры передаются через глобальные *

Листинг 6.7(продолжение)

;* переменные:*

;* ChannelNumber  номер канала (1-4);*

;* HDDNumber – номер диска на канале (0 или 1).*

;* Идентификационный блок данных считывается*

;* в массив SectorDataBuffer.*

. ************************ А-А А А"А Л А****А АЛЛ ******* А А *

PROC ReadHDD_ID near pushad push ES

; Задать режим CHS

mov [ATAAddressMode],0

; Послать команду идентификации устройства

mov [ATAFeaturesLO

mov [ATAHead],0

mov [ATACommand],OECh call SendCommandToHDD cmp [HDDErrorCode],0 проверить код ошибки jne

@@End закончить, сохранив код ошибки

; Ожидать готовности данных HDD

mov АХ,0

mov ES.AX

mov DX,[HDDBasePortAddr]

add DX,7 :адрес регистра состояния

@@WaitCompleet:

; Проверить время выполнения команды

mov ЕАХ.[ES:046Ch] sub ЕАХ,[HDDTime] cmp EAX,MaxHDDWaitT1me ja

@@Errorl ;ошибка тайм-аута

; Проверить готовность in AL.DX

test AL,80h состояние сигнала BSY jnz

@@WaitCompleet test AL.l :состояние сигнала ERR jnz

@@Error6

test AL,08h состояние сигнала DRQ jz

@@WaitCompleet

; Принять блок данных от контроллера

mov АХ,[CS:Ma i nDataSeg]

mov ES.AX

mov DI,offset SectorDataBuffer

mov DX,[HDDBasePortAddr] ;регистр данных

mov CX.256 ;число считываемых слов rep insw .-принять блок данных

jmp short

@@End

; Записать код ошибки

@@Errorl:

mov [HDDErrorCode],1

jmp short

@@End

рреггогб:

mov [HDDErrorCode],6

@@End: pop ES popad ret

ENDP ReadHDD_ID ENDS

Программа IdentifyDevices, приведенная в листинге6.8, осуществляет поиск жестких дисков по каналам 1 (Primary) и 2 (Secondary) АТА-контроллера, считывает и отображает на экран параметры найденных устройств. Программа использует процедуры ввода-вывода общего назначения из глав «Работа с клавиатурой» и «Недокументированные возможности процессоров Intel 80x86», процедуры считывания данных с диска из листинга 6.7, а также две вспомогательные подпрограммы:

•     процедура ShowHDD_ID отображает на экран содержимое некоторых полей 512-байтной структуры-идентификатора диска;

•     процедура CIearPrevInfo очищает экран и выводит текстовые сообщения в верхней (заголовок) и нижней (надпись Ждите) строках экрана.

Листинг 6.8. Поиск подключенных жестких дисков по каналам 1 и 2

IDEAL

Р386

LOCALS

MODEL MEDIUM

: Подключить файл инеионических обозначений

; кодов управляющих клавиш и цветовых кодов

Include "listl_03.inc"

; Подключить файл макросов

Include "listl_04.inc"

DATASEG

Текстовые сообщения Txtl

DB LIGHTCYAN,0,26,"ИДЕНТИФИКАЦИЯ ЖЕСТКИХ ДИСКОВ",0

DB YELLOW.24.35."Ждите …".О Txt2

DB 2,27,"На канале найден диск .",0

DB 4,25,"Параметры обнаруженного диска:",0

DB 6.22,"Общая информация:",0

DB 7.12."Число логических цилиндров:".0

DB 8,14,"Число логических головок:".О

DB 9.13,"Число логических секторов:",0

DB 10,24,"Серийный номер:",0

DB 11.32."Модель:".О

DB 12.8."Макс, количество секторов за сеанс.-".О

Листинг 6.8(продолжение)

ОВ 13,27,"Возможности:",0 ОВ 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,"Улучшенные режимы РЮ:",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

;* Основной модуль программы *

;**********AAA А А ААЛ А Л А********

PROC IdentifyDevices

mov AX.DGROUP

mov DS.AX

mov [CS:MainDataSeg],AX

; Установить текстовый режим и очистить экран

mov АХ.З int 10h

; Скрыть курсор  убрать за нижнюю границу экрана

mov [ScreenStri ng],25

mov [ScreenCol umn], 0 call SetCursorPosition

; Вывести текстовые сообщения на экран MShowColorText 2,Txtl

: Цикл опроса каналов

mov [ChannelNumber],1 : Опросить Master-диск

@@AskMaster:

call ClearPrevInfo

mov [HDDNumber],0 call ReadHDD_ID cmp [HDDErrorCode],0 jne

@@AskSlave call ShowHDDJD : Опросить Slave-диск

@@AskSlave:

call ClearPrevInfo

mov[HDDNumber].1 call ReadHDD_ID

cmp[HDDErrorCode],0

jne@@NextCannel call ShowHDDID

@@NextCannel:

inc[Channel Number]

cmp[Channel Number],3

jb@@AskMaster

@@End:

; Выдать сообщение о завершении поиска call ClearPrevInfo MShowColorText 2,Txt3 call GetChar

; Переустановить текстовый режим

mov ах.З int lOh : Выход в DOS

mov AH,4Ch int 21h ENDP IdentifyDevices

;* РАСШИФРОВКА ИДЕНТИФИКАТОРА ДИСКА *

PROC ShowHDDID near pushad

; Установить зеленый цвет и черный фон

mov [TextColorAndBackground],LIGHTGREEN MShowText 17.Txt2 MShowColorString AnyK

; Установить белый цвет и черный фон

mov [TextColorAndBackground],WHITE : Вывести номер канала и номер диска

MShowDecWord 2,37,[ChannelNumber] MShowDecByte 2,51.[HDDNumber] : Вывести отдельные поля идентификатора

; (только неспецифические) : Общая информация

MShowBinWord 6.40,<[word ptr SectorDataBuffer]* : Число логических цилиндров

MShowDecWord 7.40,<[word ptr SectorDataBuffer+l*2]> : Число логических головок

MShowDecWord 8,40,<[word ptr SectorDataBuffer+3*2]>

; Число логических секторов

MShowDecWord 9,40,<[word ptr SectorDataBuffer+6*2]> : Серийный номер

mov AX,0B800h

mov ES.AX

mov SI,offset SectorDataBuffer

Листинг 6.8(продолжение)

add SI,10*2

mov DI,(10*80+40)*2

mov AH.[TextColorAndBackground]

mov CX.10

@@NextWordl:

mov DX,[SI]

mov AL.DH stosw

mov AL.DL stosw

add SI,2 loop

@@NextWordl

; Номер модели

mov SI,offset SectorDataBuffer

add SI,27*2

mov DI,(ll*80+40)*2

mov AH,[TextColorAndBackground]

mov CX.20

@@NextWord2:

mov DX,[SI]

mov AL.DH stosw

mov AL.DL stosw

add SI,2 1 oop

@@NextWord2

; Макс, кол-во секторов за сеанс MShowDecByte 12.40,<[SectorDataBuffer+47*2]>

; Возможности

MShowBinWord 13,40,<[word ptr SectorDataBuffer+49*2]>

; Значения слов 54-58 достоверны?

test [word ptr SectorDataBuffer+53*2],1

jz

@@NotValid5458

; Текущее число логических цилиндров

MShowDecWord 14.40,<[word ptr SectorDataBuffer+54*2]>

; Текущее число логических головок

MShowDecWord 15,40,<[word ptr SectorDataBuffer+55*2]>

; Текущее число логических секторов

MShowDecWord 16,40,<[word ptr SectorDataBuffer+56*2]>

; Текущая емкость секторов

MShowDecDWord 17,40,<[dword ptr SectorDataBuffer+57*2]> №NotValid5458:

; Число секторов в режиме LBA

MShowDecDWord I8,40.<[dword ptr SectorDataBuffer+60*2]>

; Поддерживаемые режимы DMA

MShowBinByte 19.40.«[SectorDataBuffer+63*2]>

; Значения слов 64-70 достоверны?

test [word ptr SectorDataBuffer+53*2],10b

jz

@@NotValid6470

; Поддерживаемые режимы PIO MShowBinByte 20,40,<[SectorDataBuffer+64*2]> №NotVa1id6470:

; Ожидать нажатия любой клавиши

cal1 GetChar

popad

ret

ENDP ShowHDD_ID

* ОЧИСТИТЬ ЭКРАН И ВЫВЕСТИ ЗАГОЛОВКИ *

PROC ClearPrevInfo near

pushad

; Очистить экран

call ClearScreen : Вывести текстовые сообщения на экран MShowColorText 2,Txtl popad ret

ENDP ClearPrevInfo ENDS

: Подключить процедуры вывода данных на экран

Include "listl_02.inc"

; Подключить "математические" процедуры для перевода

; чисел из двоичного кода в десятичный

Include "list2_05.inc"

; Подключить процедуру непосредственного считывания

; сектора с жесткого диска

Include "list6_07.inc"

END

ПРИМЕЧАНИЕ

Для запуска программы lst_6_08.exe можно использовать любой АТ-совме- стимый персональный компьютер с контроллером АТА.

В листинге 6.9 приведена программа ShowHDDSector, позволяющая осуществлять считывание (в режиме LBA) и просмотр секторов Master-диска Primary-канала (канала 1). Просмотр осуществляется так же, как и в листинге 6.6 — при помощи клавиш 1 и Т; для выхода из программы используется клавиша Esc. Программа использует процедуры ввода-вывода из главы 1 «Работа с клавиатурой» и главы 2 «Недокументированные возможности процессоров Intel 80x86», а также из листинга 6.7.

Листинг 6.9. Просмотр секторов ведущего жесткого диска канала 1 в режиме LBA

IDEAL

РЗВ6

LOCALS

MODEL MEDIUM

; Подключить файл мнемонических обозначений

; кодов управляющих клавиш и цветовых кодов

Include "listl_03.inc"

; Подключить файл макросов

Include "listl_04.inc"

DATASEG

; Текстовые сообщения

Txtl

DB LIGHTCYAN,0,16,"Просмотр секторов "

DB "жесткого диска в ASCII-кодах",О

DB LIGHTGREEN,5,8,"Сектор N:",0

DB LIGHTCYAN,17,В,"Управляющие клавиши:",О

DB YELLOW,24,27,"Нажмите управляющую клавишу",О Txt2

DB 19,8,"Стрелка вниз – следующий сектор:",0

DB 20,В,"Стрелка вверх – предыдущий сектор;",0

DB 21.8,"Esc – выход.",0 Errl

DB 12,22,"Master-диск на канале 1 не обнаружен",0 Err2

DB 12,25,"Диск не поддерживает режим LBA",0 ENDS

SEGMENT sseg para stack ‘STACK"

DB 400h DUP(?)

ENDS CODESEG

• А А AAA AAAAAAAAAAAAAAA A A AAA AAAA

;* Основной модуль программы *

.А AAAAAA**~A А А***1

PROC ShowHDDSector

mov AX.DGROUP

mov DS.AX

mov [CS:MainDataSeg],AX

; Установить текстовый режим и очистить экран

mov АХ.З int 10h

; Скрыть курсор – убрать за нижнюю границу экрана

mov [ScreenString],25

mov [ScreenColumn],0 call SetCursorPosition : Опросить Master-диск канала 1

mov [ChannelNumber],l

mov [HDDNumber],0 call ReadHDDID

; Диск подключен? cmp [HDDErrorCode],О jne

@@Di skNotFound

; Режин LBA поддерживается? cmp [dword ptr SectorDataBuffer+60*2],0

je

@@LBANotSupported

; Вывести текстовые сообщения на экран MShowColorText 4.Txtl

; Установить зеленый цвет и черный фон

mov [TextColorAndBackground].LIGHTGREEN MShowText 3,Txt2

; Инициализируем переменные

mov [HDDNumber],0

mov [dword ptr SectorAddress],0

mov AX.OBBOOh

mov ES.AX

; ВНЕШНИЙ ЦИКЛ

@@ReadSector:

MShowHexDword 5,17,[SectorAddress] call ReadHDDSector

mov DI.7*160+8*2

mov SI.offset SectorDataBuffer : Задать для символов светло-голубой : цвет и синий фон

mov АН.LIGHTCYAN+BLUE*16

mov DX.8 ;счетчик строк

@@OutNextString:

mov СХ,64 :счетчик символов в строке

@@OutNextChar: lodsb stosw

loop

@@OutNextChar

add DI,16*2 dec DX

jnz

@@OutNextString

©PGetCommand:

; Ожидаем ввода следующей команды call GetChar cmp AL,0

je

@@TestCommandByte

cal1 Beep

jmp short

@@GetCommand

@@TestCommandByte:

cmp AH,B_Esc.-"Выход"

je

@@End

@@TestDn:

cmp AH.B_DN:"Стрелка вниз"

Листинг 6.9(продолжение)

jne№Testllp

; Увеличить на 1 номер сектора

inc[dword ptr SectorAddress]

jmp@@ReadSector

@@TestUp:

cmpAH,B_UP:"Стрелка вверх"

jne@@CommandError

cmp[dword ptr SectorAddress],0

je@@CommandError

; Уменьшить на 1 номер сектора

dec[dword ptr SectorAddress]

jmp@@ReadSector @eCommandError:

cal1Beep

jmp@@GetCommand

; Завершение работы программы

@@End:

; Переустановить текстовый режим (очистить экран)

mov ах.З int 10h

; Выход в DOS

mov AH,4Ch int 21h

; Обработка ошибок PPDiskNotFound:

MFatalError Errl ;диск не найден

@@LBANotSupported:

MFatalError Err2 .-диск не поддерживает LBA ENDP ShowHDDSector ENDS

; Подключить процедуры вывода данных на экран

Include "listl_02.inc"

: Подклшчить процедуру непосредственного считывания

; сектора с жесткого диска

Include "list6_07.inc"

END

ПРИМЕЧАНИЕ

Для запуска программы пригоден любой АТ-совместимый персональный компьютер с жестким диском, установленным в качестве основного на канале 1 и поддерживающим режим LBA. Чтобы проверить наличие Master- диска на Primary-канале и способность этого диска работать а режиме LBA, можно использовать программу поиска дисков из листинга 6.8.

Приведенная в листинге 6.10 программа SearchLogi cal Disks осуществляет поиск логических дисков на Master-диске Primary-канала. Работа с диском ведется в режиме LBA. Программа выводит на экран таблицу разделов и расшифровку полей загрузочного сектора каждого найденного логического диска при помощи процедур ShowParti – tionTable и DecodeBootSector. Для отображения на экран текстовых полей используется вспомогательная процедура ShowASCIIField. Программа lst_6_10.exe предъявляет к аппаратуре те же самые требования, что и программа из листинга 6.9.

Листинг 6.10. Просмотр в режиме LBA параметров логических дисков на ведущем жестком диске канала 1

IDEAL

Р386 LOCALS

MODEL MEDIUM

; Подключить файл мнемонических обозначений

; кодов управляющих клавиш и цветовых кодов

Include "listl_03.inc" : Подключить файл макросов

Include "listl_04.inc"

DATASEG

: Текстовые сообщения

TxtOO

DB YELLOW,24,29."Нажмите любую клавишу".О TxtOl

DB YELLOW.0.30

DB "MASTER-ДИСК КАНАЛА 1",0

DB YELLOW,1,22

DB "ТАБЛИЦА РАЗДЕЛОВ ЛОГИЧЕСКОГО ДИСКА".0 Txt02 ОВ B.l,"N",0

DB 8.4,"Тип",0

DB 8,9,"Призн.",0,9,9,"акт.",0

DB 8,16," Начало раздела".0

DB 9,17,"Гол.",0,9,24,"Цил.",0,9,31,"Сект.",0

DB В.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 Txtll

DB YELLOW,0,19

DB "ЗАГРУЗОЧНАЯ ЗАПИСЬ ЛОГИЧЕСКОГО ДИСКА N".0 Txtl2

DB 2,12,"Идентификатор изготовителя:",0

DB 3,22,"Байтов на сектор:",0

DB 4,19,"Секторов в кластере:",0

DB 5,14,"Число резервных секторов:",0

Листинг 6.10 (продолжение)

DB 6.23,"Число копий FAT:",О

DB 7,6."Дескрипторов в корневом каталоге:",О

DB 8,14,"Число секторов в разделе:",О

DB 9,15,"Тип носителя информации:О

DB 10,1."Число секторов, занимаемых копией FAT:".О

DB 11,13,"Число секторов на дорожке:",О

DB 12,1,"Количество рабочих поверхностей диска:",О

DB 13,16,"Число скрытых секторов:",О Txtl3

DB 14,23,"Номер дисковода:",0

DB 15,15,"Номер логического диска:",О

DB 16.27,"Метка диска:",О

DB 17,9."Аббревиатура файловой системы:".О Txtl4

DB 14,20,"Номер активной FAT:",О

DB 15.22,"Номер версии FAT:",О

DB 16,0

DB "Номер нач. кластера корневого каталога:",0

DB 17,В,"Номер сектора структуры FSINFO:",0

DB 18,4,"Номер сектора резервной копии Boot:",0

DB 19,23,"Номер дисковода:",0

DB 20,15,"Номер логического диска:",0

DB 21,27,"Метка диска:",0

DB 22,9,"Аббревиатура файловой системы:",0 Errl

DB 12,22,"Master диск на канале 1 не обнаружен",0 Err2

DB 12,25,"Диск не поддерживает режим LBA",0 ЕггЗ

DB 12,25,"Основной раздел DOS не найден",0

; Номер раздела PartitionNumber

DB ?

; Начальный сектор основного раздела DOS PriDOSStartSector DD ?

; Начальный сектор расширенного раздела DOS ExtDOSStartSector DD ?

; Начальный сектор текущего логического диска CurrentDriveStartSector DD ?

; Линейный адрес загрузочного сектора BootSector DD ?

; Номер логического диска LogicalDriveNumber

DB ?

; Флаг присутствия в системе следующего диска NextDrivePresent

DB ? ENDS

SEGMENT sseg para stack ‘STACK’

DB 400h DUP(?)

ENDS

CODESEG

• A A A A’ A’ A’ ‘A1 ‘A’ A A’ ‘A A A A’A’ A’ AA A’A’ A’ "A1 A’ A A A ‘A’ A’A’

PROC SearchLogicalDisks

mov AX,DGROUP

mov DS.AX

mov [CS:MainDataSeg].AX

; Установить текстовый режим и очистить экран

mov АХ.З int 10h

; Скрыть курсор – убрать за нижнюю границу экрана

mov [ScreenString],25

mov [ScreenColumn].0 call SetCursorPosition : Опросить Master-диск канала 1

mov [Channel Number],1

mov [HDDNumber],0 call ReadHDDID : Диск подключен? cmp [HDDErrorCode],0 jne

@@Di skNotFound : Режим LBA поддерживается? cmp [dword ptr SectorDataBuffer+60*2],0

je

@@LBANotSupported

; Обнулить ноиер логического диска

mov [LogicalDriveNumber],Q

; Прочитать MBR диска

mov [CurrentDri ve_StartSector].0

mov [dword ptr SectorAddress],0 cal1 ReadHDDSector Отобразить таблицу разделов

call ShowPartitionTable

: Найти и записать номера начальных секторов

; основного и расширенного разделов DOS

mov [NextDri vePresent],0

mov SI,offset SectorDataBuffer

add SI.lBEh :смещение первой записи

mov AL,[SI+4] ;извлечь тип раздела : Проверить код основного раздела cmp AL.Olh

je

@@PrimPartFound cmp AL,04h

je

@@PrimPartFound cmp AL.06h

je

@@PrimPartFound cmp AL.OBh

je

@@PrimPartFound cmp AL.OEh jne

@@PrimPartNotFound

@@PrimPartFound:

: Найден основной раздел, сохранить

Листинг 6.10 (продолжение)

: адрес его начального сектора

mov ЕАХ,[SI+8] -.извлечь адрес сектора

mov [PriDOS_StartSector],EAX

add SI ЛOh ;смещение второй записи

mov AL.[SI+4] ;извлечь тип раздела

: Проверить код расширенного раздела

cmp AL,05h

je

@@ExtPartFound

cmp AL.OCh

je

@@ExtPartFound

cmp AL.OFh

jne

@@NextDri veNotPresentO

@@ExtPartFound:

; Имеется расширенный раздел

mov EAX,[SI+8] .-извлечь адрес сектора

mov [ExtDOSStartSector],EAX

mov [NextDrivePresent],l PPNextDri veNotPresentO:

: Прочитать 800T-сектор основного раздела

mov ЕАХ, [PriDOSStartSector]

mov [SectorAddress],EAX cal1 ReadHDOSector

; Отобразить данные ВООТ-сектора основного раздела cal1 DecodeBootSector

: Имеется следующий диск? cmp [NextDrivePresent].0

je

@@End

mov EAX,[ExtDOS_StartSector]

mov [CurrentDrive_StartSector],EAX

: ЦИКЛ ОПРОСА ЛОГИЧЕСКИХ ДИСКОВ РАСШИРЕННОГО РАЗДЕЛА

@@ReadSMBR:

inc [LogicalDriveNumber]

: Прочитать очередной SMBR

mov ЕАХ, [CurrentDri veStartSector]

mov [BootSector],EAX

mov [SectorAddress],EAX

cal1 ReadHDDSector

; Отобразить таблицу разделов

call ShowPartitionTable

; Найти и записать номера начальных секторов

mov [NextDri vePresent],О

mov SI.offset SectorDataBuffer

add SI.lBEh ;смещение первой записи

mov EAX,[SI+B]

add [BootSector].EAX

add Sl.lOh :смещение второй записи

mov ЕАХ. [SI+8]

cmp EAX,0 следующий диск присутствует?

je

@@NextDriveNotPresentl : Вычислить адрес SMBR следующего диска

add ЕАХ,[ExtDOS_StartSector]

mov [CurrentDrive_StartSector].EAX : Установить признак наличия следующего диска

mov [NextDrivePresent],l

@@NextDriveNotPresentl:

: Прочитать BOOT-сектор логического диска

mov EAX,[BootSector]

mov [SectorAddress].EAX cal1 ReadHDDSector

; Отобразить данные BOOT-сектора cal1 DecodeBootSector : Имеется следующий диск?

cmp [NextDri vePresent].0

je

@@End

jmp

@@ReadSMBR

; Завершение работы программы

@@End: : Переустановить текстовый режии

mov ах,3 int 10h : Выход в DOS

mov AH,4Ch int 21h

: Обработка ошибок

@@DiskNotFound:

MFatalError Errl ;диск не найден POLBANotSupported:

MFatalError Err2 ;диск не поддерживает LBA WrimPartNotFound:

MFatalError ЕггЗ ;не найден основной раздел ENDP SearchLogicalDisks

;* ПРОЧИТАТЬ НУЛЕВОЙ СЕКТОР И ОТОБРАЗИТЬ * НА ЭКРАН ТАБЛИЦУ РАЗДЕЛОВ *

PROC ShowPartitionTabl е near pushad push ES : Очистить экран

call CIearScreen

: Вывести текстовые сообщения на экран

Листинг 6.10 (продолжение)

MShowColorString TxtOO MShowColorText 2,Txt01

mov[TextColorAndBackground].YELLOW MShowHexByte 1.57,[Logi calDri veNumber]

; ЦИКЛ РИСОВАНИЯ ТАБЛИЦЫ

movAX,0B800h Настроить ES для прямого

movES.AX ;вывода на экран

movDI,B*B0*2 :Начать вывод с В-й строки

movAH.LIGHTBLUE :Чертить синим цветом

movAL,0B3h ;Задать симвоп-разделитель

movDX.7 ;3адать общее число строк

; Отобразитьсимволы-разделители колонок таблицы

@@асО: pushDI

addDI,3*2

mov[ES:DI],AX

addDI,5*2

movCX, В

l?@acl: mov[ES:DI].AX

addDI,7*2

loop@@acl

addDI,4*2

mov[ES:DI],AX

popDI

addDI,80*2

decDX

jnz@@acO

; Установить зеленый цвет и черный фон

mov [TextCol orAndBackground],LIGHTGREEN

; Отобразить шапку таблицы MShowText 16,Txt02

; ЦИКЛ ВЫВОДА ДАННЫХ

; Установить белый цвет и черный фон

mov [TextCol orAndBackground].WHITE

; Отобразить загрузочный сектор на экран

mov [PartitionNumber].l

mov SI,offset SectorDataBuffer

; Прибавить смещение первой записи

; от начапа сектора

add SI.lBEh

; Задать начальную строку для вывода данных

mov [ScreenString],11

@@ShSO:

; Отобразить порядковый номер раздела

mov AL,[PartitionNumber]

mov [ScreenColumn],О cal1 ShowHexByte

; Отобразить код типа раздела lodsb

mov [ScreenColumn],11 cal 1 ShowHexByte

; Отобразить номер начальной поверхности раздела lodsb

mov [ScreenColumn],18 cal 1 ShowHexByte

; Отобразить номер начального цилиндра : и номер начального сектора раздела lodsw

mov BL.AL

; Вычислить и отобразить номер цилиндра shr AL.6 xchg AL.AH

mov [ScreenColumn],24 cal1 ShowHexWord : Вычислить и отобразить номер сектора

mov AL, Bland AL.0111111b

mov [ScreenColumn],32 cal1 ShowHexByte

; Отобразить код признака активного раздела

mov [ScreenColumn],5

lodsb

call ShowHexByte

: Отобразить номер конечной поверхности раздела

mov [ScreenColumn],39

lodsb

cal1 ShowHexByte

: Отобразить номер конечного цилиндра : и номер конечного сектора раздела lodsw

mov BL.AL

: Вычислить и отобразить номер цилиндра

shr AL.6

xchg AL.AH

mov [ScreenColumn],45

call ShowHexWord

: Вычислить и отобразить номер сектора

mov AL.BL

and AL.0111111b

mov [ScreenColumn],53

cal1 ShowHexByte

Листинг 6.10 (продолжение)

: Отобразить абсолютный нонер начального сектора

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

; Вывести текстовые сообщения на экран MShowColorString TxtOO MShowColorString Txtll

; Отобразить порядковый номер логического диска

mov [TextColorAndBackground],YELLOW MShowHexByte 0,58,[LogicalDriveNumber]

: Установить зеленый цвет и черный фон

mov [TextColorAndBackground],LIGHTGREEN

; Отобразить названия общих полей MShowText 12,Txtl2

: Настроить ES для прямого вывода на экран

mov AX,0B800h

mov ES.AX

; Установить указатель на область данных

mov SI,offset SectorDataBuffer

; Установить белый цвет и черный фон

mov [TextColorAndBackground],WHITE

; ОБЩИЙ УЧАСТОК BOOT-СЕКТОРА

; Отобразить идентификатор OEM с 40-й позиции 2-й строки

MShowASClIField 2,40,3,8

; Отобразить число байтов на сектор

MShowHexWord 3,40,[SI+OBh]

; Отобразить число секторов в кластере

MShowHexByte 4,40.[SI+ODh]

; Отобразить число резервных секторов MShowHexWord 5,40.[SI+OEh]

; Отобразить число копий FAT в разделе

MShowHexByte 6.40,[SI+10h] : Отобразить число дескрипторов в корневом каталоге

MShowHexWord 7.40.[SI+llh]

; Отобразить число секторов в разделе cmp [word ptr SI+13h],0

je

@@UseTotSec32 :использовать BPB_TotSec32 MShowHexWord 8,40,[SI+13h]

@@UseTotSec32:

; Отобразить тип носителя информации MShowHexByte 9.40.[SI+15h]

; Отобразить число секторов, занимаемых копией FAT cmp [word ptr SI+16h],0

je

@@UseFATSz32 :использовать BPB_FATSz32 MShowHexWord 10,40,[SI+16h]

@@UseFATSz32:

: Отобразить число секторов на дорожке MShowHexWord 11,40,[SI+lBh]

; Отобразить количество рабочих поверхностей диска

MShowHexWord 12,40,[SI+lAh]

; Отобразить число скрытых секторов

MShowHexDWord 13,40,[SI+lCh]

; Отобразить число секторов в разделе cmp [dword ptr SI+20h],0

je ,

@@UseTotSecl6 ;использовать BPB_TotSecl6 MShowHexDWord 8,40,[SI+20h] @0UseTotSecl6:

: Если размер корневого сектора равен нулю – FAT32 cmp [word ptr SI+llh].0

je

@@FAT32

; УЧАСТОК BOOT-CEKTOPA, СПЕЦИФИЧЕСКИЙ ДЛЯ FAT12 И FAT16

; Установить зеленый цвет и черный фон

mov [TextColorAndBackground],LIGHTGREEN : Отобразить названия полей, специфических : для FAT12 и FAT16

MShowText 4,Txtl3 : Установить белый цвет и черный фон

mov [TextColorAndBackground].WHITE

Листинг 6.10 (продолжение)

: Установить указатель на область данных

mov SI,offset SectorDataBuffer

; Отобразить номер дисковода

MShowHexByte 14,40,[SI+24h]

; Отобразить номер логического диска

MShowHexDWord 15,40,[SI+27h]

; Отобразить метку диска

MShowASCIIField 16,40,2Bh,ll

; Отобразить аббревиатуру файловой системы MShowASCIIField 17,40,36h.8 jmp

@@End

@@FAT32:

; УЧАСТОК ВООТ-СЕКТОРА, СПЕЦИФИЧЕСКИЙ ДЛЯ FAT32

; Установить зеленый цвет и черный фон

mov [TextColorAndBackground],LIGHTGREEN

; Отобразить названия полей, специфических FAT32

MShowText 9,Txtl4

; Установить белый цвет и черный фон

mov [TextColorAndBackground].WHITE

; Установить указатель на область данных

mov SI,offset SectorDataBuffer

; Отобразить число’секторов, занимаемых копией FAT32

MShowHexDWord 10.40.[SI+24h]

; Отобразить номер активной FAT

MShowHexWord 14,40.[SI+2Bh]

; Отобразить код версии FAT

MShowHexWord 15,40,[SI+2Ah] : Отобразить номер начального кластера корневого : каталога

MShowHexDWord 16,40,[SI+2Ch]

; Отобразить номер сектора структуры FSINFO

MShowHexWord 17,40,[SI+30h]

; Отобразить номер сектора резервной копии Boot-ceKTopa

MShowHexWord 18.4Q,[SI+32h] : Отобразить номер дисковода

MShowHexByte 19,40.[SI+40h]

; Отобразить номер логического диска

MShowHexDWord 20,40,[SI+43h] : Отобразить метку диска

MShowASCIIField 21.40.47h.il : Отобразить аббревиатуру файловой системы MShowASCIIField 22.40.52h.B

@@End: call GetChar pop ES popad ret

ENDP DecodeBootSector

ENDS

; Подключить процедуры вывода данных на экран

Include "listl_02.inc"

; Подключить процедуру непосредственного считывания

; сектора с жесткого диска

Include "list6_07.inc"

END

Листинг 6.11 содержит программу SearchAutoexecBat, которая осуществляет поиск файла с именем autoexec.bat в корневой папке первого логического диска Master-диска Primary-канала (то есть диска, который обычно служит для загрузки операционной системы и обязательно содержит подобный файл), а затем отображает содержимое файла на экран. Процесс поиска программа иллюстрирует, отображая на экране содержимое начальных участков корневой папки и FAT логического диска.

Листинг 6.11. Поиск файла AUTOEXEC.BAT в корневом каталоге

ведущего диска канала 1, считывание и отображение его на экране

IDEAL

Р386

LOCALS

MODEL MEDIUM

; Подключить файл иненонических обозначений

; кодов управляющих клавиш и цветовых кодов

Include "listl_03.mc"

; Подключить файл иакросов

Include "listl_04.inc"

; Разиер корневого каталога в секторах RootDirSize equ 32

: Адрес области дополнительной памяти, выделенной

; для хранения FAT (размер области 128 Кб) FATAreaAddress equ llOOOOh

; Адрес области дополнительной памяти, выделенной для

; хранения корневого каталога (размер области 16 Кб) RootDirAddress equ 130000h

; Адрес области дополнительной памяти, выделенной для

; хранения файла FileBufferAddress equ 134000h

DATASEG

; Текстовые сообщения

TxtOO

DB YELLOW,24,29,"Нажмите любую клавишу",О

Листинг 6.11 (продолжение)

Txt20

DB YELLOW,0,25,"Начальная область первой FAT:",О Txt30

DB YELLOW,0,23

DB "Список файлов корневого каталога:",О Txt40

DB YELLOW,0,16."Просмотр начального "

DB "участка файла AUTOEXEC.BAT:".0 Errl

DB 12,22,"Master-диск на канале 1 не обнаружен",0 Err2

DB 12,25."Диск не поддерживает режим LBA",0 : Номер раздела PartitionNumber

DB ? : Начальный сектор основного раздела DOS PrnDOSStartSector DD ? : Линейный адрес загрузочного сектора BootSectorDD ?

; Флаг присутствия в системе следующего диска NextDrivePresent

DB ?

; Число секторов в кластере SectorsInCluster DW ?

; Число резервных секторов RSectsDD ?

: Число таблиц FAT на диске FATsOnDiskDW ?

: Размер одной таблицы FAT в секторах FATSizeDW ?

: Число скрытых секторов HiddenSectors DD ? : Абсолютный номер начального сектора FAT FATStartSect DD ?

: Абсолютный номер начального сектора корневого каталога

RootDirStartSect DD ?

: Начальный кластер файла

FileStartCluster DW ?

: Абсолютный номер начального сектора файла

FileStartSect DD ?

; Длина файла в байтах

FileSnzeDD ?

ENDS

SEGMENT sseg para stack ‘STACK’

DB 400h DUP(?)

ENDS CODESEG

• "A* "A’A1 A A A’ A’ A A A’ A’A A’ A A’ A’ A’ A’A’ A A "A’A1 ‘A A’ M’M’fck

;* Основной модуль программы * ;*****************************

PRX SearchAutoexecBat

mov AX,DGROUP

mov DS.AX

mov [CS:Mai nDataSeg],AX

: Установить текстовый режим и очистить экран

mov АХ,3 int 10h : Установить режим прямой адресации памяти

call Initialization

; Скрыть курсор – убрать за нижнюю границу экрана

mov [ScreenStri ng],25

mov [ScreenColumn],О call SetCursorPosition : Опросить Master-диск канала 1

mov [Channel Number].1

mov [HDDNumber],0 call ReadHDD_ID

; Диск подключен? cmp [HDDErrorCode].0 jne

@@Di skNotFound

; Режим LBA поддерживается? cmp [dword ptr SectorDataBuffer+60*2].0

je

@@LBANotSupported

: Прочитать загрузочный сектор диска 0

mov [dword ptr SectorAddress].0 call ReadHDDSector

; Записать номер начального сектора основного раздела

mov SI,offset SectorDataBuffer

add SI.lBEh ;смещение первой записи

mov EAX,[SI+8]

mov [PriDOS_StartSector],EAX

: Прочитать ВООТ-сектор основного раздела диска 0

mov EAX.[PnDOS_StartSector]

mov [SectorAddress],EAX call ReadHDDSector

; Записать основные параметры для расчетов

mov SI, offset SectorDataBuffer

; Число секторов в кластере movzx АХ,[byte ptr SI+ODh]

mov [SectorsInCluster],AX

; Число резервных секторов movzx EAX,[word ptr SI+OEh]

mov [RSects],EAX : Число копий FAT в разделе movzx AX,[byte ptr Sl+lOh]

mov [FATsDnDisk],AX : Размер одной таблицы FAT в секторах

mov АХ,[SI+16h]

mov [FATSize],AX

; Число скрытых секторов

mov EAX,[SI+lCh]

mov [HiddenSectors],EAX

Листинг 6.11 (продолжение)

; ПРОЧИТАТЬ И ПОКАЗАТЬ FAT ОСНОВНОГО РАЗДЕЛА ДИСКА О : Очистить экран и вывести текстовые сообщения call ClearScreen MShowColorString Txt20 MShowColorString TxtOO : Скопировать FAT в дополнительную память

; Вычислить начальный сектор FAT

mov ЕАХ. [PriDOSStartSector]

add EAX.[RSects]

mov [FATStartSect],EAX

mov [SectorAddress].EAX

; Прочитать FAT

mov EDI.FATAreaAddress

mov DX,[FATSize] ;счетчик секторов FAT

@@Next FATSector:

; Прочитать очередной сектор FAT call ReadHDDSector

inc [dword ptr SectorAddress] : Переписать сектор FAT в дополнительную память

mov SI. offset SectorDataBuffer

mov CX.512

@@NextFATSectByte: lodsb

mov [GS:EDI].AL

inc EDI

loop

@@NextFATSectByte dec DX

jnz

@@NextFATSector

; Показать на экране начальный участок FAT

mov [ScreenString],2

mov [ScreenColumn],0

mov EDI,FATAreaAddress

mov CX.256 P0FAT:

mov AX,[GS:EDI] call ShowHexWord

inc [ScreenColumn]

add EDI,2 loop

@@FAT

; Ожидать нажатия любой клавиши call GetChar

; ПРОЧИТАТЬ И ПОКАЗАТЬ КОРНЕВОЙ КАТАЛОГ

; ОСНОВНОГО РАЗДЕЛА ДИСКА О : Очистить экран и вывести текстовые сообщения call ClearScreen MShowColorString Txt30 MShowColorString TxtOO

; Скопировать корневой каталог в дополнительную память

; Вычислить начальный сектор корневого каталога

movzxЕАХ,[FATSize]

movzxEDX,[FATsOnDisk]

mulEDX

addEAX.[FATStartSect]

mov[RootDirStartSect],EAX

mov[SectorAddress],EAX

; Прочесть корневой каталог

movEDI.RootDi rAddress

movDX,RootDirSize ;счетчик секторов

@@NextRootSector:

; Прочитать очередной сектор каталога

callReadHDDSector

inc[dword ptr SectorAddress] : Переписать сектор в дополнительную память

movSI, offset SectorDataBuffer

movCX.512

@@NextRootByte: lodsb

mov[GS:EDI],AL

incEDI

loop@@NextRootByte

decDX

jnz@@NextRootSector

; Показать на экране начальный участок каталога

movAX.OBBOOh

movES.AX

movDI,160*2

movESI,RootDirAddress

movAH,WHITE

movDX,100 ;счетчик записей

@@NextFileName:

movCX.ll

@@NextNameByte:

movAL,[GS:ESI] stosw

inc[ScreenColumn]

incESI

loop@@NextNameByte

addDI,(16-11)*2

addESI,32-11

decDX

jnz@@NextFileName

; Ожидать нажатия любой клавиши

callGetChar

: НАЙТИ И ВЫВЕСТИ НА ЭКРАН ФАЙЛ AUTOEXEC.BAT ‘ : Очистить экран и вывести текстовые сообщения call С1earScreen MShowColorString Txt40 MShowColorString TxtOO : Найти в корневом каталоге файл AUTOEXEC.BAT

Листинг 6.11 (продолжение)

movESI,RootDi rAddress

movCX.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@@AutoexecFi1eFound

@@NotAutoexec:

addESI,32 :прибавить разиер элемента

loop@@NextElement : Ошибка – файл AUTOEXEC.BAT не найден

; Показать начальный участок файла AUTOEXEC.BAT

@@AutoexecFi1eFound:

: Определить начальный кластер файла

mov АХ,[GS:ESI+lAh]

mov [FileStartCluster],АХ

; Определить длину файла в байтах

mov ЕАХ,[GS:ESI+lCh]

mov [FileSize],ЕАХ

; Вычислить абсолютный номер сектора movzx ЕАХ,[FileStartCluster] sub ЕАХ,2

movzx EDX.[SectorsInCluster] mul EDX

add EAX,[RootDirStartSect]

add EAX,RootDirSize

mov [Fi1eStartSect],EAX

mov [SectorAddress],EAX

; Прочитать кластер

mov EDI,Fi 1 eBufferAddress

mov DX,[SectorsInCluster]

@@NextFi1eSector:

; Прочитать очередной сектор файла cal1 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 АХ,0B800h

mov ES,AX

mov DI.160*2 ;вывод начать со 2-й строки

mov ESI.FileBufferAddress :сиещение данных

mov ЕСХ,[FileSize];разнер файла

mov DX,0 счетчик строк экрана

mov ВХ,0 счетчик колонок экрана

mov АН, LIGHT GREEN

@@0utl:

; Загрузить очередной символ строки в AL

mov AL.[GS:ESI]

inc ESI

; Проверка на символ конца строки cmp AL.ODh jz

@@0ut2

: Проверка на символ перевода строки

; (игнорировать его) cmp AL,OAh jz

@@0ut3

; Вывести символ на экран stosw

inc ВХ cmp ВХ.ВО jb

@@0ut3

@@0ut2:

add DI.160 sub DI.BX sub DI.BX

mov BX.O

inc DX cmp DX.22 ja

@@0utEnd

@@0ut3: dec ECX

jnz @0Outl P@0utEnd:

; Ожидать нажатия любой клавиши

cal1 GetChar

; Переустановить текстовый режим

mov ах,3 int 10h : Выход в DOS

mov АН.40) int 21h

: Обработка ошибок

@@DiskNotFound:

MFatalError Errl :диск не найден POLBANotSupported:

MFatalError Err2 ;диск не поддерживает LBA ENDP SearchAutoexecBat ENDS

Листинг 6.11 (продолжение)

; Подключить процедуры ввода данных и вывода на экран

; в текстовом режиме

Include "listl_02.inc"

; Подключить подпрограмму, переводящую сегментный

; регистр 6S в режим линейной адресации

Include "list2_01.inc"

: Подключить процедуру непосредственного считывания

; сектора с жесткого диска

Include "list6_07.inc"

END

ПРИМЕЧАНИЕ

В приведенных примерах Master-диск Primary-раздела был выбран исходя из того, что в персональных компьютерах традиционно жесткий диск подключается именно таким образом (в старых моделях компьютеров такое подключение обеспечивало максимальную скорость передачи данных, а затем это стало фактическим стандартом, вошло в привычку).

Источник: Кулаков В. К90 Программирование на аппаратном уровне: специальный справочник (+дискета). 2-е издание. — СПб.: Питер, 2003. — 847 е.: ил.

По теме:

  • Комментарии