はりぼて日記
2007 | 01 | 02 | 03 | 04 | 05 | 07 | 08 | 10
2006 | 11 | 12
1月 18 (木曜日) 2007
22:56
ちょっと脱線(LDTがわからん)
 
まずはGDTをもう一度復習。P110から読み直し!



GDTはセグメントの情報を管理する表。で、メモリに存在する。GDTはかならずセットしないとセグメントが使えないのでこまるが、GDTをどこから始めるのかは勝手に決めてよいようだ。(GDTRに書きこめばよいらしい。)



for (i = 0; i < 8192; i++) {

set_segmdesc(gdt + i, 0, 0, 0);

}



ええと、これが約8000個分あるGDTの各行の設定のパターン。(ここではforで回して、一旦ぜーんぶのGDTに0を入れている。



   set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);

   set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);



このパターンで個々のGDTをセットアップしている。細かく言えば、



set_segmdesc(gdt + GDT番号, 大きさ, 開始番地, 属性);



と、こうなる。ちなみに属性は少々ややこしいが、P126のカッコ内をとりあえず下二桁にあてはめればいいようだ。



なので、上記 GDT1番、GDT2番はそれぞれ、「92なので、システム専用の読み書き可能セグメント。実行はできない」「9aなので、システム専用の実行可能セグメント。読み込みもOK。書き込みはできない」と、こうなる。



P292。

マルチタスクする場合、切り替える前のレジスタの情報全てを一旦どこかに退避させ、別のタスクに切り替える。(ちょうどレジスタを丸ごとバックアップするようなもの)

その退避場所(104バイト必要)をTSSという。TSSはプログラム上で勝手に適当な変数を作ってやるのではない。セグメントの一種としてあつかう。なので、上記のGDTの設定と同じようにしないといけない。(大きさと属性だけが決まっている。あとは適当でいい)



 set_segmdesc(gdt + 3, 103, (int) &tss_a,AR_TSS32);



(AR_TSS32は0x0089のこと。とにかくこの数値を当て込むと、そのセグメントはTSSという特殊なセグメントになる)



P312から汎用なタスク操作のプログラムが始まっている。

これを見ると、「task」という構造体を用意し、これがおのおののタスクに必要なデータを管理and記憶していることがわかる。



task->sel  簡単に言えば、GDTの何番のセグメントを使うのかという情報。

task->flags  使用中かそうでないかのフラグ

task->tss  このタスクが使うtss構造体





task_init 関数を使い、これらを初期化している。初期化はいったいなにをやっているかというと



for (i = 0; i < MAX_TASKS; i++) {

taskctl->tasks0[i].flags = 0;

taskctl->tasks0[i].sel = (TASK_GDT0 + i) * 8;

set_segmdesc(gdt + TASK_GDT0 + i, 103, (int) &taskctl->tasks0[i].tss, AR_TSS32);

}





























・・・・あーーー。だめだぁ・・・わっかんねぇ〜・・・・



今日はもう寝る!

 
name: @Guest  Comment:
Referer  (8)
21:26
27日目
 
27日目



[1]

なるほど。納得〜。



[2]

え〜? これいいのかな?。 いや、プログラムはわかるけど、こういう仕様でええんかなぁ・・・。だってWinのコンソールもこういうふうにはなってないような・・・??



[3]

むむむ? ほんとだ。いかれちゃった。



・・・うーむ。なるほどぉ。OSのガードが固いので、アプリのほうをおかしくしちゃうと。考えたもんだなぁ。(コードの意味もわかるぞ。)



[4]

んんん?LDT?。なんだそれ?

えーー! こりゃ便利! タスクごとにGDTを設置できるの?(子GDTみたいな感じか!)



あっれ〜?。わっかんねぇなぁ。ええと・・・どういうことなのかな???



LDTがメモリのどこにあるのかはGDTの中にLDTセグメントを作って教えてあげます



・・・これの意味がどうしてもわからんなぁ・・・。コードから読み取らないとわからないかな???

 
name: @Guest  Comment:
18:04
26日目2
 
26日目



[4]

・・・あれぇぇぇ? ここ、どうも意味がわからないなぁ。いや、FIFOが空っぽになってから書き換えるってのは意味解るけど、そうなるとマウスが止まるまで再描画をしないっていう理屈にならない??

