Использование ЯВУ C при написании учебной ОС в рамках курса
«Операционные системы»
Морев Н.
В рамках практикума по курсу «Операционные системы» студентам
предлагается создать небольшую учебную ОС, основанную на архитектуре
микропроцессора i386.
Создание ОС -- это достаточно сложная работа, которая, чтобы быть успешной,
может опираться не только на творческий и конструктивный подход к делу,
но и на использование удобных инструментов в процессе ее создания.
Написание ОС полностью на ассемблере не оправдано по ряду причин:
- Ассемблер не нагляден, исходные тексты написанные на нем очень плохо
читаются.
- В ассемблере отсутствуют средства для структурного программирования.
- ЯВУ обеспечивают более высокий уровень абстракции.
Для решения различных достаточно сложных проблем часто разбивают задачу на
отдельные подзадачи. В программировании данный приём используется также
очень широко. При написании программы, её исходники разбиваются на
несколько отдельных файлов (модулей) в соответствии с их
функциональностью. При сборке проекта эти файлы компилируются в объектные
модули, которые затем компонуются в исполняемый файл.
Среди достоинств данного
подхода необходимо отметить возможность написания отдельных исходных
модулей на разных языках программирования. Все что для этого нужно -- это
чтобы компиляторы используемых языков могли генерировать объектные файлы
определенного формата, который распознается компоновщиком. Например, если
использовать любые компиляторы фирмы Borland для DOS, то с
этим не будет никаких проблем, т. к. все они совместимы на уровне
объектных модулей с компоновщиком Tubro Link той же фирмы.
Необходимо скомпоновать исполняемый файл учебной ОС из отдельных объектных
модулей, скомпилированных из исходных файлов на C и ассемблере.
Для реализации поставленной задачи необходимо:
- компилятор Turbo Assembler (tasm), т. к. именно его
использование рекомендуется в [2];
- компоновщик объектных модулей Turbo Link (tlink);
- компилятор Borland C (bcc).
Исходя из технических требований видно, что студенту, приступившему к
выполнению данной работы, необходимы следующие знания:
- навыки работы с командной строкой MS DOS;
- знание языков программирования ассемблер для x86 и C.
Так как непосредственно написание учебной ОС не входит в рассмотрение
этого текста, примером реализации учебной задачи будет небольшая
программка, которая выполняет следующие действия:
- Переходит в защищенный режим процессора i386.
- Выводит на экран строку. Причем процедура вывода
строки находится в исходном файле на C.
- Переходит обратно в реальный режим процессора.
- Завершается.
Также из рассмотрения будут выключены некоторые куски кода связанные с
инициализацией защищенного режима и т. п.
Исходный текст программы состоит из следующих файлов (полные исходные тексты, в архиве):
- startup.asm
- инициализация защищенного режима, вызов функции
main(), завершение программы;
- startup.mac
- различные макросы, не имеющие непосредственного
отношения к поставленной задаче;
- main.c
- основной модуль программы, содержит процедуру вывода строки
на экран puts() и два ее вызова в функции main();
- Makefile
- файл описания последовательности сборки программы,
используется утилитой make.
; FOO_OS -- учебная операционная система
; (c) 2003, Kolia Morev <kolyuchiy@gmail.com>
;
; Начальная загрузка ОС.
.386p
include startup.mac
; Из main.c
extrn C main:proc
DGROUP group _DATA,_BSS
assume cs:_TEXT,ds:DGROUP
_DATA segment word public use16 'DATA'
gdt label word
;
gdt_null descr <0,0,0,0,0,0>
sel_code = 10q
gdt_code descr <0FFFFh,,,10011010b>
sel_data = 20q
gdt_data descr <0FFFFh,,,10010010b>
sel_stack = 30q
gdt_stack descr <size _stack-1,,,10010010b>
sel_screen = 40q
gdt_screen descr <3999,8000h,0bh,0f2h>
;
gdt_size = $ - gdt
idt label word
intr 256 dup (<>)
idt_size = 256 * size intr
; Поля данных программы
tmpdescr descr <>
message_exit db '* exit: PeaJIbHbIu Pe>|<uM.$'
_DATA ends
_BSS segment word public use16 'BSS'
_BSS ends
_TEXT segment byte public use16 'CODE'
assume cs:_TEXT,ds:DGROUP
startup:
mov ax,dgroup
mov ds,ax
perehod_v_prot_mode
; Переход в защищённый режим
mov eax,cr0
or eax,1b
mov cr0,eax
; Теперь процессор работает в защищённом режиме
; Загрузка в CS селектора сегмента команд,
; перезагрузка буфера команд
db 0eah
dw offset continue
dw sel_code
continue:
; Инициализируем сегментные регистры
mov ax,sel_data
mov ds,ax
mov ax,sel_stack
mov ss,ax
mov ax,sel_screen
mov es,ax
mov ax,0
mov gs,ax
mov fs,ax
; Запускаем ядро ОС
call main
perehod_v_real_mode
; Проверим выполнение функций DOS и завершим программу
mov ah,09h
mov dx,offset message_exit
int 21h
mov ax,4c00h
int 21h
_TEXT ends
_STACK segment stack 'stack'
org 200h
_STACK ends
end startup
/* FOO_OS -- учебная операционная система
* (c) 2003, Kolia Morev <kolyuchiy@gmail.com>
*
* Главный модуль.
*/
#define VERSION "npuBeT u3 protected mode\n" \
"build: "__TIME__", "__DATE__"\n"
#define GOODBYE "DocBuDaHu9I!!!\n"
void puts(char *string);
void main(void)
{
puts(VERSION);
puts(GOODBYE);
}
int pos = 640;
/* Выводит символ на экран */
#define putc(c,pos,attr) \
_AL = c; \
_AH = attr; \
_DI = pos; \
__asm stosw;
/* Выводит на экран строку в текущую позицию
* в видеобуфере.
*/
void puts(char *string)
{
int i = 0;
while(string[i]!=0) {
_AL = string[i];
if(_AL==0x0a) {
pos += 80*2 - pos%(80*2);
} else {
putc(_AL,pos,7);
pos += 2;
}
i++;
}
}
# FOO_OS -- учебная операционная система
# (c) 2003, Kolia Morev <kolyuchiy@gmail.com>
#
# Makefile.
CC = bcc
AS = tasm
LD = tlink
CFLAGS = -3 -c -v
ASFLAGS = /m2
LDFLAGS = /3
LISTING = ,
ASDEBUG = /zi
LDDEBUG = /v /m
OBJS = startup.obj main.obj
all: foo_os.exe
foo_os.exe: $(OBJS) makefile
$(LD) $(LDFLAGS) $(LDDEBUG) $(OBJS), foo_os.exe,,
.asm.obj:
$(AS) $(ASFLAGS) $(ASDEBUG) $<, $(LISTING)
.c.obj:
$(CC) $(CFLAGS) $<
# Зависимости
startup.obj: makefile startup.asm startup.mac \
main.obj
main.obj: makefile main.c
В startup.asm сегменты организованы и названы именно так, как
их создает по умолчанию и bcc1. Это нужно для того, чтобы код и данные из разных
объектных модулей находились в одном сегменте исполняемого модуля.
Чтобы переменные или функции из ассемблерного объектного модуля были видны
в другом объектном модуле, их надо объявить, как public, а чтобы
получить к ним доступ из другого файла, в описании надо использовать
ключевое слово extrn для ассемблера или extern для C.
Например, сделаем указатель на IDT, определенный в startup.asm,
видимым для ints.asm и sys.c:
startup.asm:
idt label word
intr 256 dup (<>)
public C idt
ints.asm:
extrn C idt
sys.c:
extern gate_desc_t idt[256];
Опция C в public и extrn указывает на то, что указатель
объявлен по правилам принятым для языка C, т. е. в объектном модуле его
имя представлено не как idt, а как _idt.
bcc по умолчанию описывает все переменные как public.
Использование ЯВУ при написании учебной ОС позволит вам не заострять
внимание на несущественных особенностях оптимизации кода,
использования регистров, адресации и системы команд процессора каждый раз,
когда вы хотите просто организовать цикл или разделить два числа, что
позволит существенно сократить время кодирования и уделить больше внимания
проектированию.
- 1
- Орлов С. Б. Программа-справочник по системе
программирования Турбо Ассемблер 2.0: Руководство пользователя, справочное
руководство. М.: 1990.
- 2
- Барков В. А. Лабораторный практикум по дисциплине
<<Операционные системы>>. (01.04.2003).
Использование ЯВУ C при написании учебной ОС в рамках курса
«Операционные системы»
This document was generated using the
LaTeX2HTML translator Version 2K.1beta (1.48)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -nonavigation -split 0 -local_icons -address kolyuchiy@gmail.com -no_auto_link report.tex
The translation was initiated by Kolia Morev on 2003-05-15
Сноски
- ...bcc1
- В чём можно убедиться с
помощью команды bcc -S main.c, которая переводит исходник на C в
исходник на ассемблере.
kolyuchiy@gmail.com
Обновлено Tue Apr 15 21:27:20 2014 +0400