#1
by ユーマ » 5年前
最近OSのプログラミングをしていて、気になったことがあったので質問させていただきます。
質問の内容はIF(割り込み禁止フラグ)についてです。
自分はOS起動直後にCPUに対していろいろな設定をする際、割り込みが途中で入るのがまずいと思ったので初期化関数の先頭にcli命令を入れました。また、割り込みが入っても大丈夫というタイミングでsti命令を入れました。
普通はこれでいいと思うのですが、あるソースを読んでいるとまずフラグ全体をpushf命令からのpopl %eaxで取り出し、変数に保存した後(これをeflagsとします)cli命令で割り込みを禁止して、割り込み禁止の処理が終わった後にpushlでフラグを保存した変数(eflags)をプッシュして(このタイミングでもともとIFは0だったのでcliを解除する)、popfでフラグに格納していました。
(ここでいうフラグはCPUのフラグのことです。)
いまいちこれをする意味が分かりません。
自分も実際にcli,stiをやめてフラグをpopf,pushfするようにしてプログラムを書き、objdumpでファイルの大きさを確認したりしてみたのですがプログラムサイズがむしろ大きいくらいです。実行速度も大して変わらないでしょう。
割り込み禁止中にフラグを書き換えるような命令もないですし...
ちなみに有名なOS自作入門という本に書いてあったことなのですが...
一応プログラムを貼っておきます。色の設定をする関数です。
インライン使いすぎですね。読みにくくてごめんなさい。
コード:
void init_palette(){
int i;
int eflags;
unsigned char *rgb;
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00, /* 0:黒 */
0xff, 0x00, 0x00, /* 1:明るい赤 */
0x00, 0xff, 0x00, /* 2:明るい緑 */
0xff, 0xff, 0x00, /* 3:明るい黄色 */
0x00, 0x00, 0xff, /* 4:明るい青 */
0xff, 0x00, 0xff, /* 5:明るい紫 */
0x00, 0xff, 0xff, /* 6:明るい水色 */
0xff, 0xff, 0xff, /* 7:白 */
0xc6, 0xc6, 0xc6, /* 8:明るい灰色 */
0x84, 0x00, 0x00, /* 9:暗い赤 */
0x00, 0x84, 0x00, /* 10:暗い緑 */
0x84, 0x84, 0x00, /* 11:暗い黄色 */
0x00, 0x00, 0x84, /* 12:暗い青 */
0x84, 0x00, 0x84, /* 13:暗い紫 */
0x00, 0x84, 0x84, /* 14:暗い水色 */
0x84, 0x84, 0x84 /* 15:暗い灰色 */
};
rgb = table_rgb;
//このしたでpushfでフラグを変数eflagsにいれている
__asm__ __volatile__ ("pushf;"
"popl %%eax;"
"movl %%eax, %0;"
: "=r"(eflags)
:
: "%eax");
__asm__ __volatile__("cli");
//ここから
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c8), "i"(0)
: "%edx", "%al");
for(i = 0;i < 16;i++){
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[0]/4))
: "%edx", "%al");
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[1]/4))
: "%edx", "%al");
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[2]/4))
: "%edx", "%al");
rgb += 3;
}
//ここまではパレットの設定。
//__asm__ __volatile__("sti"); eflagsの操作を行わないならここでstiが入るだろう。
//この下で変数eflagsをpopfしている
__asm__ __volatile__("movl %0, %%eax;"
"pushl %%eax;"
"popf;"
:
: "g"(eflags)
: "%eax");
return;
}
どなたかお分かりの方がいらっしゃいましたらよろしくお願いいたします。
最近OSのプログラミングをしていて、気になったことがあったので質問させていただきます。
質問の内容はIF(割り込み禁止フラグ)についてです。
自分はOS起動直後にCPUに対していろいろな設定をする際、割り込みが途中で入るのがまずいと思ったので初期化関数の先頭にcli命令を入れました。また、割り込みが入っても大丈夫というタイミングでsti命令を入れました。
普通はこれでいいと思うのですが、あるソースを読んでいるとまずフラグ全体をpushf命令からのpopl %eaxで取り出し、変数に保存した後(これをeflagsとします)cli命令で割り込みを禁止して、割り込み禁止の処理が終わった後にpushlでフラグを保存した変数(eflags)をプッシュして(このタイミングでもともとIFは0だったのでcliを解除する)、popfでフラグに格納していました。
(ここでいうフラグはCPUのフラグのことです。)
いまいちこれをする意味が分かりません。
自分も実際にcli,stiをやめてフラグをpopf,pushfするようにしてプログラムを書き、objdumpでファイルの大きさを確認したりしてみたのですがプログラムサイズがむしろ大きいくらいです。実行速度も大して変わらないでしょう。
割り込み禁止中にフラグを書き換えるような命令もないですし...
ちなみに有名なOS自作入門という本に書いてあったことなのですが...
一応プログラムを貼っておきます。色の設定をする関数です。
インライン使いすぎですね。読みにくくてごめんなさい。
[code=C]
void init_palette(){
int i;
int eflags;
unsigned char *rgb;
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00, /* 0:黒 */
0xff, 0x00, 0x00, /* 1:明るい赤 */
0x00, 0xff, 0x00, /* 2:明るい緑 */
0xff, 0xff, 0x00, /* 3:明るい黄色 */
0x00, 0x00, 0xff, /* 4:明るい青 */
0xff, 0x00, 0xff, /* 5:明るい紫 */
0x00, 0xff, 0xff, /* 6:明るい水色 */
0xff, 0xff, 0xff, /* 7:白 */
0xc6, 0xc6, 0xc6, /* 8:明るい灰色 */
0x84, 0x00, 0x00, /* 9:暗い赤 */
0x00, 0x84, 0x00, /* 10:暗い緑 */
0x84, 0x84, 0x00, /* 11:暗い黄色 */
0x00, 0x00, 0x84, /* 12:暗い青 */
0x84, 0x00, 0x84, /* 13:暗い紫 */
0x00, 0x84, 0x84, /* 14:暗い水色 */
0x84, 0x84, 0x84 /* 15:暗い灰色 */
};
rgb = table_rgb;
//このしたでpushfでフラグを変数eflagsにいれている
__asm__ __volatile__ ("pushf;"
"popl %%eax;"
"movl %%eax, %0;"
: "=r"(eflags)
:
: "%eax");
__asm__ __volatile__("cli");
//ここから
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c8), "i"(0)
: "%edx", "%al");
for(i = 0;i < 16;i++){
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[0]/4))
: "%edx", "%al");
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[1]/4))
: "%edx", "%al");
__asm__ __volatile__ ("movl %0, %%edx;"
"movb %1, %%al;"
"outb %%al, %%dx;"
:
: "i"(0x000003c9), "r"((unsigned char)(rgb[2]/4))
: "%edx", "%al");
rgb += 3;
}
//ここまではパレットの設定。
//__asm__ __volatile__("sti"); eflagsの操作を行わないならここでstiが入るだろう。
//この下で変数eflagsをpopfしている
__asm__ __volatile__("movl %0, %%eax;"
"pushl %%eax;"
"popf;"
:
: "g"(eflags)
: "%eax");
return;
}
[/code]
どなたかお分かりの方がいらっしゃいましたらよろしくお願いいたします。