(でも実際は、移動中もウインドゥがついてくるわけで・・・)



わからーーん!





[5]〜[8]

うーむ。task_aがまだ動いていたとは!

しかし、逆にいえば、こういう内部での処理をするタスク(監視タスクとでもいうのかな?)が必要ということだよね??



[9]

ツルツル〜



[10]

むむむ! また失敗オチ!?

 
name: @Guest  Comment:
17:34
26日目
 
26日目



[1]

なっるほどなぁ。たしかこういうテクニックって前にもどこかでやったよね?。

一見、コードが長くなるように見えなくもないけど、無駄なif(しかもforのせいで数万回分の)がなくなるので相当変化があると思われる。



[2]〜[3]

ふむ。これはつまり、こういうことだよね??



普通に8バイト書き込む



               ┌──────┐

MOV [0x00001000],0x11  →│ 0x11   │0x00001000

               ├──────┤

MOV [0x00001001],0x12  →│ 0x12   │

               ├──────┤

MOV [0x00001002],0x13  →│ 0x13   │

               ├──────┤

MOV [0x00001003],0x14  →│ 0x14   │ :

               ├──────┤ :

MOV [0x00001004],0x15  →│ 0x15   │ :

               ├──────┤

MOV [0x00001005],0x16  →│ 0x16   │

               ├──────┤

MOV [0x00001006],0x17  →│ 0x17   │

               ├──────┤

MOV [0x00001007],0x18  →│ 0x18   │0x00001007

               └──────┘



※ 合計8回もMOV命令を実行しないといけない。

=================================================================

32bit命令で8バイト書き込む



                  ┌──────┐

MOV [0x00001000],0x14131211  →│ 0x11   │0x00001000

                  ├──────┤

                 →│ 0x12   │

                  ├──────┤

                 →│ 0x13   │

                  ├──────┤

                  │ 0x14   │ :

                  ├──────┤ :

MOV [0x00001004],0x1817161515 →│ 0x15   │ :

                  ├──────┤

                →│ 0x16   │

                  ├──────┤

                 →│ 0x17   │

                  ├──────┤

                 →│ 0x18   │0x00001007

                  └──────┘



※ たった二回のMOV命令の実行で同じ結果になる。







むむむ・・・こりゃややこしいな。でもやっていることはわかるな。







 
name: @Guest  Comment:
Referer  (4)
13:57
25日目2
 
25日目



[2]〜[3]

え”え”え”??

なんだこれ? gb2palはパズルだと? わっかんねぇぇぇ。

たしかにどう見ても、これだけでできるとは思えないんだけどなぁ。

くやしいな。いつか挑戦してやるぞ! <え!今やらないの?



[4]

ツルツル〜っと。



[5]

他コンソール化。ふむ。まずはとりあえず配列タイプへ改造と。



[6]

なるほどなぁ。確かに格納変数一個しかないもんな。でも、これをどうやって振り分ける??。



なるほどぉぉぉ。

タスクの構造体というより、おのおののセグメント内の番地に担当させるっていうほうが適当かもな??



[7]

ん??? え?あれ? そうだっけ??

・・・あー!ほんとだ!確かにそうだね。

しかしそうなると、セグメント番号もまた、SHEETやタスクのように管理する必要があるよね? (わー!ややこしい!)



うむむ。すでの持っている数値(task->sel)に簡単な計算をして出てくる数値を使おうと・・・。なるほどなるほど。(でもあとで当て込みの位置が動いたりしたらややこしそうだかな・・・)



[8]

オケオケ。そのとおりだね。ツルツル〜



[9]〜[10]

ん〜と。これはとりあえず暫定処置だよね?このままじゃFIFOも二個しか初期化してないわけだから。(たぶんタスク起動させる段階でこの初期化がなされるように変更される悪寒)
 
name: @Guest  Comment:
1月 17 (水曜日) 2007
23:57
25日目
 
25日目



[1]

あははは!こりゃ楽しい!

(・・・つか、Beepってこんなんでこういう音出せるのね・・・)



時に、本編と関係ないんだけど、本にはqumeではBEEPのエミュが不十分で音が鳴らないと。(実際そうだね)

