以前上学时从网上找到的一篇好文章,翻译过,但找不到译文了,整理资料时找到了,虽然用处不大,但也是一番回忆,贴到这儿先。

How to write an operating system

Writing an operating system is something that can not only be interesting (if you're one of those people that get turned on by Int 13....) but it is also a great learning experience. Through creating your own operating system you will learn exactly what goes on behind the scenes, elevating you above the average programmer that just writes in Visual Basic.

In this tutorial you will be tought by examples, and by the end you should have created your own operating system.

Tools:

EasyOs New version of EasyOS Most reliable version of Easyos.zip easyos.zip 300kb
EasyOS is a very simple operating system, it contains all the tools needed to build an operating system. (Not written by me, although I did add bits to it and mess it up a bit)

A quick explanation of assembly: (see here for a good tutorial)

si and ah Think of si as something to put text into, and ah as something to put numbers into.
mov This (mov)es data. mov ah,0 would move 0 into ah. (The data on the right is moved into the left)
Int Think of these as functions. Different int's do different things when ah is different. Ahem. Eg. when ah = 0 and you call int 10 it prints si to the screen.
Stuff To put words and stuff in your program you can't just do mov si,'some words' (well, you can but you wont like the resutls) so instead you have to declare the words first. You do this by putting the name of what you want the words to be called by, then the data type (nearly always db) then the words themselves. Eg:
name db 'some words'
Jump To give sections of code a label, just type the label and add a : at the end, eg code: . You can then use jmp to jump to it, eg jmp code If To do an if in assembly you use cmp, eg cmp al,0 (if al=0). On the next line you then put je code, and if al=0 then the program jumps to the section of code called code. If you use jne code, then if al is not 0 the program will jump to code.
The stack The stack is where stuff is stored. push pushes stuff into it, pop pulls stuff out. The following example would put cx into dx:
push cx pop dx

Now you know everything there is to know about assembly, you can now understand most of the program that boot's EasyOs. Drives (hard drives and floppy's) are split into lots of bits, all 512 bytes long (enough to fit 512 letters in). These are calle sectors. The first sector is what the computer looks for when it boots. It is called the bootsector.
Open the folder src and then open boot.asm. Or if you are lazy, just look at the code below (its the same).

; This is a comment
[ORG 0x7C00] ;This just tells the program where it is in the memory. Not important
[BITS 16] ;Not important too.jmp start      ; Jump over BIOS parameter blockstart: ;The label for the start of the actual programpush cs ;Put cs onto the stack
pop ds ;Take it out and put it into dsmov si,Print_loading     ;Print loading message
call printstring         ;Call is like jump, but it goes back. Like a function;The complicated bit: Loads the next program
mov ah,02h               ;When ah=, int13 reads a disk sector
mov al,4                 ;Al is how many sectors to read
mov ch,0                 ;The track to read from
mov cl,2                 ;Sector Id
mov dh,0                 ;Head
mov dl,0                 ;Drive (0 is floppy)
mov bx,0x1000            ;Es and Bx put together are where to load the program too (see jmp 0x1000:0x00)
mov es,bx
mov bx,0x00
int 13h                 ;Int 13 is all functions for disksmov si,putdot           ;Print a ".".
call printstringjmp 0x1000:0x00         ;Run Bootinit from stack.printstring:            ;Print string routine.
mov ah,0eh              ;Mov ah into 0, so int 10 prints
stringloop:             ;The following code loads each seperate charcter so it can be printed
lodsb
cmp al,00               ;If al =0, then the string has all been loaded
je endstring
int 10h                 ;When int 10 is called, and ah=, it prints
jmp stringloop
endstring:
ret                     ;Ret returnsputdot        db '.',0
Print_loading db 13,10,'Loading Easy OS v0.01a...',0
times 425 db 0 ;wastes 425 bytes on purpose, so the sector is full (The program must be 512 bytes long)

You may have noticed that numbers, like int 10h, end in h. They don't have to, it just looks funky (there is a real reason, but it's boring).
Anyway, now copy the program called copyboot in the folder called utils to the folder with test.asm in. Open the dos prompt and type: (Make sure a blank floppy is inserted)
copyboot test.com 0
copyboot is the name of the program, test.com the name of the file to copy, and 0 is the sector.
In the program above all it does is print a string then load whats at sector 1. The program that easyos loads under the src folder called bootinit. If you assemble it with nasm, then copy it to sector 1 and restart, the bootsector will load it.
There isn't much more to be learnt from EasyOs, so run either setup.exe or make.bat to build the whole thing. The difference is setup.exe lets you setup a root password for EasyOs. If you just run make.bat the passwords is the default password: monty (named after my psychotic dog).
Now restart and be amazed. Wow. Pretty crappy, but it isn't that bad.

