os自作入門」等といった本では、序盤の方に出てきます。GDTとIDTはosを動かす為に必要不可欠な設定項目です。よって、自作本と言った説明しながら作る本ではどうしてもはじめの方で説明しなければなりません。それ故に早い段階で躓いてしまう人もおおいでしょう。そこで、今回は簡単にGDTの概要だけを紹介したいと思います。GDTとはGDTとは、分かりやすくいえばメモリの整理整頓です。家では子供はお母さんに、遊んだ後はちゃんと整理整頓しなさいと言われますよね?それは、洋服を決められた場所に置かなければ後で探すのに困るからです。メモリも同じで、どのメモリにアクセスするか、どの番地にあるコードを実行するか等、整理整頓しなければならないのです。GDTの仕組みそれでは、GDTの仕組みの説明に入りたいと思います。とあるサイトから、以下の写真を借りて説明します。図1図1の写真には、左側にGDT、右側にメモリ(memory)と書かれてありますね。この図を本に例えれば分かりやすいでしょう。左がわのGDTは本を読む際の目次だと考えればいいでしょう。目次には、何ページ目にどんな内容が書いてあるか等を記載しています。図2図2の資料は(リンク先から借りた)wordでの目次の例です。ご覧の通り、目次には何ページ目に何の内容が書いてあるかを伝える役割を担ってます(図2で言うと、「目次作成にはwordが便利」と書かれた内容は3ページ目にあり、6ページ目にまとめがあります)。図1のGDTも同じ役割を担っているのです。図1の左のGDTと書かれたエリアの0x08番目(segment_discripter2)に、base_addrss=0x00000500と書かれてあります。これは、0x08番目の目次が指す場所は物理アドレスの0x500番地にある事を意味します。0x08のsegment_discripter2の矢印の指す場所はsegment2になってます。segment_discripter2はsegment2(0x500番地以降のアドレス)を参照する為の目次だったのです。追記1:図1には書いてありませんが、GDTにはメモリのサイズ(limit_size)を指定する必要があります。0x1500)となります。0x1500)のメモリを参照する際の目次だったという事です。segment_discripter3は0x10)になってるのは、base_addrssと追記1にあるlimit_sizeと権限(ここでは説明しない)を設定する必要があるからです。それらの情報は64ビットで表せます。番地は1ビット毎に8ビットのvalueを格納してるので、64➗8=8ビット毎にGDTのsegment_discripterを保存してるのが分かります。それでは、仕上げといきます。GDTを指定しただけでは具体的なメモリ番地にアクセスする事はできません。図1だと、base_addressから離れた、0x1500のアドレスのアドレスにアクセスできません。100p」と書いてあるからといって、「study」が100ページ丁度にある事なんてほぼありません。目次だけではなく、その「S」から数えた何ページ目にあるかを調べないといけないでしょう。そこで役に立つのがoffsetなのです。0x00001000と書かれた四角形があります。このオフセットは、「GDT(目次)」の指してるbase_addressから数えて何番目の番地にアクセスしたいかを表しています。0x1500)の範囲のアドレスを指してる事を追記1から指摘しました。具体的に0x1500番地のアドレスにアクセスしたいとしましょう。GDTだけでは、アクセスしたいメモリの範囲は分かっても、その範囲内のどこにアクセスすればいいかまでは分かりません。そこで、offsetで0x00001000と指定します。0x1500なので、0x1500にジャンプできるのです。0x08:0x00001000と指定すれば0x1500のアドレスにjmpできます。JMP命令にある0x08は、(図1参照)segment_discripterの開始アドレスが最初から数えて0x08番目にあるからです。GDTの設定それでは、設定に入りましょう。「30日で出来るos自作入門」のasmhead.nasから以下のコードを抜き出します(改変あり)。GDT0まずはGDTR0をご覧ください。1と書かれてありますね。GDT0と書かれています。これは、GDT(つまりメモリの目次)を格納してるのはGDTR0にあるという意味です。次はGDT0を見てみましょう。GDTを指定する際に最初の8番地分は0にするのが決まりみたいです。次の部分は以下のようになります。0xffff,0x0000,0x9200,0x00cf上記の最初の最初の0xffffはlimit_size(前節--GDTの原理を参照)を表しています。この番地の指す物理アドレスは0xffffビットの大きさになります。次の0x0000,0x9200,0x00cfの部分ですが、そこはbase_addressが2000000である事を表しています。実は、0x0000,0x0200,0x0000がベースアドレスをあらわしていて、その上にある0x0000,0x9000,0x00cfは読み書き可能を表しています。なるかは、とあるサイトにお任せします。読み書き可能(実行不可)というのは、mov命令でセグメントにデータいれたり、データを引き出す事ができるからです。実行不可の為にjmp命令で0x2000000番地に飛んでコードを実行する事はできません。0xffff,0x0000,0x9a28,0x0047そして、その下にある上のコマンドは、セグメントのベースアドレスが0x280000、サイズが0xffff、0x9aと0x0047なので(ここもとあるサイト参照)実行可能セグメントとなります。GDTR0を使えば指定した領域がGDTになるのです。0x08:0x00000000でコードセグメントのアドレスにジャンプできます。EAXとデータを格納する事ができます。IDTとはIDTとは、簡単に言えば外部装置との繋がりです(正確ではないのですが、最初はそう考えても構わないでしょう。詳しくはグーグルで割り込みと調べれば出てきます。キーボードからの入力は一旦IDTを経由(割り込み--詳しくはグーグル先生で)してからパソコンの中の送り込まれます。実は、IDTを使わなくてもアセンブラでキーボードの入力を受け付けられるのですが、IDTを経由した方が早くなります。パソコン内のタイマーもIDTを通して繋げる事ができるので、IDTでパソコンの時間を取得して、目覚まし時計が作れたりします。IDTの設定IDTの構文は以下のようになります。IDT0とある海外サイトからパクリました。1、ベースアドレスがIDT0です。次にIDT0を見てみましょう。0x0000IDT0_end:それぞれirq0、irq1、irq2と分かれています。それぞれ一番最初にisr0、isr1、isr2と書かれています。これらは実はc言語で言う関数ポインターみたいなものです。その下にある数々のパラメーターは、各種設定を表していますが、そこもグーグル先生にお預けします。実は、IDTの場合はハードウェアや使いたい性能がそれぞれ番地が決まっているのです。上のコードで言うと、例えば、irq0番はタイマー(時間関連)、irq1はキーボードに繋がってます。今回はキーボードを例に説明したいので、irq1を以下のように定義します。iret見てのとおり、test関数を呼び出すだけの関数です(test関数はc言語やなんやで自分で作ろう)。この関数はIDTの2番に登録されてる為、キーボードを押すと自動的に実行されます(前に実行してるプログラムは一次中断される)。最後のiretはretと同じ意味で、IDTに登録されてる関数はこちらを使います(一般のret命令は通用しない)。前回中断されたとこからプログラムがまた始まるのです。IDTを実行させるには、picを初期化する必要がありますが、話が長くなりますので「30日で出来るos自作入門」等の本を参照していただけたらなと思います。upLoginユーザーは見つかりませんでした。