かといって、実機はちと面倒。で、VMWareで試してみました。これはダメ。で、MSのVertualPC2004(今はフリー化されてる)でやってみたら鳴りました〜!

qumeも最新のやつだとBEEPが鳴るとあっきーさんに教えてもらったのですが、どうも設定がまずいのか、ウチでは鳴りません・・・



 
name: @Guest  Comment:
Referer  (1)
23:13
24日目2
 
24日目



[5]〜[6]

うーむ。ウィンドゥの切り替え。

だんだん各関数が複雑になってきたなぁ。これ、逆にこのソースだけ読んで、ピピピッと解る人いるのかな?

(悪い言い方だけど、これらの関数って建て増し建て増しだよね?でも逆に、建て増しだから意味を追えるってとこあるし・・・)



[7]〜[8]

んん? いや、本編とはまったく関係ないんだけど、この「謎文字」がどこから来たのかなぁと思って。(^^

 
name: @Guest  Comment:
21:11
24日目
 
24日目



[1]〜[2]

うむ〜。ここはめずらしく、何一つむずかしくない〜♪



[3]

ふむむ。なまいきだけど、ここらへんって、わりとベタな方法使ってますね?。(まあわざとなんだろうけど)

なんかチューンできそうな悪寒・・・



[4]

わかる。わかるぞ〜! (^^



 
name: @Guest  Comment:
16:13
23日目2
 
23日目



[2]〜[8]

わーい! たのしーーー!



しかし、ここで再び課題に直面。やっぱりアプリが終了するとメモリは開放されているっぽい。しかし、その処理がどこで、どういう理屈なのかがわからないor読み落とししているらしい。あとで復習するとき忘れないようにここに赤で記載
 
name: @Guest  Comment:
15:24
23日目
 
23日目



[1]

んんん? 例外になる?? え?だって、memman_allocするでしょ?。その番地を返す。アプリのデータセグメントの外と。だったらそこの番地つーか、DSを書き換えて・・・あああ! ほんとだ!こりゃマズイじゃん!



うーーーん・・・どうもよくわからないなぁ。ここ。

まず、いままでのプログラムとmallocの違いは





 いままでのプログラムA         malloc導入のプログラムB

0x00 ┌─────────────┐    ┌─────────────┐0x00

   │xxxしろ          │    │xxxしろ          │

   ├─────────────┤    ├─────────────┤

   │xxとxxxを計算しろ     │    │xxとxxxを計算しろ │

   ├─────────────┤     ├─────────────┤

   │xxを描画しろ        │    │xxを描画しろ      │

   ├─────────────┤    ├─────────────┤

   │変数のためメモリを確保しろ│ ⇒  │mallocでメモリもらってこい│

   ├─────────────┤    ├─────────────┤

   │  ・・・ここは変数a  │    │変数aにxxxしろ │

   ├─────────────┤    ├─────────────┤

   │   ・・・ここは変数b  │    │プログラム終了しろ │

   ├─────────────┤    └─────────────┘0x06  

   │   ・・・ここは変数c  │  

   ├─────────────┤       アプリのサイズは6kb

   │変数aにxxxしろ  │  

   ├─────────────┤  

   │プログラム終了しろ    │  

0x09 └─────────────┘  



   アプリのサイズは9kb





とまあ、こういう理屈になるよね?。なので、mallocを導入したほうはプログラムの実行ファイルが小さくなると。

(ただ、mallocのほうでも実行時には同じ数だけ変数を要求すれば「メモリを食う大きさ」は同じになるという感じかな)



うーん。つまりこういうことか???

 ・プログラムA。命令+変数に必要なメモリで9kb

 ・ファイルが9kb。読み込まれると9kbのメモリに収まる

 ・「メモリ内で」9kbを食っている。命令+変数に必要なメモリ



これだと無駄っぽいので

 ・プログラムB。命令のみ。

 ・ファイルが6kb。しかし読み込まれる時、9kbのメモリを確保する

 ・「メモリ内では」9kbを食っている。命令+変数に必要なメモリ



こういう理解でいいのかなぁ・・・?

 
name: @Guest  Comment:
Referer  (1)
1 2 3 4 5 6 7 (8) 9 10 11 12 13 14 » 

PopnupBlog V3 Denali created by Bluemoon inc.