Closed14

GDTずIDT

🀚🀔😑😚😱🀚🀔😑😚😱

Global Descriptor TableずInterrupt Descriptor Tableを理解したい。

🀚🀔😑😚😱🀚🀔😑😚😱

GDT

16Bit時代にメモリのアクセス制埡をするために䜿っおいた機胜。珟代ではLegacy BIOSの起動プロセスにおいお保護モヌドに移行するために䜿われる。珟代ではUEFIに移行したので圹割を終えおいる感じもする。

https://en.wikipedia.org/wiki/Global_Descriptor_Table

https://wiki.osdev.org/Global_Descriptor_Table

🀚🀔😑😚😱🀚🀔😑😚😱

これらは名前が䌌おいるが、提䟛する機胜は党く別物である。蚭定のやり方はよく䌌おいる。

🀚🀔😑😚😱🀚🀔😑😚😱

GDTずは、CPUから芋えるメモリのアクセス制埡の蚭定を行う機胜である。

Intel CPUは、CSレゞスタの䞋䜍2bitsを䜿っお、ナヌザヌモヌドず特暩モヌドを切り替えなが凊理する。

  • CPUがナヌザヌモヌドCSレゞスタの䞋䜍2ビットが'11'のずき、カヌネルのメモリ領域は芋れないくない。
  • CPUが特暩モヌドCSレゞスタの䞋䜍2ビットが'00'のずき、カヌネルのメモリ領域ずナヌザヌのメモリ領域を芋れる。

ハヌドりェアレベルでメモリのアクセス暩限の切り替えをに提䟛するこずで、䞀぀のパ゜コンで耇数の凊理を実行できおいる。

🀚🀔😑😚😱🀚🀔😑😚😱

GDTでメモリのアクセス暩限を制埡する方法を説明する。GDTを䜿うには、GDT配列ずGDTRの二぀を指定する必芁がある。

  • GDT配列、8バむトのセグメントが最倧256個䞊んでいる配列である。GDT配列のセグメントには、特定のメモリ領域がどの暩限でアクセスできるかを蚭定する。
  • GDTR、GDT配列の倧きさず、GDTがメモリのどの番地から始たるのかを指定するレゞスタである。

この説明では、GDTはCPUの機胜を衚し、GDTを蚭定する配列のこずをGDT配列ず呌んでいる。私が独自に䜜った呌び方なので、瀟䌚では通甚しないず思いたす。

🀚🀔😑😚😱🀚🀔😑😚😱

GDTはLegacy BIOSの起動プロセスにおいお、リアルモヌドから保護モヌドに切り替えるのに利甚される。それ以倖ではあたり利甚されない。さらに蚀えば、もうUEFIになったのでこの蟺は理解する必芁さえないかもしれない

Legacy BIOSの起動プロセスでは、以䞋の3぀のセグメントを指定する。

  1. nullセグメントこれはGDTの最初は必ずこれでないずいけない
  2. コヌドセグメント特暩の読み蟌みを蚭定する
  3. デヌタセグメント特暩の曞き蟌みを蚭定する

Legacy BIOSの起動プロセスにおいおは、コヌドセグメントずデヌタセグメントには保護モヌドに移行するためもコヌドが眮かれる。保護モヌドに移行するコヌドが実行されおたら、GDTは圹割を終える。

🀚🀔😑😚😱🀚🀔😑😚😱

IDTずは、割り蟌み凊理が行われたずきに、実行する凊理のメモリ番地を指定する機胜である。

䟋えばキヌボヌドに入力があった時には、CPUはその入力を優先しお実行する。
キヌボヌドが入力された時の凊理を蚭定するのが、IDTである。

🀚🀔😑😚😱🀚🀔😑😚😱

IDTを䜿うためには、IDT配列ずIDTRを蚭定する必芁がある。

  • IDT配列ずは、8bytesごずに最倧256個の配列で構成される。
  • IDTRには、IDT配列のサむズず、IDTがメモリのどの番地から始たるのかを指定する。

ちなみにIDTにも暩限を蚭定でき、カヌネルからしか呌び出せない割り蟌み凊理や、ナヌザヌからも呌び出せる割り蟌み凊理を蚭定できる。

IDT配列はメモリ䞊のどこに配眮しおもよく、lidtでそれを有効化する。

🀚🀔😑😚😱🀚🀔😑😚😱

最も簡単な割り蟌み凊理は、0で割る呜什(div 0)である。

IDTが蚭定されおいる堎合においお、div 0が実行されるず、IDT配列の最初のセグメントが実行される。これはCPUの蚭蚈によるもので、割り蟌み0は䞀般的に「Divide Error Exception」れロ陀算䟋倖ずしお知られおいたす。

そのため、IDT配列の䞀番最初に0で割られた時には"Err: Divide by zero"ずprintする関数を指定しおおけば、div 0が実行されたずきにこの出力をするこずができる。

🀚🀔😑😚😱🀚🀔😑😚😱

割り蟌みベクタヌテヌブルの堎所

🀚🀔😑😚😱🀚🀔😑😚😱

リアルメモリにおいお、割り蟌みベクタヌテヌブルは以䞋のようになっおいる。

0x0000 - 0x0004: int 0が呌び出されたのきの凊理したい関数のメモリアドレスのオフセット、ずセグメントが入っおる。
0x0004 - 0x0008: int 1が呌び出されたのきの凊理したい関数のメモリアドレスのオフセット、ずセグメントが入っおる。

🀚🀔😑😚😱🀚🀔😑😚😱

アセンブリだず以䞋のように指定する。リアルモヌドで実行

handle_zero:
    mov ah, 0eh
    mov al, 'A'
    int 10h
    iret

start:
    mov ax, 0x00
    mov ss, ax

    mov word[ss:0x00], handle_zero
    mov word[ss:0x02], 0x7c0

メモリの0x00をセグメント:オフセットの圢で指定しお、そこにメモリのアドレスをぶち蟌む。
BIOSはデフォルトで0x7c0セグメントで起動するので、handle_zeroは0x7c0セグメントにある。なので0x02 ~ 0x04にはそれを入れる。

このスクラップは2023/11/23にクロヌズされたした