Архив рубрики: ОС Своими Руками

ОС своими руками — assembler.com.ua

Пишем загруочный сектор для ОС

В  данном посте хочу рассказать как можно запись исполняемый код в загрузочный сектор не задев при этом служебной информации о фат12(которая используется на дискете). Для большей ясности рекомендую прочесть статью на   харбе , прочитать про FAT а также на нашем сайте уже писалось по поводу загрузочного сектора.

И так приступим. Наш загрузчик должен быть компактен, чтоб его размер не превышал 256 байт(хотя можно и чуть больше,  я в данном примере копирую в сектор 432 (1b0h) байта то есть такой размер  кода может быть в загрузочном секторе , но реально 256 байт хватает с головой чтоб загрузить с дискеты файл и запустить его ). Для начала просто напишем код код который выводит на экран «Hello world!» . Для уменьшения кода я написал простенький макрос который используется в 2х местах _rwsecto, этот макрос как видите принимает два параметра, первый отвечает за запись/чтение второй буфер куда или от куда считывать.​

view sourceprint?

01macro _rwsector rw,buf{
02    ;2 чтение,  3 запись
03    mov ah,rw     ;//функция чтения/записи
04    mov al,1      ;//кол секторов
05    mov bx,buf    ;//буфер куда читаем
06    mov ch,0      ;//номер дорожки
07    mov cl,1      ;//номер сектора
08    mov dh,0      ;//сторона головки
09    mov dl,0      ;//сам дисковод А=0 B=1
10    int 13h
11}
12 
13org 100h    ;//генерируем СОМ файл, загружаемый с 0x100
14use16
15jmp start
16qwe db  0ch dup (0)
17fun:
18jmp pisem
19;//-------------
20pisem:
21mov ax,07b3h
22mov  ds,ax
23        mov si,msg   
24         cld ;//направление для строковых команд
25         mov  ah, 0x0E  ;//номер функции BIOS
26    pnext:
27             lodsb ;//загружаем очередной символ в al
28             cmp al,'$' ;// $ символ означает конец строки
29             jz   next
30             int  0x10 ;//вызываем функцию BIOS
31             jmp  pnext
32      next:
33     
34jmp $  ;//  организовываем вечный цикл
35;//==================
36msg db "Hello World!"'$' ; переменная которую выведем на экран
37;//==================
38start:  ;// начало кода который записывает данные в загрузочный сектор
39mov ax,cs ;
40mov es,ax ;//также определяем es так как чтение кластера дискеты будет проходить по адресу es:ds 
41     _rwsector 2,buf ;//макрос который считывает в буфер загрузочный сектор дискеты
42 
43;//пишем сначала джамп а потом  идем на +03аh и там наш код пишем
44;//просто после первых 3 байт идет описание дискеты оно занимает 0а3h , дальше все наше))
45;/если эту информацию повредить то windows или dos не смогут определить какая там файловая
46;//система и предложат ее отформатировать
47mov si,buf
48mov ah,0ebh
49mov [si],ah
50mov ah,03ch
51mov [si+1],ah
52mov ah,90h
53mov [si+2],ah
54;//далее пишем сам код
55mov cx,1b0h ;
56mov di,buf   ;//куда писать будем
57add di,03eh ;//отступаем чтоб не повредить инфу о дискете
58mov si,fun ;//указываем начало кода который нужно вписать
59 
60rep movsb ;//и пишем
61_rwsector 3,buf ;// затем преобразованный сектор пишем обратно на дискету
62 
63;================
64 
65mov ah,0x4C   ;//эта функция завершает программу    
66mov al,0      ;//код возврата 0    
67int 0x21      ;//вызываем ядро операционной системы
68buf db  512 dup (0)  ;// буфер для хранения информации считанной с сектора

Данный код должен быть выполнен на os Windows или в DOSe с тем учетом что в ПК иметься дискета (3,5″ и объемом 1,4 Мб) под буквой А. Можно (даже рекомендуется) все делать на виртуальной машине. Затем перезагрузить машину(ПК) и загрузиться с дискетки. Если все сделали верно то должно вывести «Hello world!!» как на рисунке ниже:

ОС на ассемблере. Загрузочный сектор

 Теперь давайте разберемся как загрузиться с дискеты а затем загрузить нужный нам файл в память и передать управление этому участку памяти куда мы загрузили наш файл. 