Fat 12

No, its not a fat people supprt group but a file system. If you try and access the floppy disk Windows will say it need s to be formatted. Formatted? You ask. Formatting is basically organising the sectors so you can give them names. Underneath Windows and Fat, you are still just accessing sectors. I won't go into Fat here, check out http://www.maverick.subnet.dk/ for some info. Anyway, the bootsector needs to have some information in it that when Windows reads it it tells it it is fat. The following BootSector was disgustingly ripped by me of NYAOS (I have no idea what i stands for). With your A* qualification in assembly language you can no doubt understand it.

; NYAOS Boot Sector (C) Copyright Sean Tash 1998
; assemble with:
; nasm -f bin -o bootsect.bin bootsect.asmbits 16org 0x7C00start:      jmp short beginnop
bsOEM       db "NYAOS1.0"               ; OEM String
bsSectSize  dw 512                      ; Bytes per sector
bsClustSize db 1                        ; Sectors per cluster
bsRessect   dw 1                        ; # of reserved sectors
bsFatCnt    db 2                        ; # of fat copies
bsRootSize  dw 224                      ; size of root directory
bsTotalSect dw 2880                     ; total # of sectors if < 32 meg
bsMedia     db 0xF0                     ; Media Descriptor
bsFatSize   dw 9                        ; Size of each FAT
bsTrackSect dw 18                       ; Sectors per track
bsHeadCnt   dw 2                        ; number of read-write heads
bsHidenSect dd 0                        ; number of hidden sectors
bsHugeSect  dd 0                        ; if bsTotalSect is 0 this value is; the number of sectors
bsBootDrv   db 0                        ; holds drive that the bs came from
bsReserv    db 0                        ; not used for anything
bsBootSign  db 29h                      ; boot signature 29h
bsVolID     dd 0                        ; Disk volume ID also used for temp; sector # / # sectors to load
bsVoLabel   db "NO NAME    "            ; Volume Label
bsFSType    db "FAT12   "               ; File System typebegin:      cli                         ; disable interruptsmov [bsBootDrv],dl          ; save drive numbermov ax,0x9000               ; put stack at 0x98000mov ss,axmov sp,0x8000mov cx,[bsTrackSect]        ; update int 1E FDC param tablemov bx,0x0078lds si,[ds:bx]mov byte [si+4], clmov byte [si+9], 0x0Fsti                         ; enable interruptspush dsmov dl,[bsBootDrv]          ; reset controllerxor ax,axint 0x13pop dsjc bootfail2                ; display error messagejmp _l1
bootfail2:  jmp bootfail
_l1:mov ax,0x0000mov es,axmov ds,axmov si,MsgLoad              ; display load messagecall putstr; find the root directoryxor ax,axmov al,[bsFatCnt]mov bx,[bsFatSize]mul bxadd ax,word [bsHidenSect]adc ax,word [bsHidenSect+2]add ax,word [bsRessect]     ; ax holds root directory locationmov word [BootSig],axcall checkrootxor ax,axadd ax,word [start]add ax,word [bsVolID]       ; sector numberadd ax,word [BootSig]sub ax,2                    ; correction for a mis-calcmov cx,word [bsVolID+2]     ; number of sectorsmov bx,0x8000mov es,bxnextsector: push ax                     ; save registerspush cxpush dxpush esxor bx,bx                   ; set zero offsetcall readsect               ; read a sectormov si,MsgDot               ; display a dotcall putstrpop es                      ; restore registerspop dxpop cxpop axmov bx,esadd bx,20h                  ; increment address 512 bytesmov es,bxinc ax                      ; read next sectorloopnz nextsectormov ax,0x8000               ; set segment registers and jumpmov es,axmov ds,axpush axmov ax,0push axretfcheckroot:push ax                     ; save registerspush bxpush cxpush dxpush sipush dimov ax,0x8000               ; put root directory at 0x80000mov es,axmov ax,32                   ; AX = ((32*RootSize)/512) + 2mul word [bsRootSize]div word [bsSectSize]mov cx,ax                   ; cx holds # of sectors in rootmov word [start],axmov ax,word [BootSig]       ; get prev. saved loc. for root dirr1:         xor bx,bxpush cx                     ; save countpush ax                     ; save sector numberpush espush dxcall readsectxor bx,bx
l_1:        mov di,bx                   ; set address to check frommov cx,11                   ; check 11 bytesmov si,FileName             ; address of string to check withrepz cmpsbje founditadd bx,32                   ; check next entrycmp bx,[bsSectSize]         ; end of sector?je l_2jmp l_1
l_2:        pop dx                      ; restore registerspop espop axpop cxinc ax                      ; read next sectorloopnz r1jmp bootfail
foundit:    pop dx                      ; get these off the stackpop espop axpop cxmov di,0x1A                 ; get clustor #add di,bxpush bx                     ; save bx for finding # of sectorsmov ax,[es:di]xor bx,bx                   ; calculate sector #mov bl,[bsClustSize]mul bx                      ; ax holds sector #mov word [bsVolID],axpop bx                      ; get location of directory entrymov di,0x1Cadd di,bxmov ax,[es:di]              ; put number of bytes in axxor dx,dxmov bx,[bsClustSize]        ; # of bytes / 512div bxinc axmov word [bsVolID+2],ax     ; save number of sectors to loadpop di                      ; restore registerspop sipop dxpop cxpop bxpop axret                         ; return to callerputstr:     ; SI = address of string to displaylodsbor al,aljz short putstrdmov ah,0x0Emov bx,0x0007int 0x10jmp putstr
putstrd:    retn                        ; return to callerbootfail:   ; display failure messagemov si,MsgBad               ; display error messagecall putstrxor ax,ax                   ; wait for keypressint 0x16int 0x19                    ; rebootreadsect:   ; ES:BX = Location ; AX = Sectormov si,[bsTrackSect]div si                      ; divide logical sect by track sizeinc dl                      ; sector # begins at 1mov [bsReserv],dl           ; sector to readxor dx,dx                   ; logical track left in axdiv word [bsHeadCnt]        ; leaves head in dl, cyl in axmov dh, [bsBootDrv]         ;xchg dl,dh                  ; head to dh, drive to dlmov cx,ax                   ; cyl to cxxchg cl,ch                  ; low 8 bits of cyl to ch, hi 2 bitsshl cl,6                    ; shifted to bits 6 and 7or cl, byte [bsReserv]      ; or with sector numbermov al,1                    ; number of sectorsmov ah,2                    ; use read function of int 0x13int 0x13                    ; read sectorjc bootfail                 ; display error messageret                         ; return to callerpadding     times 45 db 0
FileName    db "OSLOADERCOM"
MsgBad      db "Disk Error...",13,10,0
MsgDot      db ".",0
MsgLoad     db "doors loading",0
BootSig     db 0x55, 0xAA

