ザビタン開発日記
2009 | 01
2008 | 01 | 02 | 06 | 12
2007 | 10 | 11 | 12
11月 03 (土曜日) 2007
23:01
ファイル検索用APIを妄想
 
・・・っと思ったけど、オイラこんな心臓部いじるの初めて。
ちょこ〜っと実験ね。
4EのAPIが本当にちゃんと呼べるかどうか、簡単なコードで実験してみよう。

まずはconsole.c内ね。こんなのを置いてみました。

:
:
}

else if (edx == 0x4E) {
int i;
i = eax;
i = i++;
reg[7] = i;
}
:
:

そんでもって、まずはdir2.nas。とりあえずこんなのね。

[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "dir2.nas"]

GLOBAL _HariMain

[SECTION .text]

_HariMain:
MOV EDX,1 ;機能番号
MOV AL,'A' ;Aの文字コードをALにセット
INT 0x40 ;コール!

MOV EDX,4 ;アプリを終了
INT 0x40

コンパイルすると、ちゃんと動くね。dir2[Enter]で文字Aが表示される。
これをこうする。

_HariMain:

MOV EDX,0x4E ;機能番号
MOV EAX,0 ;一旦クリア
MOV AL,'A' ;Aの文字コードをALにセット
INT 0x40 ;コール!
;これで現在、ALには「B」の文字コードが入っているはず


MOV EDX,1
INT 0x40 ;コール!

MOV EDX,4 ;アプリを終了
INT 0x40

コンパイルして実行・・・・おぉぉ! Bが表示された。いいみたいだぞ!!

それじゃさっそく、さっき決めた仕様どおり動くように建て増しだ!
 
30日を過ぎたBlogにはコメントできません。

Referer  (2)
21:15
ファイル検索用APIを妄想
 
