asm.h #define SEG_ASM(type,base,lim)
トップページ
jupiteroak.hatenablog.com
asm.h
https://github.com/mit-pdos/xv6-public/blob/master/asm.h#L11
#define SEG_ASM(type,base,lim) \ .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
SEG_ASMマクロは、アセンブリ言語のソースコードにおいて、セグメントディスクリプタに値を設定するために使用されます。
引数 type
セグメントの種類を指定する値(4bit)です。
typeはセグメントディスクリプタのbit43-40に格納されます。
引数 base
セグメントのベースアドレス(32bit)となる値です。
ベースアドレスの上位8bitはセグメントディスクリプタのbit63-56に格納され、ベースアドレスの下位24bitはセグメントディスクリプタのbit39-16に格納されます。
引き数 lim
セグメントのサイズを指定するリミット値(セグメントのサイズ-1)を含んだ値(32bit)です。
limの値(32bit)のうち上位20bitをリミット値として利用します。
リミット値の上位4bitはセグメントディスクリプタのbit51-48に格納され、リミット値の下位16bitはセグメントディスクリプタのbit15-0に格納されます。
処理の内容
- 前提
- セグメントディスクリプタのbit15-0にリミット値を設定する
- セグメントディスクリプタのbit39-16にセグメントのベースアドレスを設定する
- セグメントディスクリプタのbit47-40に値を設定する
- セグメントディスクリプタのbit55-48に値を設定する
- セグメントディスクリプタのbit63-56にセグメントのベースアドレスを設定する
前提
説明の都合上、便宜的にマクロを書き換えます。
#define SEG_ASM(type,base,lim) \ .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
↓
#define SEG_ASM(type,base,lim) .word (((lim) >> 12) & 0xffff); .word ((base) & 0xffff); .byte (((base) >> 16) & 0xff); .byte (0x90 | (type)); .byte (0xC0 | (((lim) >> 28) & 0xf)); .byte (((base) >> 24) & 0xff);
セグメントディスクリプタのbit15-0にリミット値を設定する
.word (((lim) >> 12) & 0xffff);
リミット値の下位16bitをセグメントディスクリプタのbit15-0に設定します。
limの値(32bit)を12bit右シフト演算し0xffffでマスク処理することにより、リミット値の下位16bitを取得しています。
.wordは、アセンブリ言語のソースコードで使用される疑似命令で、(((lim) >> 12) & 0xffff)の値が2バイトであることを示しています。
セグメントディスクリプタのbit39-16にセグメントのベースアドレスを設定する
.word ((base) & 0xffff); .byte (((base) >> 16) & 0xff);
セグメントのベースアドレス下位24bitをセグメントディスクリプタのbit39-16に設定します。
baseの値(32bit)を0xffffでマスク処理することによりセグメントのベースアドレスbit15-0を取得し、 baseの値(32bit)を16bit右シフト演算し0xffでマスク処理することによりセグメントのベースアドレスbit23-16を取得しています。
.wordは、アセンブリ言語のソースコードで使用される疑似命令で、((base) & 0xffff)の値が2バイトであることを示しています。
.byteは、アセンブリ言語のソースコードで使用される疑似命令で、(((base) >> 16) & 0xff))の値が1バイトであることを示しています。
セグメントディスクリプタのbit47-40に値を設定する
byte (0x90 | (type));
0x90とtypeの値をビット和演算した結果をセグメントディスクリプタのbit47-40に設定します。
typeの値(4bit)はそのままセグメントディスクリプタのbit43-40に格納され、0x90(1001 0000)の上位4bitである1、00、1が、セグメントディスクリプタのbit47( Pフラグ)、bit46-45 (DPL)、bit44 (Sフラグ)にそれぞれ格納されます。
.byteは、アセンブリ言語のソースコードで使用される疑似命令で、(0x90 | (type))の値が1バイトであることを示しています。
bit43-40(type)
セグメントの種類を指定するフィールドです。
typeの値とセグメントの種類の対応例を以下に示します。
typeの値 | セグメントの種類 |
---|---|
0010 | 読み書き可能データセグメント |
1010 | 実行と読み出し可能コードセグメント |
bit44(Sフラグ)
セグメントディスクリプタでは常に1の値です。
bit46-45(DPL)
セグメントへのアクセスに必要なCPUの特権レベルを指定するフィールドです。
この値が00の時は、セグメントへのアクセスに必要なCPUの特権レベルがカーネルモードであることを示しています。
bit47(Pフラグ)
セグメントがメモリ上に存在するかしないかを示すフィールドです。
この値が1の時は、セグメントがメモリ上に常に存在することを示しています。
セグメントディスクリプタのbit55-48に値を設定する
.byte (0xC0 | (((lim) >> 28) & 0xf));
0xC0と((lim >> 28) & 0xf)をビット和演算した結果をセグメントディスクリプタのbit55-48に設定します。
)(lim >> 28) & 0xf)の値(4bit)はそのままセグメントディスクリプタのbit51-48に格納され、0xC0(1100 0000)の上位4bitである1、1、0、0が、セグメントディスクリプタのbit55(Gフラグ)、bit54(Dフラグ)、bit53(Lフラグ)、bit52(AVL)にそれぞれ格納されます。
.byteは、アセンブリ言語のソースコードで使用される疑似命令で、(0xC0 | (((lim) >> 28) & 0xf)の値が1バイトであることを示しています。
bit51-48(リミット値)
リミット値の上位4bitをセグメントディスクリプタのbit51-48に設定します。
limの値(32bit)を28bit右シフト演算し0xfでマスク処理することにより、リミット値の上位4bitを取得しています。
bit52(AVL)
常に0の値です。
bit53(Lフラグ)
常に0の値です。
bit54(Dフラグ)
セグメントで使用されるアドレスサイズやデータサイズを指定するフラグです。
この値が1の時は、セグメントで使用されるアドレスサイズやデータサイズが32bitであることを示しています。
bit55(Gフラグ)
リミット値の単位を指定するフラグです。
この値が1の時は、リミット値の単位がページ(4KB)であることを示しています。