Anyways, copy the above program, save it, build it with nasm, copy it with copyboot.
As you can guess above, it loads a program called 'OSLOADER.COM' off of the floppy. So, if you want a particularily funky os, build the following with nasm:

;Funky squares
;
;Assembles with NASM
;Made by Frej  somewhere between april and may 2000
;Bits reprogrammed to run within DeviatorOS
;
;This demo is just to show you how small graphical demos can get ;)
;Reprogrammed for DeviatorOS as demo programorg 0x0000mov ax,csmov ds,axmov es,ax         ; fix segment regsstart:  mov bx,cs         ;put codesegment to bxadd bh,0x20       ;add 2000 to bxmov ds,bx         ;and put it to dsmov ax,0x13       ;set ax to videomode 13int 10h           ;and do that
Main:   push ds           ;put buffer seg to stackpop es            ;and put that into esin ax,0x40        ;generate "random" number (timer)shl ax,4          ;multiply random # with 16mov di,ax         ;box offset (random)mov al,255        ;color of the boxmov bx,50         ;height=50
pl:     add di,270        ;di+270 (320-width(50))mov cx,50         ;# bytes to copy to bufferrep stosb         ;and do itdec bx            ;decrement bxjnz pl            ;jump if bx not zeromov bh,0xFA       ;assume bl = 0 (-> bx = FA00)
Smudge: mov al,[bx+1]     ;right color to almov cl,[bx-1]     ;left color to cladd ax,cx         ;and add it to axmov cl,[bx-320]   ;upper color to cladd ax,cx         ;and add it to axmov cl,[bx+320]   ;lower color to cladd ax,cx         ;and add it to axshr ax,2          ;divide with 4mov [bx],al       ;and but the avarage color to bufferdec bx            ;decrement bxjnz Smudge        ;jump if bx not zeromov ax,0xA000     ;vga segmov es,ax         ;put it to esmov ch,0xFA       ;# bytes to copy to vgaxor di,di         ;zero vga offsetxor si,si         ;zero buffer offsetrep movsb         ;and do thatin al,0x60        ;check for keysdec al            ;was it esc?jnz Main          ;nope, continuemov ax,3          ;text modeint 10h           ;get back into text modexor ah,ah         ;yes, return to OSint 0x18          ;back to good old kernel
;Note:- This was, as you can guess, ripped by from an os. So when it goes back to the 'good ol kernel' it just restarts.

