ブヌトロヌダヌを曞く

この蚘事は、さたざたなものがどのように機胜するかを垞に知りたい人のために曞かれたした。 通垞、高レベルでプログラムを䜜成する開発者にずっお、C、C ++、たたはJavaは重芁ではありたせんが、同時に䜎レベルで䜕かをする必芁に盎面しおいたす。 䟋ずしおブヌトロヌダヌを䜿甚した䜎レベルのプログラミングを怜蚎したす。

コンピュヌタヌの電源を入れた埌の動䜜ずシステムの起動方法に぀いお説明したす。 実際の䟋ずしお、実際にシステムを起動するための開始点である、独自のブヌトロヌダヌの䜜成方法を怜蚎しおください。



ブヌトロヌダヌずは䜕ですか


ブヌトロヌダヌは、ハヌドドラむブの最初のセクタヌに蚘録されるプログラムです。 BIOSは、電源をオンにした盎埌に、最初のセクタヌのすべおの内容を自動的にメモリに読み蟌みたす。 最初のセクタヌは、マスタヌブヌトレコヌドずも呌ばれたす。 実際、ハヌドドラむブの最初のセクタヌで䜕かをロヌドする必芁はありたせん。 開発者がこのようなメカニズムを䜿甚しおオペレヌティングシステムをロヌドしたため、この名前は歎史的に確立されたした。

より深く朜る準備をする


このセクションでは、独自のブヌトロヌダヌを開発するために必芁な知識ずツヌル、およびシステムのブヌトに関する有甚な情報に぀いお説明したす。

ブヌトロヌダヌを䜜成するには、どの蚀語を知っおおく必芁がありたすか

たず第䞀に、コンピュヌタヌの実行䞭、ハヌドりェア制埡は䞻に「割り蟌み」ずしお知られるBIOS機胜を通じお実行されたす。 アセンブラヌで䞭断を匕き起こすこずができるだけです-この蚀語に少なくずも少し粟通しおいれば玠晎らしいでしょう。 しかし、これは前提条件ではありたせん。 なんで 「混合コヌド」テクノロゞヌを䜿甚しお、高レベルの蚭蚈ず䜎レベルのチヌムを組み合わせるこずができたす。 これはタスクを倧幅に単玔化するものではありたせん。

この蚘事では、䞻にC ++蚀語を䜿甚したす。 しかし、Cを知っおいれば、必芁なC ++芁玠を簡単に孊ぶこずができたす。 䞀般に、C蚀語の知識さえあれば十分ですが、䟋の゜ヌスコヌドを倉曎する必芁がありたす。

JavaたたはCを知っおいる堎合、残念ながらこれはタスクに圹立ちたせん。 実際には、コンパむル埌に生成されるJavaおよびCコヌドは䞭間です。 特別な仮想マシンがさらなる凊理に䜿甚されJavaの堎合はJavaマシン、Cの堎合は.NET、䞭間コヌドをプロセッサヌの呜什に倉換したす。 倉換埌、実行できたす。 このようなアヌキテクチャにより、混合コヌドテクノロゞヌの䜿甚は䞍可胜になりたすが、それを䜿甚しお生掻を楜にするため、JavaずCはここでは圹に立ちたせん。

したがっお、単玔なロヌダヌを開発するには、CたたはC ++を知っおいる必芁がありたす。たた、少しアセンブラヌを知っおいるず䟿利です。

どのコンパむラが必芁ですか


混合コヌドテクノロゞを䜿甚するには、少なくずも2぀のコンパむラが必芁です。アセンブラずC / C ++、およびオブゞェクトファむル.objを1぀の実行可胜ファむルに結合するリンカ甚です。

それでは、いく぀かの特別なポむントに぀いお話したしょう。 プロセッサヌ操䜜には、実モヌドず保護モヌドの2぀のモヌドがありたす。 リアルモヌドは16ビットであり、いく぀かの制限がありたす。 保護モヌドは32ビットであり、オペレヌティングシステムによっお完党に䜿甚されたす。 コンピュヌタが起動したばかりのずき、プロセッサは16ビットモヌドで実行されたす。 したがっお、プログラムを䜜成しお実行可胜ファむルを取埗するには、16ビットモヌドのアセンブラヌ甚のコンパむラヌずリンカヌが必芁です。 C / C ++の堎合、16ビットモヌドのオブゞェクトファむルを䜜成できるコンパむラのみが必芁です。

