Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Прерывание 16h

Вопрос:
в главе 2.3 Калашников пишет: «Работать с клавиатурой позволяет прерывание BIOS (ПЗУ) 16h, которое можно вызвать даже до запуска операционной системы, в то время как прерывания 20h, 21h и пр. доступны только после загрузки IO.SYS/MSDOS.SYS …» Вопрос у меня, а как этот вызов прерывания 16h можно проверить до запуска ОС? Возможно ли на ассемблере написать программу, которая даст запуститься ОС только после того, когда я нажму клавишу на клавиатуре? Мне в голову ничего не приходит.

Ответ:
Да это так.
Сразу после включения компьютера BIOS производит самодиагностику всего установленого "железа" и если тесты POST прошли успешно, то она начинает перебирать все устройства указаные в списке начальной загрузки(см. приложение 1):
«Boot Sequence» (последовательность начальной загрузки системы) — определяется последовательность опроса накопителей для загрузки операционной системы. Эти устройства обозначаются либо буквами для физических жестких дисков и обычных дисководов, либо названием устройства. Поддерживаются устройства: LS-120, Iomega ZIP, ATAPI CD-ROM, IDE- и SCSI-диски. Может принимать значения: 
«A,C» — такой выбор оправдан только для случая загрузки с дискеты и встречается в старых моделях ПК 
«A,C,SCSI» 
«C only» 
«C,A» 
«C,A,SCSI» 
«C,CDROM,A» 
«CDROM,C,A» 
«D,A,SCSI» (предназначено при использовании минимум двух IDE-жестких дисков) 
«E,A,SCSI» (аналогично для 3-х дисков) 
«F,A,SCSI» (аналогично для 4-х дисков) 
«LS/ZIP,C» 
«SCSI,A,C» 
«SCSI,C,A» 
В некоторых версиях BIOS опция «Boot Sequence» трансформировалась в несколько самостоятельных опций, с большей возможностью отбора и большей гибкостью: «First Boot Device», «Second Boot Device», «Third Boot Device», «Boot Other Device» (соответственно «первое», «второе», «третье» и «другое» загрузочные устройства). 
Могут принимать следующие значения: 
«Floppy» 
«HDD-0» 
«HDD-1» 
«HDD-2» 
«HDD-3» 
«LAN» 
«SCSI» 
«LS/ZIP» 
«CDROM» 
«Enable» 
«Disable» 
Обычно, следует выбирать вариант, в котором первым опрашиваемым устройством является жесткий диск, чтобы система не тратила время на опрос других накопителей.
На каждом из этих устройств ищется главный загрузочный сектор ( MBR-Master boot record), его структуру для FDD и HDD смотрите по 7.1.24. Формат первого сектора жесткого диска (очень много полезной информации). Как только будет найден MBR, BIOS передаст ему управление и уже дальнейшую загрузки любой операционной системы будет производить код MBR. Только после этого будут доступны прерывания DOS. В приложении программа которая запишет загрузочный сектор на дискету - FDD и при загрузке с нее будет считывать информацию об MBR - HDD с выводом на экран.
MASM;IDEAL or MASM
MODEL tiny
.386
CODESEG
org	100h
;настраиваем сегменты
start:		push	cs
		pop	es
;запускаем мотор дисковода
		xor	ax,ax
		int	13h
		xor	ax,ax
		int	13h
		xor	ax,ax
		int	13h
		xor	ax,ax
		int	13h
;записываем бут-сектор
		mov	ax,0301h;пишем один сектор
		mov	bx,offset BootSector;смещение на код бут-сектора
		mov	cx,01;номер цилиндра и сектора
		xor	dx,dx;номер головки и дисковода
		int	13h
;ожидаем любую клавишшу
		xor	ax,ax
		int	10h
;выход
		ret
;
;
;
;сам код бут сектора
;если его скомпилировать отдельно должно быть 512-ть байт
;
;
;настраиваем сегменты и стек
BootSector:	xor	ax,ax
		mov	ds,ax
		mov	es,ax
		mov	ss,ax
		mov	sp,7a00h
		sub	sp,2
