怎樣用C語言開發作業系統

來源:互聯網
上載者:User
怎樣用C語言開發作業系統[1]
--------------------------------------------------------------------------------

作者:tianxiangyuan   來源:原創    更新日期:2005-01-07    瀏覽次數:24
  

儘管我的題目是“用C語言寫作業系統”,但是,僅僅使用C語言是寫不出作業系統的。我看到很多篇關於自己動手開發作業系統的文章,幾乎全來自一篇叫“Write Your Own Operating System Tutorial”英文文章,而且,使用的全是組合語言。如今能夠精通組合語言的人已屬鳳毛麟角,而且現代作業系統的主體部分是用C語言寫的,難道所謂的“Own Operating System”只能用組合語言嗎?在下不才,使用C語言(在某些部分必須結合組合語言)寫了一個可以與上述文章中提到的作業系統相媲美的作業系統,拋磚引玉,希望能夠將其發展成為真正的中國人自己的作業系統。

我是在Windows環境下開發的,而不是大多數人選擇的Linux環境。開發工具也是Microsoft公司的開發工具:masm615和VC15。微軟公司的masm流傳甚廣,大家應該不陌生。對vc15可能較陌生,vc15堪稱開發DOS程式的最“高檔”編譯器(儘管有很多BUG)。如果實在找不到這些開發工具,使用TASM、Turbo C或者Borland C++都是可以的。所給出的例子以masm615和vc15為準,轉移到TASM、TC或BC平台,應該不難。有一條原則需要注意,在這裡,源碼必須使用TINY模式編譯,也就是說,必鬚生成實模式代碼。

1.          建立開發環境
這一步非常的簡單。

將masm613和vc15的壓縮包分別解壓到e:/masm615和e:/msvc15目錄下。你也可以放到其他目錄下,根據自己的情況而定,但是下面用到的編譯命令需要作相應的修改。也不需要添加或修改任何的環境變數。

2.          IBM PC的啟動及當時的記憶體使用量情況
這一部分內容已經是老生常談了,但又不能不說。我們只說從硬碟引導的情況。

當BIOS經過POST(Power On Test Self)後,將硬碟MBR讀到記憶體0x0000:0x7C00的位置,然後從這裡開始執行。一般的情況,MBR將選擇使用中的磁碟分割進行作業系統的啟動。在MBR開始執行時,記憶體使用量的情況如所示,地址資料用16進位表示:

這已經是老掉牙的內容了,但是,在20年前卻十分流行。如果想更詳細的瞭解這方面的內容,找本講解DOS的書看看吧。

我們自己的作業系統將被載入到0x1000:0x0100。這不是必需或者必然的,是人為選擇的,你也可以將其放在0x4321:1234等其他地方。但是,中註明有其他用途的記憶體地區,應該保留,否則,你會後悔的。

怎樣用C語言開發作業系統[2]
--------------------------------------------------------------------------------

作者:tianxiangyuan   來源:原創    更新日期:2005-01-07    瀏覽次數:29
  

3. 開發作業系統
我們自己的作業系統運行在實模式環境下(如果您不知道什麼是實模式,也請看看20年前出版的當時非常流行的書,或者直接請教當時的前輩高手)。即使你的電腦是P4的CPU,剛啟動時,也只相當於主頻較高的8086而已。但是,沒有關係。
首先,使用組合語言寫一個架構,檔案名稱是entry.asm:
;
;   entry.asm
;   Copyright (C) 2004, Tian XiangYuan
;
.MODEL TINY,C
.386p

option expr32
option casemap:none

cmain PROTO NEAR C

.CODE
    ORG 0100h ;位移地址
_start:
    jmp begin
    nop
    DB 'TianXiangYuan',0 ;the magic of my os
    
begin:
    cli
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,0FFFFh
    sti
    
    call cmain ;調用C語言寫的主函數
    
    mov ax,4c00h ;調用DOS的功能(為了調試),與我們自己的作業系統無關
    int 21h

這段代碼非常簡單,應該沒有什麼問題。
已經說了,作業系統將從0x1000:0x0100載入,說是無心,實則有意。我們知道,TINY模式的程式,在DOS下運行時,其起始地址就是0x0100,前面的256Byte是參數部分。如果直接將作業系統在系統啟動時載入到0x1000:0x0100,調試時非常麻煩。我們將其起始地址設為0x0100,使其可以在DOS下運行(這也是在程式的最後包含int 21h指令的原因),確認正確無誤後,再進行下一步的開發。
下面再看C語言的代碼,檔案名稱是main.c:
……
static void InitShell()
{
}
void cmain()
{
    InitShell();
    TermShell();
}