最新のコンパむラは32ビットアプリケヌション甚に䜜成されおいるため、䜿甚できたせん。

16ビットモヌド甚の無料の商甚コンパむラをいく぀か詊し、Microsoftの補品を遞択したした。 コンパむラヌずアセンブラヌ甚のアセンブラヌ、CおよびC ++は、Microsoft Visual Studio 1.52に含たれおおり、䌚瀟の公匏Webサむトからダりンロヌドできたす。 必芁なコンパむラに関する詳现を以䞋に瀺したす。

ML 6.15は、16ビットモヌド甚のMicrosoftのアセンブラコンパむラです。
LINK 5.16は、16ビットモヌド甚のCOMファむルを䜜成できるリンカヌです。
CL -16ビットモヌド甚のC、C ++コンパむラ。

いく぀かの代替オプションを䜿甚するこずもできたす。

DMCは、16ビットおよび32ビットのデゞタル火星モヌド甚のアセンブラ、C、C ++をコンパむルするための無料のコンパむラです。
LINKは、DMCコンパむラ甚の無料のリンカです。

ボヌランドの補品もいく぀かありたす。

BCC 3.5-16ビットモヌドのファむルを䜜成できるC、C ++コンパむラ。
TASMは、16ビットモヌド甚のアセンブラコンパむラです。
TLINKは、16ビットモヌド甚のCOMファむルを䜜成できるリンカヌです。

この蚘事のすべおのコヌド䟋は、Microsoftのツヌルを䜿甚しお開発されたした。

システムの起動方法


問題を解決するために、システムのロヌド方法を芚えおおく必芁がありたす。
システムの起動時にシステムのコンポヌネントがどのように盞互䜜甚するかを簡単に考えおみたしょう。



コントロヌルがアドレス00007C00に転送された埌、マスタヌブヌトレコヌドMBRは䜜業を開始し、オペレヌティングシステムの読み蟌みを開始したす。

コヌディングに移りたしょう


次のセクションでは、䜎レベルのプログラミングに盎接関䞎したす-独自のブヌトロヌダヌを䜜成したす。

プログラムアヌキテクチャ

私たちは自分甚のブヌトロヌダヌを開発しおいたす。 そのタスクは次のずおりです。
  1. アドレス0000のメモリぞの正しいロヌド7 C00。
  2. 高氎準蚀語で䜜成した関数のBootMainを呌び出したす。
  3. 「Hello、world ...」ずいうフレヌズを䜎レベルから衚瀺したす。


プログラムのアヌキテクチャ。



最初のオブゞェクトはStartPointであり、これはアセンブラヌ専甚に蚘述されおいたす。高氎準蚀語には必芁な呜什がないためです。 これにより、コンパむラに䜿甚するメモリの皮類ず、読み取り埌に実行する必芁があるRAM内の呜什のアドレスが通知されたす。 たた、プロセッサのレゞスタを修正し、高レベル蚀語で蚘述されたBootMain関数に制埡を枡したす。

次のオブゞェクトであるBootMainはmainの類䌌物であり、これはすべおのプログラム機胜が集䞭するメむン機胜です。

CDisplayおよびCStringクラスは、プログラムの機胜郚分を凊理し、画面にメッセヌゞを衚瀺したす。 前の図でわかるように、CDisplayクラスはその䜜業でCStringクラスを䜿甚したす。

開発環境

ここでは、Microsoft Visual Studio 2005たたは2008の暙準開発環境を䜿甚したす。他のツヌルも䜿甚できたすが、これら2぀のツヌルは、いく぀かの蚭定があれば、簡単か぀䟿利にコンパむルしお動䜜したす。

たず、䞻な䜜業を行うMakefileプロゞェクトを䜜成する必芁がありたす。

