| Часть полного текста документа:Настоящий "Hello World" Станислав ИевлевС чего начинается изучение нового языка (или среды) программирования? С написания простенькой программы, выводящей на экран краткое приветствие типа "Hello World!". Например, для C это будет выглядеть приблизительно так:
 main() {
 printf("Hello World!\n");
 }
 Показательно, но совершенно неинтересно. Программа, конечно, работает, приветствие свое пишет; но ведь для этого требуется целая операционная система! А что если хочется написать программку, для которой ничего не надо? Вставляем дискетку в компьютер, загружаемся с нее и ..."Hello World"! Можно даже прокричать это приветствие из защищенного режима... Сказано - сделано. С чего бы начать?.. Набраться знаний, конечно. Для этого очень хорошо полазить в исходниках Linux и Thix. Первая система всем хорошо знакома, вторая менее известна, но не менее полезна.
 Подучились? Теперь займемся. Понятно, что первым делом надо написать загрузочный сектор для нашей мини-операционки (а ведь это будет именно мини-операционка!). Поскольку процессор грузится в 16-разрядном режиме, то для создания загрузочного сектора используется ассемблер и линковщик из пакета bin86. Можно, конечно, поискать еще что-нибудь, но оба наших примера используют именно его; и мы тоже пойдем по стопам учителей. Синтаксис этого ассемблера немного странноватый, совмещающий черты, характерные и для Intel и для AT&T, но после пары недель мучений можно привыкнуть.
 Загрузочный сектор (boot.S)
 Сознательно не буду приводить полных листингов программ. Так станут понятней основные идеи, да и вам будет намного приятней, если все напишете своими руками. Для начала определимся с основными константами.
 START_HEAD = 0 - Головка привода, которою будем использовать.
 START_TRACK = 0 - Дорожка, откуда начнем чтение.
 START_SECTOR = 2 - Сектор, начиная с которого будем считывать наше ядрышко.
 SYSSIZE = 10 - Размер ядра в секторах (каждый сектор содержит 512 байт)
 FLOPPY_ID = 0 - Идентификатор привода. 0 - для первого, 1 - для второго
 HEADS = 2 - Количество головок привода.
 SECTORS = 18 - Количество дорожек на дискете. Для формата 1.44 МБ это количество равно 18.
 В процессе загрузки будет происходить следующее. Загрузчик BIOS считает первый сектор дискеты, положит его по адресу 0000:0x7c00 и передаст туда управление. Мы его получим и - для начала - переместим себя пониже по адресу 0000:0x600, перейдем туда и спокойно продолжим работу. Собственно вся наша работа будет состоять из загрузки ядра (сектора 2 - 12 первой дорожки дискеты) по адресу 0x100:0000, переходу в защищенный режим и скачку на первые строки ядра. В связи с этим еще несколько констант:
 BOOTSEG = 0x7c00 - Сюда поместит загрузочный сектор BIOS.
 INITSEG = 0x600 - Сюда его переместим мы.
 SYSSEG = 0x100 - А здесь приятно расположится наше ядро.
 DATA_ARB = 0x92 - Определитель сегмента данных для дескриптора
 CODE_ARB = 0x9A - Определитель сегмента кода для дескриптора.
 Первым делом произведем перемещение самих себя в более приемлемое место.
 cli
 xor ax, ax
 mov ss, ax
 mov sp, #BOOTSEG
 mov si, sp
 mov ds, ax
 mov es, ax
 sti
 cld
 mov di, #INITSEG
 mov cx, #0x100
 repnz
 movsw
 jmpi go, #0
 Теперь необходимо настроить как следует сегменты для данных (es, ds) и для стека.  ............
 |