Прежде всего давайте рассмотрим как вообще распределяется память в реальном режиме у ПК:

  • от 00000h до A0000h основная память  640Кбайта ( векторы прерываний, ядро ос,программы и прочее ) 
  • от A0000h до C0000h графика EGA
  • от C0000h до D0000h видео память.
  • от D0000h до F0000h системная область
  • от F0000h до FFFFFh системное ПЗУ

 Исходя из того что в самом начале памяти размещены векторы прерываний то мы будим грузиться в память по адресу 0800h. Теперь рассмотрим пример программы которая будет грузить в память с дискеты файл io.bin а затем выполнит его. Давайте сначала разберем код файла io.bin :

view sourceprint?

01mov ax,cs
02mov ds,ax
03pisem:
04mov si,msg
05print:
06        mov al,[si
07        cmp al,0
08        je next
09         
10        mov ah,0x0e 
11        int 0x10
12        mov al,[si]
13         
14        jmp pnext
15       next:
16endfun:
17jmp endfun
18pnext:
19inc si ; i
20jmp print
21msg db "files is load!", 0

Пример кода программы которая будет писать в загрузчик код, который ищет файл и загружает его в оперативную память:

view sourceprint?

001;описываем макросы
002macro _rwsector rw,kols,buf,nomd,noms,nomg,disk{
003    ;2 чтение,  3 запись
004    mov ah,rw      ;функция чтения/записи
005    mov al,kols     ;кол секторов
006    mov bx,buf      ;буфер куда читаем ES:BX
007    mov ch,nomd     ;номер дорожки
008    mov cl,noms     ;номер сектора
009    mov dh,nomg     ;сторона головки
010    mov dl,disk     ;сам дисковод А=0 B=1
011    int 13h
012}
013 
014;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
015macro _searchfile buf,nfile,nomer{
016    ;макрос ищет файл если нашел то возвращает его относительный адрес
017    ;
018    local yes
019    local no
020    local exit
021    local search
022    _rwsector 2,1,buf,0,2,1,nomer ; чтение каталога(списка) файлов
023     
024    mov cx,512
025    mov bx,0
026     
027    xor bx,bx
028    mov bx,buf
029     
030    search:
031    mov si,nfile
032    mov di,bx
033    cld
034    mov cx,11
035    repe CMPSB ;сравниваем пока строки равны, идет сравнение 6ти элементов
036    je yes
037         
038 
039    add bx,32
040         
041    cmp bx,buf+512
042    jne search
043      
044    mov ax,0
045     
046    jmp exit
047     
048    yes:
049 
050         
051        mov ah,[bx+27]
052        mov al,[bx+26]
053         
054    exit:
055}
056 
057macro _nextsector sector,buf{;макрос смотрит таблицу относительных
058    ;секторов и возвращает значение по этому адресу(чтоб узнать,
059    ;конец файла или нет)
060    ;значение возвращаем в ах
061    ;метод читает относительный адрес в карте
062    ;ax - номер относительного сектора на карте
063    ;будем учитывать что все находится в буфере buf(карта)
064    local nechet
065    local next
066        push sector
067         
068         
069        ;загружаем карту сперва
070        _rwsector 2,9,buf,0,2,0,0 ;
071         
072        mov cx,2
073        xor dx,dx
074         
075        div cx
076         
077        pop bx
078        add ax,bx
079        add ax,dx
080        ;ах = относительный сектор
081        ;читаем карту диска и снова вычисляем относительный адрес
082         
083        push dx
084        push ax
085         
086         
087        pop bx; номер кластера
088        pop dx
089         
090         
091        mov ah,[buf+bx-1];идет следом
092            mov al,[buf+bx-2]   ;идет
093         
094        cmp dx,1
095        je nechet
096        ;если нет остачи то AB *C=*CAB если нет то A* BC= BCA*
097         
098        shr ax,4
099         
100        jmp next
101        ;---------
102        nechet:
103        shl ax,4
104        shr ax,4
105         
106         
107        next:
108        ;грузим в память сектор
109 
110     
111     
112     
113    }
114;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
115;==================================
116macro _loadsector buf,nomer,disk{
117    local ost
118    local next
119    push buf ;куда грузим
120    push nomer
121    xor dx,dx
122     
123    pop ax
124    add ax,14
125    mov cx,18
126    div cx
127    ;ah-остаток
128     
129    mov cl,dl
130    push cx
131    mov ah,0
132    mov cl,2
133    div cl
134    pop cx
135    cmp ah,1
136    je ost
137        mov dh,1
138        jmp next
139    ost:
140        mov dh,0
141    next:
142     
143    add al,ah
144     
145    mov ch,al
146     
147     
148       pop buf
149       mov ah,2         ;функция чтения
150       mov al,1     ;кол секторов
151         
152    
153       mov dl,disk      ;сам дисковод А=0 B=1
154       int 13h
155}
156 
157;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
158macro _loadfile2 fname,buf,fbuf{
159    ;fname - имя файла, переменная 11 байт
160    ;buf-буфер для чтения информационных секторов, желательно иметь
161    ;размер 12*512byte=6144 byte
162    ;fbuf - буфер для загрузки файла
163    ;ах возвращает код операции fff все норм, 0-файл на найден
164     
165    local exit
166    local go
167     
168     
169    _searchfile buf,fname,0
170     
171     cmp ax,0
172     je exit   
173     
174    mov bx,fbuf
175         
176    go:
177     
178    push bx
179    push ax
180    _loadsector bx,ax,0
181    pop ax
182    _nextsector ax,buf
183    pop bx
184     
185    cmp ax,0fffh
186    je exit
187     
188    add bx,512
189    jmp go
190    exit:
191     
192}
193 
194org 100h    ;генерируем СОМ файл, загружаемый с 0x10
195use16
196jmp start
197qwe db  0bh dup (0)
198fun:
199jmp pisem
200;-------------
201; код который выполниться при загрузке первого сектора
202pisem:
203;
204    mov ax,07b3h
205    mov  ds,ax
206    mov ax,0800h ;сюда грузим имя файла
207    mov es,ax    ; а затем от туда его вынимаем
208    cld
209    xor di,di
210    mov si,nfile
211    mov cx,11
212    rep movsb
213    mov ds,ax
214    _loadfile2 0,buf,0 
215    jmp dword 0800h:0000 
216    exit:
217jmp $
218 
219 
220nfile db "IO      BIN",'!$';имя нашего файла который грузим в ОП
221;==================
222start:
223mov ax,cs
224mov es,ax
225  
226 
227_rwsector 2,1,buf,0,1,0,0
228 
229 
230;пишем сначала джамп а потом затем идем на +1а3 и там наш код пишем
231 
232mov si,buf
233mov ah,0ebh
234mov [si],ah
235mov ah,03ch
236mov [si+1],ah
237mov ah,90h
238mov [si+2],ah
239 
240mov cx,1b0h ;
241mov di,buf
242add di,03eh
243mov si,fun
244 
245rep movsb
246_rwsector 3,1,buf,0,1,0,0
247;================
248mov ah,0x4C   ;эта функция завершает программу    
249mov al,0      ;код возврата 0    
250int 0x21      ;вызываем ядро операционной системы
251buf db  512 dup (0)  ; буфер для хранения информации считанной с сектора

Теперь давайте разберемся с макросами. Слегка изменили макрос _rwsector , теперь он стал гибче и принимает больше параметров. _rwsector макрос который ищет файл, он принимает буфер для того чтоб грузить туда таблицу файлов, имя файла, и номер диска. Макрос читает таблицу файлов, и если файл найден то возвращает его относительный адрес, то есть относительный адрес первого сектора файла. Затем идет макрос _rwsector который принимает буфер и относительный сектор, он проверяет относительный сектор файла если его номер равен 0fffh то это последний сектор в файле если нет то смотрим второй и так пока не достигнем последний сектор. Макрос _rwsector загружает сектор по относительному адресу, принимает относительный адрес сектора а также буфер куда грузить и номер диска. И последний макрос _loadfile2 принимает имя файла, затем буфер служебный буфер куда будет грузиться сам файл, этот макрос содержит все выше перечисленные макросы и с помощью них загружает в память файл, также макрос в AX возвращает код операции если 0 то файл не найден.

Пишем загруочный сектор для ОС

В  данном посте хочу рассказать как можно запись исполняемый код в загрузочный сектор не задев при этом служебной информации о фат12(которая используется на дискете). Для большей ясности рекомендую прочесть статью на   харбе , прочитать про FAT а также на нашем сайте уже писалось по поводу загрузочного сектора.

И так приступим. Наш загрузчик должен быть компактен, чтоб его размер не превышал 256 байт(хотя можно и чуть больше,  я в данном примере копирую в сектор 432 (1b0h) байта то есть такой размер  кода может быть в загрузочном секторе , но реально 256 байт хватает с головой чтоб загрузить с дискеты файл и запустить его ). Для начала просто напишем код код который выводит на экран «Hello world!» . Для уменьшения кода я написал простенький макрос который используется в 2х местах _rwsecto, этот макрос как видите принимает два параметра, первый отвечает за запись/чтение второй буфер куда или от куда​ считывать.

view sourceprint?

01macro _rwsector rw,buf{
02    ;2 чтение,  3 запись
03    mov ah,rw     ;//функция чтения/записи
04    mov al,1      ;//кол секторов
05    mov bx,buf    ;//буфер куда читаем
06    mov ch,0      ;//номер дорожки
07    mov cl,1      ;//номер сектора
08    mov dh,0      ;//сторона головки
09    mov dl,0      ;//сам дисковод А=0 B=1
10    int 13h
11}
12 
13org 100h    ;//генерируем СОМ файл, загружаемый с 0x100
14use16
15jmp start
16qwe db  0ch dup (0)
17fun:
18jmp pisem
19;//-------------
20pisem:
21mov ax,07b3h
22mov  ds,ax
23        mov si,msg   
24         cld ;//направление для строковых команд
25         mov  ah, 0x0E  ;//номер функции BIOS
26    pnext:
27             lodsb ;//загружаем очередной символ в al
28             cmp al,'$' ;// $ символ означает конец строки
29             jz   next
30             int  0x10 ;//вызываем функцию BIOS
31             jmp  pnext
32      next:
33     
34jmp $  ;//  организовываем вечный цикл
35;//==================
36msg db "Hello World!"'$' ; переменная которую выведем на экран
37;//==================
38start:  ;// начало кода который записывает данные в загрузочный сектор
39mov ax,cs ;
40mov es,ax ;//также определяем es так как чтение кластера дискеты будет проходить по адресу es:ds 
41     _rwsector 2,buf ;//макрос который считывает в буфер загрузочный сектор дискеты
42 
43;//пишем сначала джамп а потом  идем на +03аh и там наш код пишем
44;//просто после первых 3 байт идет описание дискеты оно занимает 0а3h , дальше все наше))
45;/если эту информацию повредить то windows или dos не смогут определить какая там файловая
46;//система и предложат ее отформатировать
47mov si,buf
48mov ah,0ebh
49mov [si],ah
50mov ah,03ch
51mov [si+1],ah
52mov ah,90h
53mov [si+2],ah
54;//далее пишем сам код
55mov cx,1b0h ;
56mov di,buf   ;//куда писать будем
57add di,03eh ;//отступаем чтоб не повредить инфу о дискете
58mov si,fun ;//указываем начало кода который нужно вписать
59 
60rep movsb ;//и пишем
61_rwsector 3,buf ;// затем преобразованный сектор пишем обратно на дискету
62 
63;================
64 
65mov ah,0x4C   ;//эта функция завершает программу    
66mov al,0      ;//код возврата 0    
67int 0x21      ;//вызываем ядро операционной системы
68buf db  512 dup (0)  ;// буфер для хранения информации считанной с сектора

Данный код должен быть выполнен на os Windows или в DOSe с тем учетом что в ПК иметься дискета (3,5″ и объемом 1,4 Мб) под буквой А. Можно (даже рекомендуется) все делать на виртуальной машине. Затем перезагрузить машину(ПК) и загрузиться с дискетки. Если все сделали верно то должно вывести «Hello world!!» как на рисунке ниже:

ОС на ассемблере. Загрузочный сектор

передать управление этому участку памяти куда мы загрузили наш файл. 
Прежде всего давайте рассмотрим как вообще распределяется память в реальном режиме у ПК:

  • от 00000h до A0000h основная память  640Кбайта ( векторы прерываний, ядро ос,программы и прочее ) 
  • от A0000h до C0000h графика EGA
  • от C0000h до D0000h видео память.
  • от D0000h до F0000h системная область
  • от F0000h до FFFFFh системное ПЗУ

 Исходя из того что в самом начале памяти размещены векторы прерываний то мы будим грузиться в память по адресу 0800h. Теперь рассмотрим пример программы которая будет грузить в память с дискеты файл io.bin а затем выполнит его. Давайте сначала разберем код файла io.bin :

view sourceprint?

01mov ax,cs
02mov ds,ax
03pisem:
04mov si,msg
05print:
06        mov al,[si
07        cmp al,0
08        je next
09         
10        mov ah,0x0e 
11        int 0x10
12        mov al,[si]
13         
14        jmp pnext
15       next:
16endfun:
17jmp endfun
18pnext:
19inc si ; i
20jmp print
21msg db "files is load!", 0

Пример кода программы которая будет писать в загрузчик код, который ищет файл и загружает его в оперативную память:

view sourceprint?

001;описываем макросы
002macro _rwsector rw,kols,buf,nomd,noms,nomg,disk{
003    ;2 чтение,  3 запись
004    mov ah,rw      ;функция чтения/записи
005    mov al,kols     ;кол секторов
006    mov bx,buf      ;буфер куда читаем ES:BX
007    mov ch,nomd     ;номер дорожки
008    mov cl,noms     ;номер сектора
009    mov dh,nomg     ;сторона головки
010    mov dl,disk     ;сам дисковод А=0 B=1
011    int 13h
012}
013 
014;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
015macro _searchfile buf,nfile,nomer{
016    ;макрос ищет файл если нашел то возвращает его относительный адрес
017    ;
018    local yes
019    local no
020    local exit
021    local search
022    _rwsector 2,1,buf,0,2,1,nomer ; чтение каталога(списка) файлов
023     
024    mov cx,512
025    mov bx,0
026     
027    xor bx,bx
028    mov bx,buf
029     
030    search:
031    mov si,nfile
032    mov di,bx
033    cld
034    mov cx,11
035    repe CMPSB ;сравниваем пока строки равны, идет сравнение 6ти элементов
036    je yes
037         
038 
039    add bx,32
040         
041    cmp bx,buf+512
042    jne search
043      
044    mov ax,0
045     
046    jmp exit
047     
048    yes:
049 
050         
051        mov ah,[bx+27]
052        mov al,[bx+26]
053         
054    exit:
055}
056 
057macro _nextsector sector,buf{;макрос смотрит таблицу относительных
058    ;секторов и возвращает значение по этому адресу(чтоб узнать,
059    ;конец файла или нет)
060    ;значение возвращаем в ах
061    ;метод читает относительный адрес в карте
062    ;ax - номер относительного сектора на карте
063    ;будем учитывать что все находится в буфере buf(карта)
064    local nechet
065    local next
066        push sector
067         
068         
069        ;загружаем карту сперва
070        _rwsector 2,9,buf,0,2,0,0 ;
071         
072        mov cx,2
073        xor dx,dx
074         
075        div cx
076         
077        pop bx
078        add ax,bx
079        add ax,dx
080        ;ах = относительный сектор
081        ;читаем карту диска и снова вычисляем относительный адрес
082         
083        push dx
084        push ax
085         
086         
087        pop bx; номер кластера
088        pop dx
089         
090         
091        mov ah,[buf+bx-1];идет следом
092            mov al,[buf+bx-2]   ;идет
093         
094        cmp dx,1
095        je nechet
096        ;если нет остачи то AB *C=*CAB если нет то A* BC= BCA*
097         
098        shr ax,4
099         
100        jmp next
101        ;---------
102        nechet:
103        shl ax,4
104        shr ax,4
105         
106         
107        next:
108        ;грузим в память сектор
109 
110     
111     
112     
113    }
114;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
115;==================================
116macro _loadsector buf,nomer,disk{
117    local ost
118    local next
119    push buf ;куда грузим
120    push nomer
121    xor dx,dx
122     
123    pop ax
124    add ax,14
125    mov cx,18
126    div cx
127    ;ah-остаток
128     
129    mov cl,dl
130    push cx
131    mov ah,0
132    mov cl,2
133    div cl
134    pop cx
135    cmp ah,1
136    je ost
137        mov dh,1
138        jmp next
139    ost:
140        mov dh,0
141    next:
142     
143    add al,ah
144     
145    mov ch,al
146     
147     
148       pop buf
149       mov ah,2         ;функция чтения
150       mov al,1     ;кол секторов
151         
152    
153       mov dl,disk      ;сам дисковод А=0 B=1
154       int 13h
155}
156 
157;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
158macro _loadfile2 fname,buf,fbuf{
159    ;fname - имя файла, переменная 11 байт
160    ;buf-буфер для чтения информационных секторов, желательно иметь
161    ;размер 12*512byte=6144 byte
162    ;fbuf - буфер для загрузки файла
163    ;ах возвращает код операции fff все норм, 0-файл на найден
164     
165    local exit
166    local go
167     
168     
169    _searchfile buf,fname,0
170     
171     cmp ax,0
172     je exit   
173     
174    mov bx,fbuf
175         
176    go:
177     
178    push bx
179    push ax
180    _loadsector bx,ax,0
181    pop ax
182    _nextsector ax,buf
183    pop bx
184     
185    cmp ax,0fffh
186    je exit
187     
188    add bx,512
189    jmp go
190    exit:
191     
192}
193 
194org 100h    ;генерируем СОМ файл, загружаемый с 0x10
195use16
196jmp start
197qwe db  0bh dup (0)
198fun:
199jmp pisem
200;-------------
201; код который выполниться при загрузке первого сектора
202pisem:
203;
204    mov ax,07b3h
205    mov  ds,ax
206    mov ax,0800h ;сюда грузим имя файла
207    mov es,ax    ; а затем от туда его вынимаем
208    cld
209    xor di,di
210    mov si,nfile
211    mov cx,11
212    rep movsb
213    mov ds,ax
214    _loadfile2 0,buf,0 
215    jmp dword 0800h:0000 
216    exit:
217jmp $
218 
219 
220nfile db "IO      BIN",'!$';имя нашего файла который грузим в ОП
221;==================
222start:
223mov ax,cs
224mov es,ax
225  
226 
227_rwsector 2,1,buf,0,1,0,0
228 
229 
230;пишем сначала джамп а потом затем идем на +1а3 и там наш код пишем
231 
232mov si,buf
233mov ah,0ebh
234mov [si],ah
235mov ah,03ch
236mov [si+1],ah
237mov ah,90h
238mov [si+2],ah
239 
240mov cx,1b0h ;
241mov di,buf
242add di,03eh
243mov si,fun
244 
245rep movsb
246_rwsector 3,1,buf,0,1,0,0
247;================
248mov ah,0x4C   ;эта функция завершает программу    
249mov al,0      ;код возврата 0    
250int 0x21      ;вызываем ядро операционной системы
251buf db  512 dup (0)  ; буфер для хранения информации считанной с сектора

Теперь давайте разберемся с макросами. Слегка изменили макрос _rwsector , теперь он стал гибче и принимает больше параметров. _rwsector макрос который ищет файл, он принимает буфер для того чтоб грузить туда таблицу файлов, имя файла, и номер диска. Макрос читает таблицу файлов, и если файл найден то возвращает его относительный адрес, то есть относительный адрес первого сектора файла. Затем идет макрос _rwsector который принимает буфер и относительный сектор, он проверяет относительный сектор файла если его номер равен 0fffh то это последний сектор в файле если нет то смотрим второй и так пока не достигнем последний сектор. Макрос _rwsector загружает сектор по относительному адресу, принимает относительный адрес сектора а также буфер куда грузить и номер диска. И последний макрос _loadfile2 принимает имя файла, затем буфер служебный буфер куда будет грузиться сам файл, этот макрос содержит все выше перечисленные макросы и с помощью них загружает в память файл, также макрос в AX возвращает код операции если 0 то файл не найден.

Введение

Добро пожаловать на этот бог который я хочу посвятить созданию ос своими руками.
Я желаю помочь всем кто хочет это сделать самостоятельно. Для этого я буду использовать язык ассемблера, а точнее ассемблер FASM. Почему именно fasm?
по началу выбор был на nasm и fasm (так как он поддерживаться и развиваются по сегодняшний день).  Но выбор упал на последний так как он написан на ассемблере и его макросинтаксис будет по побогаче, хотя принципиальной важности это не имеет, что не сказать про первое качество. Если хотим писать все на ассемблере то и сам ассемблер(компилятор) должен быть написан на нем.!))

 Давайте определимся какая должна быть наша ОС и вообще что такое операционная система. Немного порыв в интернете мы видим что ОС это комплекс программ которые выступают посредником между железом и системными программами   состоит операционная система из:

  1. Загрузчик
  2. Ядро
  3. Имеет командный процессор(сама ее оболочка, в нашем случае командная строка)
  4. Драйвера
  5. Встроенное ПО

Наша  ОС должна содержать все эти элементы. Так же я ставлю перед этой ОС цель чтоб она была проста и каждый( начинающий программист ) мог ее понять, она у нас будет 16-битная, работать с файловой системой FAT12, а также состоять из 5 перечисленных пунктов . На данный момент это все основные цели. Если есть предложения что то добавить или вы с чем то не согласны оставляйте комментарии.

В дальнейших статьях разберем все части  ОС по порядку.​