APIをちょっと妄想してみる。

 ・EDX  0x4E   ;機能番号。なんとなくMS-DOSと同じに・・・(^^;
 ・EAX       ;探したいファイル名が格納されているアドレス
 ・EBX       ;答えの文字列を格納したいアドレス
================= 戻り値 ==================================
・AL        ;0なら異常終了もしくは該当ファイルはない
 ・EBX       ;全部で何個あったか?

・・・わはははは! 我ながらなんつーショボイAPIだろう!(^^;
まーとにもかくにも、ここいらへんからはじめましょーか!

さて、APIを新しく搭載したい場合。
APIはINT 0x40 という割り込みによって動作する。
プログラムからINT 0x40が指示され、システムにこの割り込みが発生した場合には
なにをすればいいのか?(どこのプログラムを実行すればいいのか?)が
定義されているのがIDT。IDTテーブルを見ればなにをすればいいのか解る。
The-BBL(はりぼてOS)では、IDTテーブルの設定はbootpac.cからinit_gdtidt()関数を呼び出して行っていますね。
さて、では、init_gdtidt()関数はどこにあるのかというと・・・
dsctbl.cの中にあります。(こういうのはbootpac.h内を検索するとすぐ見つかるのだ!(^^) )
ふむふむ・・・先頭のほうにあるね。

set_gatedesc(idt + 0x40, (int) asm_hrb_api, 2 * 8, AR_INTGATE32 + 0x60);

これが、INT 0x40 (40番の割り込みが発生した)が実行するプログラム。なになに? asm_hrb_api とな?

さて、asm_hrb_api ってなんだろう? 関数にしてはおかしいぞ??
C言語の関数と感じが違いますよね?。これは関数というよりは、ある番地のラベルと考えたほうがピンときます。
アセンブラで書かれたプログラムのラベルなんですねぇ。
・・・じゃ、その、アセンブラで書かれた asm_hrb_api ってのはどこかというと・・・

あったあった。naskfunc.nas内にありますね?。
さて、なにやらややこしいアセンブラが書かれていますが、これはいったいなにを・・・?

実はここはこれからC言語で書かれた実行部分に対して、レジスタに設定された
各種パラメータを渡すための細工をしている部分なんですね。
コメント・そして途中でコールされている hrb_api。これが実際に
動作を行う、C言語で書かれている関数です。
さてーーー! じゃあ、実際に動作するというhrb_apiはどこにあるのかというと・・・


みーっけ! console.c内にあるのがそうです〜。
この中で、各機能番号ごとにelse ifしてプログラムを書いていると・・・

それではさっそく、ここに 4Eの分岐を書いて、内容を書いてみよう!
 
30日を過ぎたBlogにはコメントできません。

Referer  (1)
18:46
FDアクセス:dir2コマンド試作!(挫折率高し)
 
さてさて〜。
FDアクセス用の関数がだいぶ充実してきますた!
同時にちょっと飽きてきたってのもあるので(笑)
ここらで一発、dir2(実FD用dir)の搭載を遊んでみようかなと。(`・ω・´)

コマンドの増設は以前にもやりました。(memdump)
同じ手法で外部コマンドとして搭載してみようかなぁと。
それじゃぁまず・・・・typeコマンド用ディレクトリのコピーからじゃ〜!

・・・うーん。typeコマンドのソースをじっと眺めていたら思った。
「これはやっぱり、ファイル関係のAPIとして搭載すべきでは」
と。

例によってこういうのの設計なんてできないオイラ。こうなったら
MS-DOSアタリのファンクションコールを参考にしてみるか!


--------------- 二時間後 --------------------
・・・うーむ・・・だめだなぁ。
MS-DOSの場合、16ビットなのでいろいろと無理してる感じ。
これを無理に似せるのもなんだなぁ・・・

よっしゃわかった!とにもかくにもいっぺん、いいかげんてきとーに
やってみるか!
(どうせ今から頭絞ったってロクな仕様にならんだろうしね)
 
30日を過ぎたBlogにはコメントできません。

Referer  (1)
16:13
ポインタ変数の生死やいかに!?
 
C言語って、ある関数内で宣言・使用された変数ってその関数が終了orReturnすると
死んでしまうよね?

void main(){
int A; ←(1) たとえばAは0x1000番地に作られたとする
int B; ←(2) たとえばBは0x2000番地に作られたとする
A = 100;

B = test(A); ←(3) コール。でもまだ変数Cは存在しない

←(7) もうCは存在しない。0x3000も空き家になった。
その後は誰かが勝手に使うだろう・・・
}

int test(int hikisuu){
int C; ←(4) コールされて実行された!ここで初めて変数Cが誕生する。
じゃ、たとえばCは0x3000番地に作られたとする

C = C + 100; ←(5) Cは生きている。0x3000番地は使われている。
return C; ←(6) Cの内容はBにコピーされた。そしてその後、Cは死亡・・・
すなわち0x3000番地は誰も使っていないということになる
}


・・・これ、ポインタの場合ってどうなんだろう?? たとえば・・・

int main(){
int A; ←(1) 変数Aが作られた。じゃ、0x1000番地に作られたとする
int *B; ←(2) 「この時点」では、どこか占有されてるの?それとも??

B = 0x2000; ←(3) 「この時点」で初めて、変数*Bが誕生し、使ってる場所は0x2000になる
}

うーん。この(2)の時点がよくわからんなぁ・・・

もっと言うと、

------- A ----------- ------- B -----------
int main(){ int main(){
int A; int A;
int *B; int *B;
int *C;
int *D;
int *E;
int *F;
int *G;

B = 0x2000; B = 0x2000;
}

このようにA,B二つのソースを作ったとする。Bの場合、宣言はしたが
使っていないポインタが5つもある。
・・・これはなんらかの差になるのかなぁ・・・それとも???
 
●uchan@Guest -- 11/03 19:01
ポインタも実は4バイトの変数なので、int *B; も int B; もスタック上に4バイトの領域が確保されます。
●uchan@Guest -- 11/03 19:02
それから(3)の記述は大間違いでは?
●uchan@Guest -- 11/03 19:04
連投すみませんです。(3)は2つありますが、下の方のことです。
●hideyosi -- 11/04 00:37
ありゃ! 見落としてた。うっちゃん。毎度アドバイス感謝です。うーむ。そうなのかぁ・・・。そうすると、(3)の段階でもスタックに一箇所確保されている?? たとえば親関数(main)でポインタを宣言。子関数で構造体を作って値を入れた。で、そのアドレスを戻り値にしたりした場合、子関数内で作った変数本体はどうなるんだろうってのがちょっと疑問で。・・・だめか!ここじゃちょっと長くかけないや。近い内にWikiのほうにより詳しく書いてみよう

30日を過ぎたBlogにはコメントできません。

Referer  (6)
11:08
FDアクセス:バグあった!
 
えーーっと!
先日一区切りリリースしたVer.0.03にバグがありましたあぁぁ!

「1」や「3」を押すとアクセスするよね?
何回も何回も繰り返せる。で、「5」を押す。ちゃんとファイル名が出る。
・・・その後、他のコマンドが動作しなくなっちゃうことが判明!

コードを見直してもどうしても問題点はないし・・・なんだろう?
そこでいろいろと実験してたらわかりました。

これは「5」のように、複数のセクタを読み込んだ後に起こることが解りました。
(逆に言えば、「1」や「2」のように単セクタアクセスでは起きません。

コードを見直してみると・・・・・もしやこれ??


//DMAを開ける
fd_dma_set(0);

for (i = Rroots; i < Rroote; i++)
{
//論理セクタを物理セクタに変換
fd_r2b(i,parm);

//現在のシリンダと異なるならシーク
if ( nowC != parm[0] )
{
//シークコマンドを発行
err1 = fd_seek(parm[0],parm[1],900);
nowC = parm[0];
}

//セクタリード命令を発行
err1 = fd_read_sector(parm[0],parm[1],parm[2],900);

//ここにDMAからメモリに転送する命令
}
//DMAを閉じる
fd_dma_set(1);



これを

for (i = Rroots; i < Rroote; i++)
{
//論理セクタを物理セクタに変換
fd_r2b(i,parm);

//現在のシリンダと異なるならシーク
if ( nowC != parm[0] )
{
//シークコマンドを発行
err1 = fd_seek(parm[0],parm[1],900);
nowC = parm[0];
}

//DMAを開ける
fd_dma_set(0);

//セクタリード命令を発行
err1 = fd_read_sector(parm[0],parm[1],parm[2],900);

//DMAを閉じる
fd_dma_set(1);

こうしたら、この現象は起きなくなりました。

まあつまり、今までは

・DMAを開ける → 19〜32セクタを読む → DMAを閉じる

こういうコードだったのですが、セクタリード命令の前後にDMAの
開け閉めを置き、
その都度その都度、DMAを開け閉めするようにしました。
どうやらこれが正解のようです!!

これは今後の貴重なデータのなりそうだぞ!???
 
30日を過ぎたBlogにはコメントできません。
(1) 

PopnupBlog V3 Denali created by Bluemoon inc.