1) ページング。
おそらく、すべての人はすでに人で大騒ぎしており、このページングが何であるかを知っています。 1 MBを超えてブレークアウトし、4ギガバイトのRAMをすべてアドレス指定できます。 しかし、私たちのささやかなクラフトに4 GBが必要なのはなぜですか(特に誰もがそれほど多くのRAMを持っているわけではないため) 32MBで十分です(これもたくさんありますが、夢見てみましょう)。 したがって、4Kページを使用します。 したがって、今考慮します-1024ページは4 Mbを記述します。 したがって、必要なのは1024 * 8ページのみです。 つまり、8つのテーブルと1つのディレクトリが必要です。 また、便宜上、ページは同一です。つまり、論理アドレスと物理アドレスは同じです。 それでは、必要なものすべてを形成する関数を書きましょう。
set_pages:
.set_cat:
mov edi,100000h;
mov eax,101007h;
mov cx,8 ;8*4=32
.fill_cat_usef: ;
stosd
add eax,1000h
loop .fill_cat_usef
mov cx,1016 ;
xor eax,eax
rep stosd
mov eax,00000007h
mov ecx,1024*8;32Mb
.fill_page_table: ;
stosd
add eax,1000h
loop .fill_page_table
;End;
mov eax,00100000h;1 Mb; cr3
mov cr3,eax
mov eax,cr0
or eax,80000000h
mov cr0,eax
ret
あなたは質問があるかもしれません、なぜ他のディレクトリにゼロを煩わせるのですか? また、ディレクトリなどのテーブルを1000hの倍数のアドレスに配置できることを忘れないでください。
2) 割り込み。
割り込みでは、 PMには驚きがあります。RMのように、割り込みバイトは4バイト以下です。 その代わりに、 Interrupt Gates (今では私たちにとって重要です)、 Trap Gates 、 Task Gates - IDTにある64ビット構造がありました。 構造は次のとおりです。
ここで、フィールドの目的は明確です(セグメント記述子でそれらのいくつかに出会ったので、なおさらそうです)。 今のところ、割り込みゲートのみを検討します 。 lidtコマンドを使用して、 PMに移動する前にIDTをコンパイルし、サイズとオフセットをIDTRレジスタにロードする必要があります(その構造はGDTR構造に似ています )。 ちなみに、 IDTはセグメント(たとえば、線形アドレス空間にあるGDTの対極 )です。つまり、特定のセグメントに配置されています。 たとえば、PMに転送する前に4Kのメモリを記述した場合、これらの制限の外側にIDTがあり、PMに切り替えた後に割り込みを有効にすると、すべてがクラッシュします。
さらにいくつかのメモ:Intelは割り込み0-31を予約しました。 そこで、これらのexception'ovのハンドラーを配置する必要があります。 その中でも、0で割るエラー(#DE)、#GPの一般的な保護の例外、その他の楽しいことです。 したがって、割り込みのベースアドレスをシフトする必要があります。つまり、IRQ0を32番目の位置に配置するなどです。 古き良きi8259aチップを使用することをすぐに予約しなければなりません。 もちろん、 APIC - Advanced Programmable Interrupt Controllerを使用できます (ちなみに、ハンドルでオンにする必要があります)。ただし、それを利用する必要はありません(ハードウェア割り込みの数の拡大、マルチプロセッシングへの適応性など)。 ICW ( 初期化制御ワード )とOCW ( 操作制御ワード )が何であるかをみんなが覚えているといいのですが? 使用されているものを繰り返しましょう(構造は説明しません):
ICW:
1)注文の順序の特徴の決定。
2)ベースアドレスの決定(これは私が話していたものです)。
3)通信コントローラー。
4)割り込み処理の追加機能。
OCW:
1)マスクIMRの登録の管理。
2)優先度管理。
3)コントローラーの一般的な制御。
初期化手順は次のとおりです。
Init_PIC:
mov al,11h;ICW1 – ,
out 20h,al;
out 0A0h,al;
mov al,20h;ICW2; ( ! RAM)
out 21h,al;
mov al,28h;
out 0A1h,al
mov al,04h;ICW3 – IRQ2
out 21h,al
mov al,02h
out 0A1h,al
mov al,11h;ICW4 – Pentium
out 21h,al
mov al,01h
out 0A1h,al
ret
次にIDTをビルドします。
IDT:
dd 0,0; 0
dd 0,0 ; 1
dd 0,0
dd 0,0 ; 3
;…. !
dd 0,0 ; 12
dw GP_handler and 0FFFFh,08h, 1000111000000000b, GP_handler shr 16 ; 13 #GP
dd 0,0 ; 14
;…. . dup' ,
; dd 0,0
dd 0,0 ; 30
dd 0,0 ; 31; Intel ;gate'
dw timer and 0FFFFh, 08h, 1000111000000000b, timer shr 16 ; IRQ 0 -
dw keyboard and 0FFFFh , 08h, 1000111000000000b, keyboard shr 16 ; IRQ 1 - - ;
dd 0,0;IRQ2
dd 0,0;IRQ3
dd 0,0;IRQ4
dd 0,0;IRQ5
dd 0,0;IRQ6
label IDT_size at $-IDT
IDTR dw IDT_size-1
dd IDT+10000h
だから、なぜここに書いて、そして、ここにいるのですか? -お願いします。 ここにトリックがあります:PMのすべてのコードを組織の背後に配置します(前の記事のコードを参照)。割り込みハンドラーを含みます...ここにトリックがあります:2つの半分から32ビットアドレスを作成し、ハンドラーのアドレスのみを渡します。 一般に、それについて魔法のようなものは何もありません、あなたはただこの二重の言葉にどんな意味があるかを理解する必要があります。
さて、問題は、なぜ多くのgateの場所に多くのゼロがあるのかということです。 理由は次のとおりです。控えめに言っても難しいので、すべてのハンドラーを記述する必要はありません。 割り込みゲートが見つからないため、プロセッサは悪名高いGeneral Protection Faultを生成するため、 #GPハンドラーを記述する方が簡単です。
ハードウェア割り込みハンドラーは好きなことを自由に行うことができますが、割り込みが存在する場合はフラグをクリアする必要があります-EOI信号を送信します- 割り込みの終了 (PICも構成しましたか?)
たとえば、次のように:
mov al, 20h
out 20h, al
簡単なタイマーハンドラを作成しましょう。
timer:
push ax
mov al, 20h
out 20h, al
pop ax
jmp int_EOI
int_EOI: ; Master' Slave' EOI
push ax
mov al,20h
out 20h,al
out 0a0h,al
pop ax
iretd ;
int_EOIは、すべての割り込みハンドラーに使用すると便利です。
さて、例外について少し説明します。 それらが発生すると、スタックは次のようになります。
ここでは、スタックからerror_codeをプッシュして操作します。 残りはiretdによって処理されます 。
ここで、コンテンツはリングを切り替えたかどうかに依存することに注意してください。
構造error_code:
どこで:
1)EXT-割り込みまたは例外ハンドラーで障害が発生したことを示します。
2)IDT-インストールされると、インデックスフィールドがIDTを参照することを示します。
3)TI-IDTビットが設定されていない場合、 GDTまたはLDTで一時中断する必要があることを示します。
4)セグメントセレクタインデックス-IDTの記述子番号( GDTおよびLDT )またはゲートを示します。
一般に、例外ハンドラインデックスは便利です。 私たちのクラフトが大きくなると、私たちにとって役立つでしょう。
それでは、コードを作成しましょう。 私はだまします:あなたに練習する機会を与えてください。 自分で作業コードを書きましょう。 関数はすでに作成されています。
いくつかの「ヒント」を示します。
1)org'aに対するIDTの位置(GDTで短縮)。
2)PMに移動する前にIDTRをダウンロードします。
3)割り込みハンドラーは組織にあります。
4)テキストビデオメモリは以前と同様にアクセスできます。
5)PMでPICを初期化した後、すべての割り込みを許可することを忘れないでください!
6)ページングはPMですでに初期化されています。
それでも、Claudiaの単純なハンドラーを作成します。
問題がある場合は、お問い合わせください。 次の投稿まで。
****修正****
set_pages関数は、8ではなく1つのテーブルしか記述されていないため、最初は間違って綴られていました。コードが修正されました。