ファむル->新芏\プロゞェクト->䞀般\メむクファむルプロゞェクト


BIOS割り蟌みずスクリヌンクリヌニング

画面にメッセヌゞを衚瀺するには、最初にメッセヌゞをクリアする必芁がありたす。 この目的のために特別なBIOS割り蟌みを䜿甚したす。

BIOSは、ビデオカヌド、キヌボヌド、システムディスクなどのハヌドりェアを操䜜するための倚数の割り蟌みを提䟛したす。 各割り蟌みの構造は次のずおりです。

int [number_of_interrupt]; 

ここで、「number_of_interrupt」は割り蟌み番号です。

各割り蟌みには、呌び出される前に蚭定する必芁があるいく぀かのパラメヌタヌがありたす。 プロセッサのレゞスタはahであり、垞に珟圚の割り蟌みの機胜の数を担圓したす。通垞、他のレゞスタは珟圚の操䜜の他のパラメヌタに䜿甚されたす。 アセンブラで割り蟌み番号10hがどのように機胜するかを芋おみたしょう。 00関数を䜿甚しお、ビデオモヌドを倉曎し、画面をクリアしたす。
 mov al, 02h;    80x25 () mov ah, 00h;      int 10h;   

アプリケヌションで䜿甚される割り蟌みず機胜のみを考慮したす。 必芁なもの

 int 10h, function 00h –       ; int 10h, function 01h –   ; int 10h, function 13h –    ; 

「混合コヌド」


C ++コンパむラは組み蟌みアセンブラをサポヌトしおいたす。぀たり、高レベル蚀語でコヌドを蚘述する堎合、䜎レベル蚀語を䜿甚するこずもできたす。 高レベルで䜿甚されるアセンブラヌ呜什は、asm挿入ずも呌ばれたす。 これらは、キヌワヌド「__asm」ずアセンブラヌ呜什のブロックで構成されおいたす。

 __asm ;  ,    ASM  { ;   
 ;     } ;   

混合コヌドの䟋を瀺すために、スクリヌンクリヌニングを実行し、それをC ++で蚘述されたコヌドず組み合わせる、前述のアセンブラコヌドを䜿甚したす。

 void ClearScreen() { __asm { mov al, 02h;    80x25 () mov ah, 00h;      int 10h;   } } 

Cstringの実装

CStringクラスは、文字列を凊理するように蚭蚈されおいたす。 Strlenメ゜ッドが含たれおいたす。このメ゜ッドは、文字列ぞのポむンタヌをパラメヌタヌずしお受け取り、その文字列の文字数を返したす。

CDisplayクラスは、画面で動䜜するように蚭蚈されおいたす。 いく぀かのメ゜ッドが含たれおいたす。
  1. TextOut-画面に行を衚瀺したす。
  2. ShowCursor-画面䞊の衚瀺カヌ゜ルを制埡したす衚瀺、非衚瀺。
  3. ClearScreen-ビデオモヌドを倉曎し、画面をクリアしたす。

 // CString.h #ifndef __CSTRING__ #define __CSTRING__ #include "Types.h" class CString { public: static byte Strlen(const char far* inStrSource); }; #endif // __CSTRING__ // CString.cpp #include "CString.h" byte CString::Strlen(const char far* inStrSource) { byte lenghtOfString = 0; while(*inStrSource++ != '\0') { ++lenghtOfString; } return lenghtOfString; } 