;переходим в текстовый режим
		mov	ax,03
		int	10h
;читаем один сектор
		mov	ax,0201h;читаем один сектор
		mov	bx,7A00h;смещение куда будем читать
		mov	cx,01;цилиндр и сектор
		mov	dx,080h;головка и жесткий диск
		int	13h
;адресуем сегмент на видео буфер
		mov	ax,0b800h
		mov	es,ax
;выводим сообщение
		mov	cx,160;160 символов
		mov	si,7CCDh;откуда будем выводить
		xor	di,di;куда
		cld;направление увеличение
		mov	ah,0fh;аттрибут символа:фон и цвет
isHead:		lodsb;читаем один символ
		stosw;выводим с аттрибутом
		loop	isHead;в цикле
;настраиваемся на вывод информации
		mov	si,7BBEh;смещение прочитаной таблицы разделов
		mov	cx,4;количество записей
		xor	eax,eax
loopOut:
;выводим активность раздела
		mov	al,[si];читаем один байт
		mov	bx,6;выравнивание
		call	outputNumber
;выводим тип раздела
		mov	al,[si+4]
		call	outputNumber
;начало раздела
;выводим номер головки
		mov	al,[si+1]
		call	outputNumber
;номер сектора
		mov	al,[si+2]
		and	ax,03fh
		call	outputNumber
;номер цилиндра
		mov	ax,[si+2]
		xchg	al,ah
		shr	ah,6
		call	outputNumber
;новое выравнивание
		mov	bx,7;выравнивае
;конец раздела
;номер головки
		mov	al,[si+5]
		call	outputNumber
;номер сектора
		mov	al,[si+6]
		and	ax,03fh
		call	outputNumber
;номер цилиндра
		mov	ax,[si+6]
		xchg	al,ah
		shr	ah,6
		call	outputNumber
;номер сектора начала раздела
		mov	eax,[si+8]
		mov	bx,12
		call	outputNumber
;размер раздела в секторах
		mov	eax,[si+12]
		call	outputNumber
;следующая запись
		add	si,16
		add	di,10
		loop	loopOut
;ожидаем нажатие любой клавиши
;в принципе эти строки не нужны, если их убрать,
;то нужно коректировать константу
		xor	ax,ax
		int	16h
;вешаем компьютер, т.к. делать больше нечего, поможет только ресет
;или "фигура из 3-х пальцев" - ctrl + alt + delete
isHalt:		jmp	short isHalt
;подпрограмма вывода числа в 10-ой системе
;сохраняем используемые регистры
;Write(eax:di);
;запоминаем все регистры
outputNumber:	pusha
;будем делить на 10-ть
		mov	esi,10
;сбрасываем счетчик
		xor	cx,cx
;получаем осттаток от деления на 10-ть
isDiv:		xor	edx,edx
		div	esi
;запоминаем остаток от деления в обратном порядке в стеке
		push	dx
;считаем количество символов запомненых в стеке
		inc	cx
;повторяем пока не 0
		or	eax,eax
		jnz	isDiv
;выравниваем на нужное количество знаков
		sub	bx,cx
;выравниваем, смещая указатель
		shl	bx,1
		add	di,bx
;выводим само число в нужном порядке
isOut:		pop	ax
;преобразовываем цифру в символ и добавляем аттрибут
		or	ax,0f30h
		stosw;записываем в видеобуфер
		loop	isOut
;извлекаем из стека старый указатель на видео буфер и запоминаем новый
		pop	cx
		push	di
;востанавливаем все регистры
		popa
;сбрасываем ЕАХ
		xor	eax,eax
		ret
;заголовок таблицы
dbInfo		db	'              Starting Location     Ending Location                             '
		db	'Active  Type Head Sector Cylinder Head Sector Cylinder First Sector & Size$     '
		db	130 dup(?);константа коррекции
;обьзательные байты таблицы разделов дискеты
		db 7fh,1,0,41h,0bbh,0,7,60h,66h,6ah,0,0e9h,3bh,0ffh,0,0,55h,0aah
;итого 512 байт
;
;
;
;
;
;
;
	end	start

   Вперёд
   Содержание