顧名思義,其中實現了一個簡單的shell。因為該程式本身是作業系統的一部分,所以,平時經常使用的一些C庫函數,在這裡就不能使用了。總之,一切都要自己動手實現。幸好,在實模式下,幾乎所有的裝置的驅動都包含在BIOS中了,我們可以直接使用。否則,連從鍵盤讀一個索引值這樣的事都需要自己寫鍵盤的驅動程式,實在太難了。也是這個原因,我們自己的作業系統沒有將CPU轉到保護模式下,有心之人可以試試。
下面的事情幾乎都可以使用C語言實現了。
第一,初始化顯示模式。系統啟動時,顯卡已經被初始化成3模式了,就是80X25的彩色模式(除非你的顯示器是單色顯示器),我們不需要再做什麼了。當然,你也可以將顯卡設成VGA甚至SVGA模式,只要你的BIOS和顯卡支援。
第二,實現一個具有簡單互動功能的shell。代碼不全,請自己補齊,或參看附件。
/*
*從鍵盤讀一個字元,如果沒有輸入,則等待;傳回值的低位元組為asii碼,高位元組為鍵盤掃描碼
*/
static int getch()
{
    int chr=0;
    __asm
    {
        mov ah,00h
        int 16h
        mov chr,ax
    }
    return chr;
}
/*
*使用TTY模式向螢幕輸出一個字元
*/
static void putch(unsigned char key)
{
    __asm
    {
        mov bh,0
        mov al,key
        mov ah,0Eh
        int 10h
    }
}

#define KEY_BACKSPACE 0x08
#define KEY_ENTER 0x0D
#define KEY_NEWLINE 0x0A
#define KEY_ESCAPE 0x1B

static int printk(const char* str,...)
{
    …… //給大家一點空間,自己實現吧
}
static void endline()
{
    putch(KEY_NEWLINE); //Line Feed (LF)
    putch(KEY_ENTER); //Enter (CR)
}
static char msg_prompt[]="CMD:";
static void deal_cmd(char* cmd_line,int cmd_len)
{
…… //也請大家自己實現吧,例如,可以實現help,dir,cls,halt等命令
…… //其實,就是字串比較的過程
}
static void TermShell()
{
    char cmd_line[80]={0,};
    int cmd_len=0;
    
    endline();
    printk(msg_prompt,sizeof(msg_prompt));
    
    for (;;)
    {
        cmd_line[cmd_len]=getch();
        switch(cmd_line[cmd_len])
        {
        case KEY_ENTER:
            if (cmd_len>1)
                deal_cmd(cmd_line,cmd_len);
            //break;
        case KEY_ESCAPE:
            cmd_len=0;
            endline();
            printk(msg_prompt,sizeof(msg_prompt));
            break;
        case KEY_BACKSPACE:
            if (cmd_len>0)
            {
                putch(0x08);
                putch(' ');
                putch(0x08);
                cmd_len--;
            }
            break;
        default:
            putch(cmd_line[cmd_len]);
            cmd_len++;
        }
    }
}

更複雜、功能更強大的方法請參考BIOS的相關文檔。也請大家發揮想象力,不斷的擴充功能。說心裡話,這個 “作業系統”比dos還原始!但畢竟是自己的作業系統。
4. 編譯方法
下面是build.bat的內容。各種編譯選項參看相關編譯器的說明文檔。
作系統載入到記憶體的0x1000:0x0100,並且cpu工作在實模式下。如果實在找不到合適的引導程式,只有自己動手寫一個了。
@echo off
set PATH=e:/masm615/bin;e:/msvc15/bin;
set AS=e:/masm615/bin/ml.exe
set AFLAGS=/AT /W3 /X /Gd /Zp1 /nologo
set CC=e:/msvc15/bin/cl.exe
set CFLAGS=/Od /G3 /Gd /Gs /Zl /Zp1 /X /W3 /nologo
del *.obj *.com *.cod *.dbg *.pdb *.map *.lst
%AS% /c %AFLAGS% entry.asm
if errorlevel 1 goto error
%CC% /c %CFLAGS% /Fc main.c
if errorlevel 1 goto error
%AS% %AFLAGS% /Fe"boot.com" entry.obj main.obj
if errorlevel 1 goto error
goto exit

:error
echo Failure......
:exit
pause
@echo on

5. 引導程式

