Листинг 11-1. Программа READFMT
----------------------------------------------------------------
PAGE 50,132
TITLEREADFMT.ASM/.EXE
.SALL ; подавить выдачу макрорасширений в программе
.8086 ; пользоваться только командами
; микропроцессоров 8086/8088
;*************************************************************
;** Программа READFMT Версии 1.00
;** Настоящая программа считывает сектор начальной заг-
;** рузки с любого диска, расшифровывает обнаруженный в за-
;** писи начальной загрузки блок параметров BIOS(BPB),и вы-
;** водит на экран дисплея эту информацию и некоторую другую
;** расчетную информацию.
;**
;** Примечание: во время создания этой программы перек-
;** лючатель LINK "/СР:1" должен использоваться для того,
;** чтобы во время загрузки программы, ей распределялось бы
;** действительно нужное количество памяти. По умолчанию
;** максимальным объемом распределяемой памяти в том случае,
;** когда "/СР:1" не задан, является вся память выше точки
;** загрузки программы, что вызывает завершение программы с
;** выдачей сообщения об ошибке, потому что она не в состоя-
;** нии сделать дополнительное перераспределение памяти во
;** время своей работы.
;*************************************************************
;
; СОСТАВ:
INCLUDE stdequ.inc ; включить стандартный файл равенств
INCLUDE stdmac.inc ; включить стандартный файл макросов
INCLUDELIB stdlib.lib ; включить стандартную библиотеку
; STDLIB.LIB во временное редакти-
; рование
;
; Заявки на программы обращения к внешним библиотекам,
; находящиеся в STDLIB.LIB
EXTRN dosv2con:NEAR ; получить и вывести на экран текущую
; версию DOS
EXTRN dosver:NEAR ; дать текущую версию DOS
EXTRN bin2dec2:NEAR ; вывести на экран дисплея DX:AX в
; десятичных цифрах кода ASCII
; (если регистр DX=), регистр AX
; считается беззнаковым
;
; - - - - - - ИНИЦИАЛИЗАЦИЯ - - - - - - - - - - - - - - - - - -
;
.MODEL SMALL ; малая модель
.STACK 2048 ; создать 2-Кбайтовый стек
;
;*************************************************************
; ГЛАBHАЯ ПРОГРАММА
;
.DATA
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Cсылки и обращения к компонентам записи начальной заг-
; рузки, считанной с диска и помещенный в блок памяти, осу-
; ществляются при помощи ES. Обращения производятся только
. компонентам блока "Блок параметров BIOS"(BPB); первые три
; байта и все данные расположенные после области блока ВРВ
; записи начальной загрузки, игнорируются.
;
bootrecord STRUC
BootJump db 3 DUP (?) ; исходная команда перехода
OEMstring db 8 DUP (?) ; фирма-изготовитель и версия
; операционной системы MS-DOS
SectorBytes dw ?; количество байтов в секторе
ClusterSec db ?; количество секторов в кластере
ReservedSec dw ?; зарезервированные сектора
FATcopies db ?; количество копий таблицы FAT
DirEntries dw ?; количество элементов в
; корневом каталоге
TotalSectors dw ?; общее количество секторов
; диска (100% диска)
MediaDescrip db ?; описатель среды
FATsectors dw ?; количество секторов, занятых
; одной таблицей FAT
TrackSectors dw ?; количество секторов в треке
Heads dw ?; количество головок
HiddenSectors dw ?; количество скрытых секторов
bootrecord ENDS
;
.CODE
;
; Cохранение локальных данных (храните эти определения
; в сегменте программы)
;
DSsavedw seg DGROUP ; память для регистра DS
;
.DATA
PSPsegdw ?; сегмент PSP (Префикс про-
; граммного сегмента)
.CODE
main PROC NEAR ; начало основного процесса
;
;***********************************************************
; ЗАПУСК ПРОГРАММЫ
;***********************************************************
mov ds,DSsave ; инициализация DS
mov ax,es ; получить адрес сегмента PSP
mov word ptr PSPseg,ax ; ....... и сохранить его
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Bывести на экран дисплея сообщение о запуске
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@DisStr Start1_Msg ; вывести на экран дисплея
; сообщение о запуске
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Получить номер/имя дисковода
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov di,80h; командная строка
cmp byte ptr es:[di],0 ; есть ли параметры?
je get_default_drive ; нет, получить дисковод
; по умолчанию
cmp byte ptr es:[di+3],':' ; присутствует ли двое-
; точие?
jne get_default_drive ; нет, получить дисковод
; по умолчанию
get_disk_drive: ; получить дисковод в
; командной строке
xor ah,ah ; очистить AH
mov al,byte ptr es:[di+2] ; получить заданный
; дисковод
cmp al,">"; использовалась ли
; переадресовка?
je get_default_drive ; да, получить дисковод
; по умолчанию
cmp al,61h; дисковод задан буквами
; верхнего регистра?
jge convert_upper ; да, выполнить преобра-
; зование из символов
; ASCII верхнего регистра
sub al,40h; иначе выполнить из
; символов ASCII нижнего
; регистра
jmp short test_drive ; и продолжить
convert_upper:
sub al,60h; преобразование символов
; ASCII верхнего регистра
test_drive:
cmp al,1 ; число меньше единицы?
jl bad_drive ; да, выйти на сообщение
; об ошибке
dec al ; иначе выполнить А:=0,
; ...... В: = 1 и т.д.
cmp al,25 ; результат предыдущeй
; команды > 25 (>Z:)?
jg bad_drive ; да, выйти на сообщение
; об ошибке
jmp short drive_used ; иначе сохранить
; указанный дисковод
get_default_drive:
mov ah,19h; получить дисковод
; по умолчанию
@DosCall
drive_used:
mov byte ptr DiskDrive,al ; сохранить дисковод
jmp short drive_end; и продолжить
bad_drive:
@DisStr BadDrive_Msg ; иначе вывести на экран
; сообщение об ошибке
;(синтаксической ошибке)
jmp terminate ; и выйти в DOS
drive_end:
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Cчитывание в память информации сектора начальной загрузки.
; После возвращения ES:DI(ES:0) указывает на блок памяти,
; содержащий запись начальной загрузки.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
.DATA
BootSeg dw ? ; сохранение адреса
; сегмента блока памя-
; ти содержащего копию
; записи начальной
; загрузки
.CODE
mov bx,40h ; распределить 1024 байта
call memalloc ; распределить блок
jnc read_boot ; продолжить, если не
; было ошибок
call mem_err_handler ; иначе обработать ошибку
jmp terminate ; и выйти в DOS
;
; ;
read_boot:
mov word ptr BootSeg,ax ; сохранить адрес сег-
; мента
push ax ; и сохранить его
mov al,byte ptr DiskDrive ; получить дисковод
; для считывания
xor ah,ah; очистить AH
pop ds ; получить адрес сег-
; мента нового блока
mov dx,0 ; считать логический
; сектор 0
mov cx,1 ; считать в один сектор
mov bx,0 ; поместить данные в DS:0
jnt 25h ; считать диск
jc read_boot_error ; выйти, если произошла
; ошибка
popf ; очистить флаги, про-
; толкнутые в стек во
; время прерывания
; "int 25h"
mov ds,DSsave ; повторная инициали-
; зация области DS
mov ax,word ptr BootSeg ; получить адрес сегмен-
; та начальной загрузки
mov es,ax; и инициализировать в
; него ES
xor di,di; со смещением 0
jmp end_read_boot ; и продолжить
;
read_boot_error:
popf ; очистить флаги, про-
; толкнутые в стек во
; время прерывания
; "int 25h"
mov ds,DSsave ; повторная инициали-
; зация области DS
@DisStr ReadError_Msg ; выйти с выдачей
jmp terminate ; сообщения об ошибке
;
end_read_boot:
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Проверить, чтобы считанная запись начальной загрузки
; содержала нужную нам информацию. Если диском является
; 160-Кбайтный или 320-Кбайтный гибкий диск, запись начальной
; загрузки будет содержать нужную нам информацию блока ВРВ
; (это может оказаться правильным также для некоторых нестан-
; дартных форматов дисков , в случае чего таблица FAT должна
; считываться с целью получения байта идентификатора (ID)
; формата. Этот байт требуется для определения формата диска
; (является ли диск 160-Кбайтным для -версии операционной
; системы DOS 1.0 или; 360-Кбайтным для версии операционной
; системы DOS 1.1.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
mov bx,20h ; распределить 512 бай-
; ... тов (32 параграфа)
call memalloc ; распределить блок памяти
jnc read_fat ; продолжить, если ошибок
; не было
call mem_er_handler ; иначе перейти на про-
; грамму обработки ошибок
jmp terminate ; и выйти в DOS
;
read_fat:
.DATA
FATSeg dw ? ; адрес сегмента из
; таблицы FAT
.CODE
mov word ptr FATseg,ax ; сохранить адрес сег-
; мента FAT
push ax ; и сохранить его
mov al,byte ptr DiskDrive ; получить дисковод для
; считывания
xor ah,ah ; очистить AH
pop ds ; получить адрес сег-
; мента нового блока
mov dx,1; очистить логический
; сектор 1
mov cx,1; считать в один сектор
mov bx,0; сохранить данные в DS:0
jnt 25h ; читать диск
jnc process_FAT ; продолжить, если ошибок
; не было
popf ; иначе, сбросить флаги
mov ds,DSsave ; повторная инициализа-
; ция области DS
@DisStr ReadError_Msg ; выйти с сообщением об
; ошибке
mov ax,word ptr FATSeg ; получить адрес сегмента
; начальной загрузки
call memfree ; освободить блок
jnc end_fat_err ; выйти, если не было
; ошибок
call mem_err_handler ; иначе, вывести на
; экран дисплея сообще-
; ние об ошибке
end_fat_err:
jmp terminate ; выйти в DOS
;
process_FAT:
popf ; очистить флаги, про-
; толкнутые в стек во
; время прерывания
; "int 25h"
mov ds,DSsave ; повторная инициализа-
; ция области DS
mov ax,word ptr FATSeg ; получить адрес сегмента
; начальной загрузки
mov es,ax ; и инициализировать ES
xor di,di ; в него со смещением 0
.DATA
FAT_ID db ? ; байт идентификации
; (ID) из таблицы FAT
.CODE
mov al,byte ptr es:[di] ; получить элемент О
; таблицы FAT
mov byte ptr FAT_ID,at ; и сохранить его как байт
call memfree ; освободить сегмент
; таблицы FAT
; (адрес находится в ES)
jnc comp_byte_id ; продолжить, если не
; было ошибок
call mem_err_handler ; иначе вывести на экран
; сообщение об ошибке
jmp terminate ; выход в операционную
; ; систему DOS
comp_byte_id:
mov ax,word ptr BootSeg ; указать на сегмент
; начальной загрузки
mov es,ax ; ES:0 указать на
xor di,di ; запись начальной
; загрузки
mov al,byte ptr FAT_ID ; получить идентифика-
; тор (ID) таблицы FAT
cmp al,byte ptr es:[di].MediaDescrip ; и сравнить
; с битом ID
; в записи начальной
; загрузки
jne chk_dos1_fmt ; если иначе, то решить
jmp end_read_fat ; иначе, продолжить
chk_dos1_fmt:
cmp al,0FEh ; это 160-Кбайтный
; гибкий диск?
je init_dos1_fmt; да, инициализировать
; запись начальной
; загрузки
cmp al,0FFh ; иначе, это 320-Кбайт-
; ный гибкий диск?
je init_dos1_fmt; да, инициализировать
; запись начальной
; загрузки
.DATA
UnknownMedia db "Невозможно определить формат диска."
db "Возможно, это диск не "
db "операционной системы MS-DOS.",CR,LF,"$"
.CODE
@DisStr UnknownMedia ; вывести на экран
; сообщение об ошибке
jmp terminate ; выход в операционную
; систему DOS
init_dos1_fmt:
; Инициализировать элементы формата, которые одинаковы
; для 160-Кбайтных и 320-Кбайтных форматов дисков:
mov word ptr es:[di+3],"D" ; передать по буквам
; "DOS 1.X"
mov word ptr es:[di+4],"O" ; в поле ОЕМ и
mov word ptr es:[di+5],"S" ; версии DOS записи
mov word ptr es:[di+6]," " ; начальной загрузки
mov word ptr es:[di+7],"1"
mov word ptr es:[di+8],"."
mov word ptr es:[[b]di].SectorBytes,512 ; коли-
; чество байтов в секторе
mov word ptr es:[di].ReservedSec,1 ; зарезер-
; вированные секторы
mov word ptr es:[di[.FATcopies,2 ; количест-
; во копий таблицы FAT
mov word ptr es:[di].FATsectors,1 ; количество
; секторов таблицы FAT
mov word ptr es:[di].TrackSectors,8 ; количество
; секторов в треке
mov word ptr es:[di].HiddenSectors,0 ; количество
; скрытых секторов
cmp al,0FEh ; это гибкий 160-Кбайтный диск?
je init_160K ; да, инициализировать запись
; начальной загрузки
cmp al,0FFh ; иначе, это гибкий 320-Кбайтный
; диск?
je init_320K ; да, инициализировать запись
; начальной загрузки
;
init_160K:
mov word ptr es:[di.9],"0" ; это версия
; "DOS 1.0"?
mov word ptr es:[di.10],"?" ;
mov byte ptr es:[di].ClusterSec,1 ; количество
; секторов в
; кластере
mov word ptr es:[di].DirEntries,64 ; количество
; элементов
; в каталоге
mov word ptr es:[di].TotalSektors,320 ; общее ко-
; личество
; секторов
; на диске
mov byte ptr es:[di].MediaDescrip,0FEh ; описатель
; носителя
mov word ptr es:[di].Heads,1 ; количество головок
jmp end_read_fat
;
init_320K:
mov word ptr es:[di.9],"1" ; это версия
; "DOS 1.1"?
mov word ptr es:[di.10],"?"
mov byte ptr es:[di].ClusterSec,2 ; количество
; секторов в
; кластере
mov word ptr es:[di].DirEntries,112 ; количество
; элементов
; в каталоге
mov word ptr es:[di].TotalSektors,640 ; общее ко-
; личество
; секторов
; на диске
mov byte ptr es:[di].MediaDescrip,0FFh ; описатель
; носителя
mov word ptr es:[di].Heads,2 ; количество головок
jmp end_read_fat
;
end_read_FAT:
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Вычислить величины, отсутствующие в блоке параметров
; BIOS. Примечание: ES:DI (смещение 0) должен указывать на
; начало записи начальной загрузки, считанной в память. Все
; расчетные значения сохраняются в сегменте данных.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
get_new_values:
xor di,di ; очистить DI
;
; Рассчитать общее количество секторов, используемых для всех
; копий таблицы FAT.
xor ah,ah ; очистить AH
mov al,byte ptr es:[di].FATcopies ; получить копии
; таблицы FAT
xor dx,dx ; очистить DX
mov bx,word ptr es:[di].FATsectors ; получить число
; секторов таблицы
; FAT
mul bx ; умножить на
; это число
mov word ptr TotalFATSec,ax ; сохранить ре-
; зультат в 1 слове
;
; Рассчитать общее количество секторов, используемых всеми
; элементами каталога
mov ax,word ptr es:[di].DirEntries ; получить общее
; количество эле-
; ментов корневого
; каталога
mov bx,word ptr DirEntBytes ; получить размер
; в байтах эле-
; ментов каталога
xor dx,dx ; очистить DX
mul bx ; умножить
mov bx,word ptr ;
es:[di].SectorBytes ; получить количество байтов в секторе
xor dx,dx ; очистить DX
div bx ; разделить
mov word ptr DirSectors,ax ; сохранить ре-
; зультат в 1 слове
;
; Вычислить общее количество цилиндров
mov ax,word ptr es:[di].TotalSectors ; получить общее
; количество секторов
mov bx,word ptr es:[di].TrackSectors ; получить ко-
; личество секторов в треке
xor dx,dx ; очистить DX
div bx; и разделить на него
mov bx,word ptr es:[di].Heads ; получить число головок
xor dx,dx ; очистить DX
div bx; и разделить на него
cmp word ptr es:[di].HiddenSectors ; скрытые сектора?
je store_cyl ; нет, теперь мы
; имеем общее количество цилиндров
mov cx,word ptr es:[di].HiddenSectors ; иначе, скрытые
; сектора = 1
cmp cx,word ptr es:[di].TrackSectors ; цилиндр?
je add_cyl ; да
mov ax,0 ; иначе, произошла ошибка
jmp short store_cyl ;
add_cyk:
add ax,1 ; добавить дополнительный цилиндр
store_cyl:
mov word ptr Cylinders,ax ; сохранить результат
;
; Получить общее количество байтов на всем (100%) диске
mov ax,word ptr es:[di].TotalSectors ; получить
; общее количество секторов
xor dx,dx ; очистить DX
mov bx,word ptr es:[di].SectorBytes ; получить
; количество байтов в секторе
mul bx ; и умножить на него
mov word ptr TotalBytes,ax ; и сохранить резуль-
; тат, состоящий из двух слов
mov word ptr TotalBytes.2,dx ; из AX и DX
;
; Получить общее количество секторов данных (в которых могут
; сохраняться файлы)
mov ax,word ptr es:[di].TotalSectors ; получить
; общее количество секторов
xor dx,dx; очистить DX
sub ax,word ptr es:[di].ReservedSec ; вычесть
; зарезервированные секторы
sub ax,word ptr TotalFATSec ; вычесть общее
; количество секторов таблицы FAT
; (все копии таблицы FAT)
sub ax,word ptr DirSectors ; вычесть секторы
; корневого каталога
mov word ptr DataSectors,ax ; и сохранить результат
;
; Получить количество байтов в кластере
xor ah,ah; очистить AH
mov al,byte ptr es:[di].ClusterSec ; получить секторы
; кластера
xor dx,dx; очистить DX
mov bx,word ptr es:[di].SectorBytes ; получить байты
; сектора
mul bx ; и умножить на это число
mov word ptr ClusterBytes,ax ; и сохранить результат
;
; Получить общее количество секторов
mov ax,word ptr DataSectors ; получить секторы данных
xor bh,bh ; очистить BH
mov bl,byte ptr es:[di].ClusterSec ; получить секторы
; кластера
xor dx,dx ; очистить DX
div bx ; разделить на количество секторов
mov word ptr TotalClusters,aх ; и сохранить результат
; в слове
;
; Получить количество битов в элементе таблицы FAT.
; Всегда 12 битов, если общее количество кластеров = 4,085 или
; меньше.
; Всегда 16 битов, если общее количество кластеров больше
; 4,085.
cmp word ptr TotalClusters,4085 ; общее коли-
; чество кластеров больше 4085?
jle got_entry_size ; нет используйте 12-битовое
; значение по умолчанию
mov al,16 ; иначе - 16-битовое значение
mov byte ptr FATentryBits,al ; и сохранить значение
got_entry_size:
;
; Получить общее количество байтов данных (используемых байтов)
mov ax,word ptr DataSectors ; получить общее коли-
; чество секторов
xor dx,dx, ; очистить DX
mov bx,word ptr es:[di].SectorBytes ; получить байты
; сектора
mul bx ; и умножить на это число
mov word ptr DataBytes,ax ; и сохранить результат
; в 2 словах
mov word ptr DataBytes,2,dx ; из AX и DX
;
; Вычислить регистр диска в килобайтах или мегабайтах
mov ax,word ptr TotalBytes ; получить общее коли-
; чество байтов на диске
mov dx,word ptr TotalBytes.2 ; ... (двойное слово)
mov cx,1024 ; установить делитель
div cx ; и получить значение в килобайтах
mov word ptr KBytes,ax ; сохранить значение
cmp ax,1000 ; вычислить в Мегабайтах?
jl dis_info ; нет, мы закончили
mov bx,1000 ; иначе установить делитель
xor dx,dx ; очистить регистр DX
div bx ; и получить мегабайты
mov word ptr Mbytes,ax ; сохранить главное значение
mov word ptr Mbytes2,dx ; и сохранить часть, если
; таковая имеется
cmp dx,0 ; есть ли часть?
je megabytes_end ; нет, мы закончили
mov ax,dx ; иначе установить делимое
mov bx,10 ; установить делитель
xor dx,dx ; очистить регистр DX
;
; Цикл удаления хвостовых нулей
compress_loop:
div bx ; разделить регистр AX на 10
cmp dx,0 ; есть ли остаток?
jne megabytes_end ; да, мы закончили
mov word ptr Mbytes2,ax ; иначе сохранить новое
; сжатое значение
jmp short compress_loop ; и снова повторить
megabytes_end:
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Отобразить на экране дисплея информацию о диске
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dis_info:
@DisStr Start2_Msg ; отобразить на экране дисплея
; первую часть сообщения о дисководе
xor ah,ah ; очистить регистр AH
mov al,byte ptr DiskDrive ; и вывести на экран
; имя дисковода
inc al; дать ему используемый номер
add al,40h ; преобразовать его в буквы
; ; ... ASCII верхнего регистра
@DisChr al ; и вывести его на экран
@DisChr ':' ; после него поставить двоеточие
@Newline
;
@DisStr OEM_Msg ; вывести на экран сообщение OЕМ
; (о фирме-производителя и версии)
push di ; сохранить DI
mov di,bootrecord.OEMstring ; указать строку ОЕМ
mov cx,8 ; установить счетчик символов
more_char: ; ввести дисплейный цикл
mov al,byte ptr es:[di] ; получить символ
@DisChr al ; отобразить символ на экране дисплея
inc di ; указать на следующий символ
dec cx ; счетчик десятичных символов
cmp cx,0 ; все сделаны ?
jg more_char ; нет, вывести следующий символ
@NewLine ; иначе, мы закончили
pop di ; восстановить DI
;
@DisStr MeliaDescrip_Msg ; отобразить на экране
; описатель носителя
xor ah,ah, ; очистить регистр AH
mov al,byte ptr es:[di].MediaDecrip ; считать
; байтовое значение
@DisNum ax,16,2 ; отобразить две шест-
; надцатиричные цифры
cmp byte ptr es:[di].MediaDescrip,0F8h ;жесткий диск?
je fixed_disk ; да, отобразить на экране сообщение
@DisStr RemovableMedia_Msg ; иначе - сменный диск
jmp short media_size ; и теперь сделать размер
; в Kb/Mb
fixed_disk:
@DisStr FixedMedia_Msg ; отобразить на экране
; сообщение о жестком носителе
media_size:
cmp word ptr Mbytes,0 ; показывать в Мегабайтах
je show_kilobytes ; нет, в Килобайтах
mov ax,word ptr Mbytes ; да, задать в Мегабайтах
@DisNum ax,10,1,0 ; вывод десятичного числа
; без знака
cmp word ptr Mbytes2,0
; есть ли часть?
je done_mbytes ; нет, мы закончили
@DisChr '.' ; иначе, вывести на
; экран десятичную точку
mov ax,word ptr Mbytes2 ; задать часть в Мбайтах
@DisNum ax,10,1,0 ; вывод десятичного числа
; без знака
done_mbytes:
@DisChr 'M' ; вывести на экран сим-
; вол "М" (Мегабайт)
jmp short done_media ; и мы закончили
show_Kilobytes:
mov ax,word ptr Kbytes ; получить значение в
; Килобайтах
@DisNum ax,10,1,0 ; вывод десятичного
; числа без знака
@DisChr 'K' ; вывести на экран символ "К" (Кбайт)
done_media:
@DisStr Media_Msg ; вывести на экран конец
; сообщения
@NewLine
;
@DisStr Cylinders_Msg ; отобразить на экране
; дисплея общее количество цилиндров (треков)
cmp word ptr Cylinders,0 ; была ли ошибка?
jne show_cyl ; нет, отобразить на экране
; дисплея общее количество цилиндров
@DisChr '?' ; иначе, вывести на экран символ
; "знак вопроса"
jmp short end_cyl; и закончить
show_cyl:
mov ax,word ptr Cylinders ; получить значение
@DisNum ax,10,1,0 ; и отобразить его на
; экране дисплея
end_cyl:
@NewLine
;
@DisStr Heads_Msg; отобразить на экране
; количество головок
mov ax,word ptr es:[id].Heads ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr TrackSectors_Msg ; отобразить на экране
; дисплея количество секторов в треке
mov ax,word ptr es:[di].TrackSector ; получить
; значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr SectorBytes_Msg ; отобразить на экране
; дисплея количество байтов в секторе
mov ax,word ptr es:[id].SectorBytes ; получить значе-
; ние слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr НiddenSectors_Msg ; отобразить на экране
; дисплея количество скрытых секторов
mov ax,word ptr es:[di].HiddenSectors ; получить зна-
; чение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
cmp word ptr es:[di].HiddenSectors,0 ; есть ли
; скрытые сектора?
je hidden_done ; нет, мы закончили
@DisStr PartitionInfo_Msg ; иначе, дать инфор-
; мацию о разделении
hidden_done:
@NewLine
;
@DisStr TotalSectors_Msg ; отобразить на экране
; дисплея общее количество секторов диска
mov ax,word ptr es:[di].TotalSectors ; получить
; значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr TotalBytes_Msg ; отобразить на экране
; дисплея общее количество байтов на диске
mov ax,word ptr TotalBytes ; получить значение,
; состоящее из двух слов и ...
mov dx,word ptr TotalBytes.2 ; поместить его в
; регистры AX и DX
call bin2dec2 ; и вывести на экран
; результат DX:AX
@NewLine
;
@DisStr ReservedSec_Msg ; отобразить на экране
; дисплея количество зарезервированных секторов
mov ax,word ptr es:[di].ReservedSec ; получить
; значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr FATsectors_Msg ;отобразить на
; экране дисплея количество секторов
; в одной таблице FAT
mov ax,word ptr es:[di].FATsectors ; получить
; значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr FATcopies_Msg ; отобразить на экране дисплея
; количество копий таблицы FAT
xor ah,ah ; очистить AH
mov al,byte ptr es:[di].FATcopies ; получить
; значение байта
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr TotalFATsectors_Msg ; отобразить на экране
; дисплея общее количество секторов для
; всех таблиц FAT
mov ax,word ptr TotalFATSec ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr DirEntries_Msg; отобразить на экране
; дисплея количество элементов корневого каталога
mov ax,word ptr es:[di].DirEntries ; получить значение
; слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr DirSektors_Msg ; отобразить на экране
; дисплея общее количество секторов
; корневого каталога
mov ax,word ptr DirSectors ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr DataSectors_Msg ; отобразить на экране
; ; дисплея общее количество секторов данных
mov ax,word ptrDataSectors ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr ClusterSectors_Msg ; отобразить на экране
; дисплея количество секторов в кластере
xor ah,ah ; очистить AH
mov al,byte ptr es[di].ClusterSec ; получить значение
; байта
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr ClusterBytes_Msg ; отобразить на экране
; дисплея количество байтов в кластере
mov ax,word ptr ClusterBytes ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr Totalclusters-Msg ; отобразить на экране
; дисплея общее количество кластеров
mov ax,word ptr Totalclusters ; получить значение слова
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@NewLine
;
@DisStr FATentrySize_Msg; отобразить на экране
; дисплея размер каждого элемента таблицы FAT
xor ah,ah ; очистить AH
mov al,byte ptr FATentryBits ; получить значение
; байта
@DisNum ax,10,1,0 ; вывод десятичного числа без знака
@DisStr Bits_Msg ; указать, что значение
; задано в битах
cmp byte ptr FATentryBits,12 ; определить, сколько
; имеется байтов
jg dis_two_bytes
@DisStr SmallFAT_Msg ; элемент таблицы FAT = 1,5 байта
jmp short show_fat_done
dis_two_bytes:
@DisStr LargeFAT_Msg ; элемент таблицы
; FAT = 2 байта
show_fat_done:
;
@NewLine
;
@DisStr DataBytes_Msg ; отобразить на экране дисплея
; количество байтов данных на диске
mov ax,word ptr DataBytes ; получить значение
mov dx,word ptr DataBytes.2 ; состоящее из двух
; слов и поместить его в регистры AX и DX
call bin2dec2 ; и вывести его на экран дисплея
@NewLine
;
push es ; сохранить текущее значение ES
mov ax,word ptr BootSeg ; получить адрес сегмента
; распределенного блока
mov es,ax ; и назначить ему ES
call memfree ; освободить блок
pop es; восстановить значение ES
;
terminate:
@ExitToDOS ; завершить программу
;
;************************************************************
; Конец программы
;************************************************************
main ENDP ; конец главного процесса
;
;************************************************************
; Запуск стандартных программ
;*************************************************************
;
;+++++++++++++++++++++++++++++++++++++++++++++++++
; MEM_ERR_HANDLER: Описатель ошибки распределения памяти
; (освобождения памяти) изменения размера.
;BXОД: AX = код ошибки
; BX = максимальный доступный блок памяти
; (если код ошибки = 8)
; ЕX = адрес сегмента распределенного блока
; (если код ошибки = 9)
;
;ВЫХОД: ни один (все регистры восстановлены)
;
;Вызываемые стандартные программы : нет
;- - - - - - - - - - - - - - - - - - - - - - - - -
mem_err_handler PROC NEAR
;
cmp ax,7 ; очищенные от мусора управляющие
; блоки памяти ?
jne mem_error8 ; нет, продолжить проверку
.DATA
NranshedMemErr_Msg db "Ошибка распределения памяти:"
db"разрушены управляющие блоки памяти.",CR,LF,"$"
.CODE
@DisStr TrashedMemErr_Msg ; да, выйти с сообщением
ret ; возврат
;
mem_error8:
cmp ax,8 ; недостаточно памяти ?
jne mem_error9 ; нет, продолжить проверку
.DATA
InsuffMemErr_Msg db "Ошибка распределения памяти:"
db "недостаточно памяти",CR,LF
db "Hаибольший доступный блок памяти = $"
.CODE
@DisStr InsuffMemErr_Msg ; да, выйти с сообщением
@DisNum bx,10,1,0 ; доступен
@NewLine ; вывести на экран пустую строку
ret ; возврат
;
mem_error9:
cmp ax,9 ; неправильный адрес блока памяти?
jne mem_err_unknown ; нет, неизвестная причина
.DATA
IncorrSegAddr_Msg db "Неправильный адрес сегмента для изменения"
db "изменения размера/освобождения.",CR,LF
db "Адрес сегмента = $"
.CODE
@DisStr IncorrSegAddr_Msg ; вывести на экран
; дисплея сообщение об ошибке
@DisNum es,16,4 ; вывести на экран дисплея адрес
; сегмента
@NewLine; вывести на экран пустую строку
ret ; возврат
;
mem_err_unknown:
.DATA
UnknownMemErr_Msg db "Hеизвестная ошибка распределения/"
db "/изменения размера/освобождения памяти.",CR,LF,"$"
.CODE
@DisStr UnknownMemErr_Msg ; вывести на экран
; дисплея сообщение
ret
;
mem_err_handler ENDP
;
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; MEMALLOC: Распределить блок памяти заданного размера в
; параграфах (1 параграф = 16 байтам).
;
;BXОД: BX = размер в 16-байтовых параграфах запрошенного
; блока
;
;ВЫХОД: "Успешно", если признак переноса = 0 при
; AX = адрес сегмента распределенного
; блока памяти (BX восстанавливается)
; "Сбой", если признак переноса = 1 при
; AX = код ошибки
; 7 = разрушены управляющие блоки памяти
; 8 = недостаточно памяти
; BX = наибольший доступный блок памяти
; в параграфах
; Вызываемые стандартные программы: нет
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - -
memalloc PROC NEAR
;
push bp ; сохранить указатель базы
push bx ; сохранить регистр BX
mov bp,sp ; инициализировать указатель базы
;
xor al,al ; очистить AL
mov ah,48h ; загрузить функцию распределения
; памяти
@DosCall ; выполнить распределение памяти
jnc end_memalloc ; выйти, если нет ошибок с
; с адресом сегмента в регистре AX
; иначе, выйти с установленным
; признаком переноса;
mov word ptr [bp],bx ; блок максимального размера
; (BX) и код ошибки в AX
;
end_memalloc:
pop bx; восстановить регистр BX
pop bp; восстановить указатель базы
ret
memalloc ENDP ;
;
;
;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; MEMFREE: Освобождение памяти : освободить блок памяти,
; распределенный ранее стандартной программой MALLOC
;
;BXОД: ES = адрес сегмента распределенного блока памяти
;
;ВЫХОД: "Успешно", если признак переноса = 0
; (ES восстанавливается)
;
;"Сбой", если признак переноса = 1 при
; AX = код ошибки
; 7 = разрушены управляющие блоки памяти
; 9 = неправильный адрес (ES восстанавливается)
;
; Вызываемые стандартные программы: нет
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - -
memfree PROC NEAR
;
push bp ; сохранить указатель базы
push es
push ax ; сохранить регистр AX
mov bp,sp ; инициализировать указатель базы
;
xor al,al ; очистить AL
mov ah,49h ; загрузить функцию
; освобождения памяти
@DosCall; выполнить освобождение памяти
jnc end_memfree ; выход, если не было ошибок
; иначе, выйти с установленным
; признаком переноса
mov word ptr [bp],ax ; и код ошибки
;(в регистре AX)
;
end_memfree:
pop ax; восстановить регистр AX
pop es
pop bp; восстановить указатель базы
ret
;
memfree ENDP
;
;
;************************************************************
; Конец стандартной программы
;************************************************************
;
.DATA ; переключение на сегмент данных
;************************************************************
; Hачало области сохранения данных
;************************************************************
;
; Переменные
;
DiskDrive db 0 ; рабочий дисковод (начальное
; значение = дисковод по умолчанию)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Остальные (из вычисленных) переменные параметров дискового
; формата :
Cylinders dw ? ; общее количество цилиндров
TotalBytes dd ? ; общая емкость диска в байтах
TotalFATSec dw ? ; общее количество секторов таблицы
; FAT (всех копий)
DirEntBytes dw 32 ; число байтов в элементе каталога
DirSectors dw ? ; сектора, занятые корневым каталогом
DataSectors dw ? ; общее количество секторов для хранения
; файлов
ClusterBytes dw ? ; количество байтов в кластере
TotalSectors dw ? ; общее количество кластеров
FATentryBits db 12 ; количество битов в элементе таблицы FAT
DataBytes dd ? ; общее количество байтов данных (для
; хранения файла)
Kbytes dw ? ; общее количество килобайт (всего в
; диске)
Mbytes dw 0 ; общее количество мегабайт (всего в
; диске)
Mbytes2 dw 0 ; и общее количество частей в мегабайтах
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Tекстовые сообщения
;
Start1_Msg db "Идентификатор формата диска операционной"
db "системы MS-DOS"
db "-- Версия 1.00",CR,LF,"$"
Start2_Msg db "BPB = Значение, извлеченное из записи"
db " начальной загрузки;"
db "CAL = Вычисленное значение",CR,LF,CR,LF
db "Информация о формате для дисковода $"
;
OEM_Msg db "BPB: Форматируется при помощи: $"
SectorBytes_Msg db "BPB: Количество байтов в секторе: $"
ClusterSectors_Msg db "BPB: Количество секторов в "
db "кластере: $"
ReservedSec_Msg db "BPB: Зарезервированные сектора: $"
FATcopies_Msg db "BPB: Копии таблицы FAT: $"
DirEntries_Msg db "BPB: Элементы корневого каталога: $"
TotalSectors_Msg db "BPB: Общее количество секторов "
db "диска: $"
MediaDescrip_Msg db "BPB: Описатель носителя: $"
FATsectors_Msg db "BPB: Сектора таблицы FAT "
db "(1 таблицы FAT): $"
TrackSectors_Msg db "BPB: Общее количество секторов "
db "в цилиндре: $"
Heads_Msg db "BPB: Головки: $"
HiddenSectors_Msg db "BPB: Скрытые секторы: $"
;
TotalFATsectors_Msg db "CAL: Общее количество секторов "
db "таблицы FAT: $"
DirSectors_Msg db "CAL: Секторы каталога: $"
Total Bytes_Msg db "CAL: Общее количество байтов на"
db "диске: $"
Cylinders_Msg db "CAL: Общее количество цилиндров: $"
DataSectors_Msg db "CAL: Общее количество секторов "
db "данных: $"
TotalCluaters_Msg db "CAL: Общее количество кластеров: $"
ClusterBytes_Msg db "CAL: Количество байтов в кластере: $"
FATentrySyze_Msg db "CAL: Размер элемента таблицы FAT: $"
DataBytes_Msg db "CAL: Общее количество байтов "
db "данных: $"
;
FixedMedia_Msg db "(жесткий $"
RemovableMedia_Msg db "(сменный $"
Media_Msg db "носитель)$"
Bits_Msg db "биты$"
Bytes_Msg db "байты$"
SmallFAT_Msgdb "1,5 байта)$"
LargeFAT_Msgdb "(2 байта)$"
CurrPartition_Msg db "(в пределах текущего разделения)$"
PartitionInfo_Msg db "(информация о разделении)$"
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Сообщения об ошибках:
NonDOSerr_Msg db "Диск не может быть считан."
db "Вероятно, это не диск системы DOS.",CR,LF,"$"
BadDrive_Msg db "синтаксическая ошибка или"
db "заданный дисковод не разрешен.",CR,LF,"$"
ReadError_Msg db "Общая ошибка при чтении диска."
db CR,LF,"$"
UnknownErr_Msg db "Неизвестная ошибка - завершение."CR,LF,"$"
;
;
;***********************************************************
; Конец памяти данных
;***********************************************************
END main ; конец программы
----------------------------------------------------------------
|