Build it with nasm, but rather than faffing around copyboot, just name is as OSLOADER.COM and copy it to the floppy.
Now restart and enjoy the funkiness. Woah dood.

C

Time to escape assembly language. The boot sector has to be written in assembly, but nothing else does. Unfortunately you can't just go and write a cool shell with Visual C++. First of all, its has to be a .com program, not .exe.
.exe programs are just .com with a bit of extra info. at the start giving some info on what the program is. It's very easy to add .exe capabililty to an os, or you can download a program called exe2com.
The serious problem though is that you can create your own ints to make things easier. EasyOs does this (look in kernel.asm under the src folder) and Dos does this too (Dos makes int 21). By default, compilers build a program with these ints.

For linux lovers

The following code is for Gcc on linux and nasm for dos or linux. Dos/ Windows users can download Djgpp from http://www.delorie.com/djgpp/, which is like gcc. The line
gcc -c -O2 -Wall -g -o hello.o hello.c
Tells gcc to build a plain binary. I don't know who wrote the following, e-mail me if you do.

The smallest pmode + C program I could write is shown below,
in three files. I compiled with GCC, not GPP, and got no
warnings.This code doesn't check for a 32-bit CPU or V86 mode. If you
try to run it inside a DOS box, Windows will kill it.load.asm is assembled to aout format instead of COFF, because
DJGPP COFF doesn't let you mix 16- and 32-bit code.;/****************************************************************************
;       file load.asm
;****************************************************************************/
[SECTION .text]
[BITS 16]
[GLOBAL start]
start:  xor ebx,ebx             ; now in real mode (16-bit)mov bx,csshl ebx,4mov eax,ebx        ; EAX=EBX=CS<<4lea eax,[ebx]mov [gdt2 + 2],ax  ; set descriptor base address=EAXmov [gdt3 + 2],axshr eax,16mov [gdt2 + 4],almov [gdt3 + 4],almov [gdt2 + 7],ahmov [gdt3 + 7],ahlea eax,[ebx + gdt]  ; point gdt_ptr to the gdtmov [gdt_ptr + 2],eax    ; EAX=linear address of gdtpush dword 0        ; zero EFLAGS (interrupts off,popfd         ;  IOPL=0, NT bit=0)lgdt [gdt_ptr]mov eax,cr0or al,1mov cr0,eaxjmp SYS_CODE_SEL:do_pm
[BITS 32]
do_pm:  mov ax,SYS_DATA_SEL     ; now in 32-bit pmodemov ds,eax     ; EAX works, one byte smaller :)mov ss,eaxnopmov es,eaxmov fs,eaxmov gs,eaxxor eax,eax      ; zero top 16 bits of ESPmov ax,spmov esp,eax
[EXTERN _main]call _main        ; call C codejmp $          ; freeze[SECTION .data]
; null descriptor
gdt:    dw 0            ; limit 15:0dw 0            ; base 15:0db 0         ; base 23:16db 0            ; typedb 0          ; limit 19:16, flagsdb 0            ; base 31:24
; linear data segment descriptor
LINEAR_SEL  equ $-gdtdw 0xFFFF               ; limit 0xFFFFF (1 meg? 4 gig?)dw 0            ; base for this one is always 0db 0db 0x92          ; present,ring 0,data,expand-up,writabledb 0xCF                 ; page-granular (4 gig limit), 32-bitdb 0
; code segment descriptor
SYS_CODE_SEL    equ $-gdt
gdt2:   dw 0xFFFFdw 0           ; (base gets set above)db 0db 0x9A          ; present,ring 0,code,non-conforming,readabledb 0xCFdb 0
; data segment descriptor
SYS_DATA_SEL    equ $-gdt
gdt3:   dw 0xFFFFdw 0           ; (base gets set above)db 0db 0x92          ; present,ring 0,data,expand-up,writabledb 0xCFdb 0
gdt_end:gdt_ptr:dw gdt_end - gdt - 1    ; GDT limitdd gdt           ; linear, physical address of GDT;/****************************************************************************
;       file hello.c
;****************************************************************************/
#include  /* movedata() */#define   LINEAR_SEL  0x08
#define SYS_DATA_SEL    0x18int main(void)
{const char Msg[] = "h e l l o ";movedata(SYS_DATA_SEL, (unsigned)Msg,LINEAR_SEL, 0xB8000,sizeof(Msg));return 0;
};/****************************************************************************
;   file build.bat
;*****************************************************************************/
nasm -f aout -o load.o load.asm
gcc -c -O2 -Wall -g -o hello.o hello.c
ld -o pm.com -oformat binary -Ttext=0x100 load.o hello.o /djgpp/lib/libc.a

