При загрузке компьютера BIOS считывает первый сектор дискового накопителя (жесткий/гибкий диск/DVD/CDROM) (MBR) в оперативную память по адресу 0000:7С00h и передает туда управление. Затем уже загрузчик передает управление операционной системе. Чтобы BIOS мог идентифицировать программу начальной загрузки, она в конце должна содержать ключ 55h 0aah.
Начальный загрузчик может выглядеть примерно так (для создания исполняемого файла воспользуемся MASMом и скомпилируем com-файл)
;===================== Загрузочный сектор. Евгений Попов, 2011===================== ;================================================================================== .model tiny ;для того чтобы masm скомпилировал односегментную программу не более 512 байт CSEG segment assume CS:CSEG org 7c00h ;BIOS производит чтение 512 байт первого сектора MBR в ОЗУ по адресу 0x00007C00 ;(0x07C0:0x0000 в формате реального режима), затем прочитанному коду передаётся управление start: cli ;запрещаем прерывания xor ax,ax ;обнуляем регистр ах mov ds,ax ;настраиваем сегмент данных на нулевой адрес mov es,ax ;настраиваем сегмент es на нулевой адрес mov ss,ax ;настраиваем сегмент стека на нулевой адрес mov sp,07C00h ;сегмент sp указывает на текущую вершину стека sti ;разрешаем прерывания ;очищаем экран mov al, 02h mov ah, 00h int 10h call GetCursorPos ;получаем позицию курсора mov bp, offset msg ; Загрузка mov cx, 15 call print ;Вывод на экран строки msg add dh,1 ;переходим на одну строку ниже call SetCursorPos mov bp, offset Con ; Загрузка mov cx, 23 call print mov dx,1701h call SetCursorPos mov bp,offset Off mov cx,30 call print mov bp, offset Copyright mov cx,30 add dh,01h call SetCursorPos call print call Char_in cmp al,'o' jz Turn_Off cmp al,'r' jz Restart ;cmp al, 0Dh ;Если нажимаем на Enter, то переходим к загрузке ядра ;jz Kernel ;поскольку ядра нет, код оставлен на будущее jmp $ ;===================== Подпрограммы =================================== print: ;в регистре bp - строка, в регистре cx - длина этой строки mov bl,04h ;в регистре bl- атрибут mov ax,1301h int 10h ret ;---------------------------------- GetCursorPos: ;получаем текущее значение курсора функиция 3h прерывания 10h ; в bh страница mov ah,3h xor bh,bh int 10h ret ;---------------------------------- SetCursorPos: ;установка курсора : функция 02h прерывания 10h mov ah,2h xor bh,bh int 10h ret ;---------------------------------- Char_in: ;ожидание нажатой клавиши : функция 10h прерывания 16h mov ah,10h int 16h ret ;---------------------------------- Turn_Off: ;выключение компа mov ax,5301h sub bx,bx int 15h jb stop mov ax,530eh sub bx,bx int 15h jb stop mov ax,5307h mov bx,0001h mov cx,0003h int 15h stop: ret Restart: jmp dword ptr reboot ;===================== выводимые сообщения===================== msg db Hello Eugene...',0 Off db 'r --restart o --turn off',0 Copyright db 'Copyright ',1,' Eugene Popov, 2011',0 Con db 'Press Enter to Continue',0 reboot dd 0ffff0000h ;переход по этому адресу будет вызывать перезагрузку ;---------------------------------- codeend: db 510-(codeend-start) dup (0) ;заполняем оставшуюся часть нулями db 055h,0AAh ;сигнатура, символизирующая о завершении загрузочного сектора CSEG ends end start
Теперь выведем результат программы. Для этого воспользуемся эмулятором Bochs. Сначала нам надо создать конфигурационный файл для программы - в моем случае он выглядит так
# configuration file generated by Bochs plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, gameport=1, pci_ide=1, acpi=1, ioapic=1 config_interface: win32config display_library: win32 memory: host=32, guest=10 romimage: file="C:\Program Files\Bochs-2.4.6/BIOS-bochs-latest" vgaromimage: file="C:\Program Files\Bochs-2.4.6/VGABIOS-lgpl-latest" boot: disk floppy_bootsig_check: disabled=0 # no floppya # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, mode=flat, translation=auto, path="C:\Users\Eugene\NBOOT1.COM", cylinders=1, heads=1, spt=1, biosdetect=auto, model="Generic 1234" ata0-slave: type=disk, mode=flat, translation=auto, path="C:\Users\Eugene\ASM\BOOT12.BIN", cylinders=20, heads=16, spt=63, biosdetect=auto, model="Generic 1234" ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=0 ata3: enabled=0 parport1: enabled=1, file="" parport2: enabled=0 com1: enabled=1, mode=null, dev="" com2: enabled=0 com3: enabled=0 com4: enabled=0 usb_uhci: enabled=0 usb_ohci: enabled=0 i440fxsupport: enabled=1 vga_update_interval: 50000 vga: extension=vbe cpu: count=1, ips=4000000, reset_on_triple_fault=1, ignore_bad_msrs=1 cpuid: cpuid_limit_winnt=0, mmx=1, sse=sse2, xapic=1, sep=1, aes=0, xsave=0, movbe=0, 1g_pages=0, pcid=0 fsgsbase=0 cpuid: stepping=3, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " print_timestamps: enabled=0 port_e9_hack: enabled=0 text_snapshot_check: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local # no cmosimage ne2k: enabled=0 pnic: enabled=0 sb16: enabled=0 # no loader log: - logprefix: %t%e%d panic: action=ask error: action=report info: action=report debug: action=ignore pass: action=fatal keyboard_type: mf keyboard_serial_delay: 250 keyboard_paste_delay: 100000 keyboard_mapping: enabled=0, map= user_shortcut: keys=none mouse: enabled=0, type=ps2, toggle=ctrl+mbutton
В данном случае у меня файл программы загрузки - C:\Users\Eugene\NBOOT1.COM
В итоге получим следующую картинку