Часть полного текста документа:The Real Hello World В этой статье мы напишем... собственную мини-ОС. Да да, создадим свою собственную операционную систему. Правда система будет грузиться с дискеты и выводить знакомое Hello World, но согласитесь, это произведет впечатление и на вас, и на ваших друзей. Ведь именно Вы создадите СВОЮ мини-ОС. 1. Идея (hello.c) Изучение нового языка программирования начинается, как правило, с написания простенькой программы, выводящей на экран краткое приветствие типа "Hello World!". Например, для C это будет выглядить приблизительно так. main() { printf("Hello World!\n"); } Показательно, но совершенно не интересно. Программа, конечно работает, режим защищенный, но ведь для ее функционирования требуется ЦЕЛАЯ операционная система. А что если написать такой "Hello World", для которого ничего не надо. Вставляем дискетку в компьютер, загружаемся с нее и ..."Hello World". Можно даже прокричать это приветствие из защищенного режима. Сказано - сделано. С чего бы начать?.. Набраться знаний, конечно. Для этого очень хорошо полазить в исходниках Linux и Thix. Первая система всем хорошо знакома, вторая менее известна, но не менее полезна. Подучились? ... Понятно, что сперва надо написать загрузочный сектор для нашей мини-опрерационки (а ведь это именно мини-операционка). Поскольку процессор грузится в 16-разрядном режиме, то для созджания загрузочного сектора используется ассемблер и линковщик из пакета bin86. Можно, конечно, поискать еще что-нибудь, но оба наших примера используют именно его и мы тоже пойдет по стопам учителей. Синтаксис этого ассемблера немколько странноватый, совмещающий черты, характерные и для Intel и для AT&T (за подробностями направляйтесь в Linux-Assembly-HOWTO), но после пары недель мучений можно привыкнуть. 2. Загрузочный сектор (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 Mb это количество равно 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 ; прыжок в новое местоположение загрузочного сектора на метку go Теперь необходимо настроить как следует сегменты для данных (es, ds) и для стека. ............ |