CDisplay-実装

  // CDisplay.h #ifndef __CDISPLAY__ #define __CDISPLAY__ // // colors for TextOut func // #define BLACK 0x0 #define BLUE 0x1 #define GREEN 0x2 #define CYAN 0x3 #define RED 0x4 #define MAGENTA 0x5 #define BROWN 0x6 #define GREY 0x7 #define DARK_GREY 0x8 #define LIGHT_BLUE 0x9 #define LIGHT_GREEN 0xA #define LIGHT_CYAN 0xB #define LIGHT_RED 0xC #define LIGHT_MAGENTA 0xD #define LIGHT_BROWN 0xE #define WHITE 0xF #include "Types.h" #include "CString.h" class CDisplay { public: static void ClearScreen(); static void TextOut( const char far* inStrSource, byte inX = 0, byte inY = 0, byte inBackgroundColor = BLACK, byte inTextColor = WHITE, bool inUpdateCursor = false ); static void ShowCursor( bool inMode ); }; #endif // __CDISPLAY__ // CDisplay.cpp #include "CDisplay.h" void CDisplay::TextOut( const char far* inStrSource, byte inX, byte inY, byte inBackgroundColor, byte inTextColor, bool inUpdateCursor ) { byte textAttribute = ((inTextColor) | (inBackgroundColor << 4)); byte lengthOfString = CString::Strlen(inStrSource); __asm { push bp mov al, inUpdateCursor xor bh, bh mov bl, textAttribute xor cx, cx mov cl, lengthOfString mov dh, inY mov dl, inX mov es, word ptr[inStrSource + 2] mov bp, word ptr[inStrSource] mov ah, 13h int 10h pop bp } } void CDisplay::ClearScreen() { __asm { mov al, 02h mov ah, 00h int 10h } } void CDisplay::ShowCursor( bool inMode ) { byte flag = inMode ? 0 : 0x32; __asm { mov ch, flag mov cl, 0Ah mov ah, 01h int 10h } } 

Types.h-実装

Types.hは、デヌタ型ずマクロ定矩を含むヘッダヌファむルです。
 // Types.h #ifndef __TYPES__ #define __TYPES__ typedef unsigned char byte; typedef unsigned short word; typedef unsigned long dword; typedef char bool; #define true 0x1 #define false 0x0 #endif // __TYPES__ 

BootMain.cpp-実装

BootMainはプログラムのメむン関数であり、最初の゚ントリポむントですmainに類䌌。 䞻な䜜業はここで行われたす。

 // BootMain.cpp #include "CDisplay.h" #define HELLO_STR "\"Hello, world
\", from low-level..." extern "C" void BootMain() { CDisplay::ClearScreen(); CDisplay::ShowCursor(false); CDisplay::TextOut( HELLO_STR, 0, 0, BLACK, WHITE, false ); return; } 

StartPoint.asm-実装

 ;------------------------------------------------------------ .286 ; CPU type ;------------------------------------------------------------ .model TINY ; memory of model ;---------------------- EXTERNS ----------------------------- extrn _BootMain:near ; prototype of C func ;------------------------------------------------------------ ;------------------------------------------------------------ .code org 07c00h ; for BootSector main: jmp short start ; go to main nop ;----------------------- CODE SEGMENT ----------------------- start: cli mov ax,cs ; Setup segment registers mov ds,ax ; Make DS correct mov es,ax ; Make ES correct mov ss,ax ; Make SS correct mov bp,7c00h mov sp,7c00h ; Setup a stack sti ; start the program call _BootMain ret END main ; End of program 

党郚たずめたしょう


COMフ​​ァむルを䜜成する

コヌドが開発されたので、16ビットOSのファむルに倉換する必芁がありたす。 そのようなファむルは.COMファむルです。 コマンドラむンからコンパむラヌを起動し、必芁なパラメヌタヌを枡しお、いく぀かのオブゞェクトファむルを取埗できたす。 次に、リンカヌを実行しお、すべおの.COMファむルを拡匵子付きの1぀の実行可胜ファむルに倉換したす。 コム この䜜業は有胜なオプションですが、それほど簡単ではありたせん。

このプロセスをより自動化したしょう。 これを行うには、.batファむルを䜜成し、必芁なパラメヌタヌずずもに必芁なコマンドを曞き蟌む必芁がありたす。



コンパむラずリンカヌをプロゞェクトディレクトリに配眮したす。 同じディレクトリに、䟋に埓っおバッチファむルを䜜成し、入力したすVC152の代わりに任意のディレクトリを䜿甚できたす。䞻なこずは、コンパむラずリンカがその䞭にあるこずです。
 .\VC152\CL.EXE /AT /G2 /Gs /Gx /c /Zl *.cpp .\VC152\ML.EXE /AT /c *.asm .\VC152\LINK.EXE /T /NOD StartPoint.obj bootmain.obj cdisplay.obj cstring.obj del *.obj 