我們自己的作業系統雖然寫完了,但是還沒有辦法引導,使其擁有系統的控制權。你可以使用第三方的引導程式,只要它能夠將我們的作業系統載入到記憶體的0x1000:0x0100,並且cpu工作在實模式下。如果實在找不到合適的引導程式,只有自己動手寫一個了。

;

;   bootsect.asm

;   Copyright(C) 2004, Tian XiangYuan

;

.MODEL TINY,C

.386p

option expr32

option casemap:none

SYSSEG EQU 1000h

SYSOFF EQU 0100h

.CODE

    ORG 7C00h

_start:

    jmp begin

    nop

    DB 'BOOTSECT',0 ;magic

    

    pack_size DB 16

    DB 0   ;reserved

    DW 60 ;sectors

    DW SYSOFF ;buf_addr_off

    DW SYSSEG ;buf_addr_seg

    DD 2 ;sector_from

    DD 0 ;sector_from_high

    

begin:

    cli

    mov ax,cs

    mov ds,ax

    mov es,ax

    mov ss,ax

    mov sp,0FFFFh

    sti

    

    mov cx,msg_load_len ;length

    lea bp,msg_load ;es:bp

    call display_msg

    ; read disk for my OS

    lea si,pack_size

    mov dl,80h

    mov ax,4200h

    int 13h ;使用LBA方式讀硬碟

    jc error

    

    ; test magic of my os

    lea si,magic_test ;ds:si

    mov ax,SYSSEG

    mov es,ax

    mov di,SYSOFF

    add di,3 ;es:di

    mov cx,magic_test_len

    cld

test_again:

    cmpsb

    jnz error

    loop test_again

    

    push SYSSEG

    push SYSOFF

    retf ;轉入作業系統執行

error:

    mov ax,cs

    mov es,ax

    lea bp,msg_error ;es:bp

    mov cx,msg_error_len

    call display_msg

failure:

    hlt

    jmp failure

;cx    : length of message

;es:bp : address of message

;void display_msg();

display_msg PROC NEAR C

    ;scrollup a line

    push cx

    push bp

    mov ax,0601h

    mov bh,07h

    mov cx,0000h ;y/x

    mov dx,184Fh ;y2/x2, 24/79

    int 10h

    pop bp

    pop cx

    ;display message

    mov ax,1301h

    mov bx,000Ah

    ;mov cx,msg_error_len

    mov dl,0  ;x

    mov dh,24 ;y

    ;lea bp,msg_error ;es:bp

    int 10h

    ret

display_msg endp

.DATA

msg_load DB 'Loading......',0

msg_load_len DW $ - msg_load

msg_error DB 'NO BOOTER,please reboot!',0

msg_error_len DW $ - msg_error

magic_test DB 'TianXiangYuan',0

magic_test_len DW $ - magic_test

    end _start

上面這段代碼,是MBR的內容,他使用LBA方式讀硬碟(支援大硬碟),將我們自己的作業系統讀入0x1000:0x0100,然後轉入作業系統執行。

很顯然,我們的作業系統必須放在硬碟的No.2(LBA定位方式)扇區開始的60個扇區之內(實際上我們的作業系統遠沒有這麼大),這時我們的引導程式的硬性規定,如果使用第三方的引導程式,也許會更方便。

可以自己開發安裝程式,也可以使用WinHex工具將其寫入硬碟。請一定注意資料安全,不要將硬碟分區搞壞,建議做好備份工作,或者使用沒有重要資料的測試硬碟。順便說一下,我是使用WinHex寫入測試硬碟的。

這段引導程式的編譯方式與作業系統一樣,build.dat檔案如下:

@echo off

set PATH=e:/masm615/bin;

set AS=e:/masm615/bin/ml.exe

set AFLAGS=/AT /W3 /WX /Gd /Zp1 /X /nologo

del *.obj *.com *.cod *.dbg *.pdb *.map

%AS% /c %AFLAGS% bootsect.asm

if errorlevel 1 goto error

%AS% %AFLAGS% /Fe"bootsect.com" bootsect.obj

if errorlevel 1 goto error

goto exit

:error

echo Failure......

:exit

pause

@echo on

6.          後記
我們自己的作業系統太原始了,連DOS都不如!在這裡,主要介紹的是一種開發方法,旨在說明使用C語言如何開發像作業系統這樣底層的軟體。

閑暇時,將其移至Linux平台下開發,並且使用cpu的保護模式,畢竟這樣才能發揮80x86系列cpu的強大功能。

歡迎提出寶貴意見:tianxiangyuan@sina.com.cn

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.