That's it

E-mail the@womble.co.uk with questions
Or find me and others at alt.os.development

http://os-dev.isa.net.au/boardindex.phtml -Os programming messege board
More Os's and links

Download your FREE Work From Home E-book A FREE E-Book on how to set up your own home-based business. Download your free copy of "Dare To Succeed Online Training System"

How to write an operating system相关推荐

  1. How to Make a Computer Operating System

    How to Make a Computer Operating System 如何制作一个操作系统(翻译版) 原文地址:Github:How to Make a Computer Operating ...

  2. VMware vSphere Client中启动虚拟机提示No boot filename received/Operating System not found解决方法

    VMware vSphere Client中启动虚拟机提示No boot filename received/Operating System not found解决方法 参考文章: (1)VMwar ...

  3. vm虚拟机安装系统后出现operating system not found解决办法(VM装ghost 不能进系统的解决方法)

    vm虚拟机安装系统后出现operating system not found解决办法不知你使用那种软件分的区?   用DIANGEN的话,它本来就清楚列明了激活分区选项的. 如果用PQ分区的话,还必须 ...

  4. Directory lookup for the file xxx.mdf failed with the operating system error 2

    Directory lookup for the file "xxx.mdf" failed with the operating system error 2(系统找不到指定的文 ...

  5. 成功解决解决VM软件安装Linux的Ubuntu过程,打开时 Operating System not found

    成功解决解决VM软件安装Linux的Ubuntu过程,打开时 Operating System not found 目录 解决问题 解决思路 解决方法 解决问题 安装Ubuntu16.04虚拟机,打开 ...

  6. 什么是posix?(Portable Operating System Interface 便携式操作系统接口)

    POSIX(Portable Operating System Interface)是Unix系统的一个设计标准.当年最早的Unix,源代码流传出去了,加上早期的Unix不够完善,于是之后出现了好些独 ...

  7. linux ros是什么?(Robot Operating System)

    Robot Operating System 参考文章:ROS学习入门(抛砖引玉篇)

  8. 【中级软考】什么是实时操作系统?(RTOS:Real Time Operating System)

    实时操作系统(RTO:Real Time Operating System)是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出 ...

  9. 如何定位“Operating system error 32(failed to retrieve text for this error. Reason: 15105)”错误中被占用的文件...

      之前在这篇"Operating system error 32(failed to retrieve text for this error. Reason: 15105)"博 ...

最新文章

  1. windows环境中利用NMake工具编译连接C++源代码
  2. android的log.d不显示结果
  3. 牛客网(剑指offer) 第二十五题 复杂链表的复制
  4. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-PLC支持哪些PLC语言类型
  5. IDEA中Spring Boot项目报错:There was an unexpected error (type=Not Found, status=404)
  6. python3 输入输出_21.Python3 输入和输出
  7. wifi频率和zigbee干扰_浅谈ZigBee和Wi—Fi的共存和干扰
  8. 华为鸿蒙系统备用,就只有华为有备用系统?其实谷歌也准备了一个,不输鸿蒙系统!...
  9. Unity GC垃圾回收
  10. 【稀饭】react native 实战系列教程之数据存储
  11. Java(二十二) -- 生产者消费者模式
  12. 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用
  13. 《零基础学JavaScript(全彩版)》学习笔记
  14. 快速缩小GIF图片文件的两种方式
  15. [反汇编练习] 160个CrackMe之021
  16. ellipsize属性
  17. 计算机图形学:Mesh
  18. SSM源码分析之23种设计模式(策略模式和模板模式)
  19. 百度大脑人体分析服务3月上新盘点
  20. 三维动画制作流程细节

热门文章

  1. [转]java中byte转换int时为何与0xff进行与运算
  2. FW : 一只小青蛙的一生(图片连载)
  3. hdu 3416(最短路+最大流)
  4. bnu- 34985 Elegant String
  5. nyoj42一笔画问题
  6. 《机器学习实战》chapter 11 使用apriori算法进行关联分析
  7. NYOJ 716 River Crossing(动态规划)
  8. 数据算法 --hadoop/spark数据处理技巧 --(二次排序问题和TopN问题)
  9. luogu P5304 [GXOI/GZOI2019]旅行者
  10. KeyDown,KeyPress和KeyUp详解(转)