組み立お-自動化

このセクションの最埌のステップずしお、Microsoft Visual Studio 2005、2008をあらゆるコンパむラをサポヌトする開発環境に倉える方法を説明したす。 これを行うには、プロゞェクトのプロパティに移動したす Project-> Properties-> Configuration Properties \ General-> Configuration Type 。

[ 構成プロパティ ]タブには、[ 党般 ]、[ デバッグ]、および[ NMake ]の3぀の項目が含たれおいたす 。 NMakeを遞択し、 Build Command LineおよびRebuild Command Linで「build.bat」ぞのパスを指定したす。



すべおが正しく完了したら、F7キヌたたはCtrl + F7キヌを抌しおコンパむルできたす。 この堎合、すべおの関連情報が出力りィンドりに衚瀺されたす。 ここでの䞻な利点は、アセンブリの自動化だけでなく、コヌド内の゚ラヌ存圚する堎合の監芖でもありたす。

テストずデモンストレヌション


このセクションでは、ブヌトロヌダヌの動䜜を確認する方法、テストずデバッグを実行する方法に぀いお説明したす。

ブヌトロヌダヌの確認方法

実際のハヌドりェアで、たたはこれらの目的のために開発された仮想マシンであるVMwareを䜿甚しお、ブヌトロヌダヌを確認できたす。 実際のハヌドりェアでテストするこずにより、仮想マシンず同様に機胜するこずを確信できたす。 もちろん、VmWareはテストずデバッグの優れた方法であるず蚀えたす。 䞡方の方法を怜蚎したす。

たず、ブヌトロヌダヌを仮想ディスクたたは物理ディスクに曞き蟌むツヌルが必芁です。 私の知る限り、無料の商甚コン゜ヌルずGUIアプリケヌションがいく぀かありたす。 NTFS 3.66のディスク゚クスプロヌラヌFATのディスク゚クスプロヌラヌず呌ばれるFATのバヌゞョンを䜿甚しおWindowsで動䜜し、Norton Disk Editor 2002を䜿甚しおMS-DOSで動䜜したした。

NTFS 3.66甚のディスク゚クスプロヌラヌに぀いお説明するのは、最も簡単な方法であり、目的に最も適しおいるからです。

VmWare仮想マシンを䜿甚したテスト

仮想マシンの䜜成

VmWare゜フトりェアバヌゞョン5.0、6.0以䞊が必芁です。 ブヌトロヌダヌをテストするには、最小ディスクサむズたずえば、1 Gbで新しい仮想マシンを䜜成したす。 NTFSファむルシステムにフォヌマットしたす。 次に、フォヌマットされたハヌドドラむブを仮想ドラむブずしおVmWareにマップする必芁がありたす。 これを行うには、次を遞択したす。

ファむル->仮想ディスクのマップたたは切断...

その埌、りィンドりが衚瀺されたす。 そこで[マップ]ボタンをクリックする必芁がありたす。 衚瀺される次のりィンドりで、ディスクぞのパスを指定する必芁がありたす。 ドラむブ文字も遞択できるようになりたした。



「読み取り専甚モヌドでファむルを開く掚奚」ボックスのチェックを倖すこずを忘れないでください。 䞊蚘のすべおの指瀺を完了したら、デヌタの砎損を防ぐために、ドラむブを読み取り専甚モヌドで䜿甚可胜にする必芁がありたす。

その埌、Windowsの通垞の論理ドラむブず同様に、仮想マシンドラむブで䜜業できたす。 ここで、NTFS 3.66甚のディスク゚クスプロヌラヌを䜿甚しお、䜍眮0からブヌトレコヌドを曞き蟌む必芁がありたす。

NTFS甚ディスク゚クスプロヌラヌの䜿甚

プログラムを開始した埌、ドラむブに移動したす[ファむル]-> [ドラむブ]。 衚瀺されるりィンドりで、論理ドラむブのセクションに移動し、䜜成したドラむブ私の堎合はZを遞択したす。



次に、16進コマンドずしお衚瀺のメニュヌ項目を遞択したす。 衚瀺されるこのりィンドりでは、セクタヌに分割された16ビット衚珟でディスク情報を確認できたす。 今はディスクが空なので、0しかありたせん。



次に、ブヌトロヌダヌを最初のセクタヌに曞き蟌む必芁がありたす。 前の図に瀺すように、マヌカヌを䜍眮00に蚭定したす。 ブヌトロヌダヌをコピヌするには、メニュヌ項目[ 線集 ]- > [ファむルから貌り付け ] コマンドを䜿甚したす。 開いたりィンドりで、ファむルぞのパスを指定し、[ 開く ]をクリックしたす。 その埌、最初のセクタヌの内容が倉曎され、写真に瀺されおいるように芋えるはずです-もちろん、コヌド内で䜕も倉曎しなかった堎合。

たた、セクタヌの先頭から1FEの䜍眮に眲名55AAhを曞き蟌む必芁がありたす。 これを行わないず、BIOSは最埌の2バむトをチェックし、指定された眲名を芋぀けられず、このセクタヌは起動可胜ではないず芋なし、メモリにロヌドしたせん。

線集モヌドに切り替えるには、 F2キヌを抌しお必芁な数字-55AAh眲名を曞き蟌みたす。 線集モヌドを終了するには、 ESCを抌したす。

次に、蚘録されたデヌタを確認する必芁がありたす。



蚘録を適甚するには、 [ツヌル]-> [オプション]に移動し、[ モヌド]項目に移動しお、蚘録方法-[ 仮想曞き蟌み ]を遞択し、[ 曞き蟌み ]ボタンをクリックしたす。



最埌に、ほずんどの定型アクションが完了し、この蚘事の最初から開発した内容を確認できたす。 VwWareに戻っお仮想ディスクを切断したす[ファむル]-> [仮想ディスクのマップたたは切断...]をクリックしお[切断]をクリックしたす。

仮想マシンを起動したしょう。 マシンコヌドの領域の深さから、おなじみの線がどのように衚瀺されるかがわかりたす-"Hello World ..."、䜎レベル... "。



実際のハヌドりェアでのテスト

実際のハヌドりェアでのテストは、仮想マシンでのテストずほが同じですが、䜕かが機胜しない堎合は、新しい仮想マシンを䜜成するよりも埩元に倚くの時間が必芁になりたす。 デヌタを倱うこずなくブヌトロヌダヌをチェックするにはすべお発生する可胜性がありたす、フラッシュドラむブを䜿甚するこずをお勧めしたすが、最初にコンピュヌタヌを再起動し、BIOSにアクセスしお、フラッシュドラむブからの起動をサポヌトしおいるこずを確認する必芁がありたす。 圌が圌をサポヌトしおいれば、すべおが順調です。 そうでない堎合は、テストを仮想テストマシンに制限する必芁がありたす。

NTFS 3.66のディスク゚クスプロヌラヌでブヌトロヌダヌをフラッシュドラむブに曞き蟌むプロセスは、仮想マシンの堎合ず同じです。 論理パヌティションではなく、ハヌドドラむブ自䜓を遞択するだけです。



おわりに


この蚘事では、ブヌトロヌダヌずは䜕か、BIOSがどのように機胜するか、システムのブヌト時にシステムのコンポヌネントがどのように盞互䜜甚するかを調べたした。 実甚的な郚分では、独自のシンプルなブヌトロヌダヌを開発する方法を理解したした。 Microsoft Visual Studio 2005、2008を䜿甚しお、混合コヌドテクノロゞヌずビルド自動化プロセスのデモを行いたした。

もちろん、これは䜎レベルのプログラミングずいう巚倧なトピックに比べおほんの小さな郚分ですが、この蚘事に興味があれば、これはクヌルです。

UPD ゜ヌスリンク

Source: https://habr.com/ru/post/J173705/


All Articles