雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。
6: 2005-07-23 (土) 19:37:40 ソース バックアップ No.6 を復元して編集 現: 2024-01-06 (土) 22:39:10 ソース 編集
Line 227: Line 227:
となります。・・・じゃ、論理セクター18は?っていうと、 となります。・・・じゃ、論理セクター18は?っていうと、
-|シリンダ| 1| (一番内側から2つ目)|+|シリンダ| 0| (一番内側)|
|セクタ| 1 | (詳しいことは省略。FDはちゃんとスタート位置があります。)| |セクタ| 1 | (詳しいことは省略。FDはちゃんとスタート位置があります。)|
-|ヘッド| 0 | (表面のこと)|+|ヘッド| 1 | (裏面のこと)|
と、こう続いていくわけです。もうお解りですね? (^^) と、こう続いていくわけです。もうお解りですね? (^^)
 +
 +同じくセクタ34はどこかっていうと、
 +
 +|シリンダ| 0| (一番内側)|
 +|セクタ| 18 | (詳しいことは省略。FDはちゃんとスタート位置があります。)|
 +|ヘッド| 1 | (裏面のこと)|
 +
 +じゃ、セクタ35は? というと・・・・
 +
 +|シリンダ| 1| (一番内側から2番目)|
 +|セクタ| 1 | (詳しいことは省略。FDはちゃんとスタート位置があります。)|
 +|ヘッド| 0 | (表面のこと)|
 +
 +とこう続いていくわけです。
 +
 +
 +
 +
 +
 +
 +
Line 276: Line 297:
 ;AXレジスタに開始番号、DXレジスタに終了番号を入れてコールすると読んでくれる  ;AXレジスタに開始番号、DXレジスタに終了番号を入れてコールすると読んでくれる
 ;なんてできないものかな・・・  ;なんてできないものかな・・・
 + 
 readsec1:  readsec1:
   PUSH  AX      ;AXの値を一旦バックアップ    PUSH  AX      ;AXの値を一旦バックアップ
 + 
   SUB    AX,DX    ;まず引き算して、AXに「個数」を入れる    SUB    AX,DX    ;まず引き算して、AXに「個数」を入れる
   MOV    CX,AX    ;CXレジスタに個数を入れる。(LOOP用のカウンタ)    MOV    CX,AX    ;CXレジスタに個数を入れる。(LOOP用のカウンタ)
 + 
   POP    AX      ;リストア    POP    AX      ;リストア
 + 
   ;ヘッダの値を計算する    ;ヘッダの値を計算する
   PUSH  AX      ;AXの値を一旦バックアップ    PUSH  AX      ;AXの値を一旦バックアップ
   DIV    AX,2    ;値を半分に割る。    DIV    AX,2    ;値を半分に割る。
   SUB    AX,1439  ;片面のセクタ数を引き算する。    SUB    AX,1439  ;片面のセクタ数を引き算する。
 + 
   ;・・・あれぇ。引き算の場合、マイナスになるような場合って・・・    ;・・・あれぇ。引き算の場合、マイナスになるような場合って・・・
Line 342: Line 363:
・・・・''ダメじゃん''・・・・ orz ・・・・''ダメじゃん''・・・・ orz
 +あー。むずかしく考えすぎたかもしれん。こうかな???
 + ;まず、hを求める
 + h = R ÷ (B ÷ 2) (余りは破棄)
 +・・・うん。これでよさそうだ。
 +で、これでhが求められると。
 + ;セクタも求める
 + s = R mod A + 1
 +・・・おぉ? これでいいのかな???
 +そうするってーと、シリンダはこうかな?
 + ;シリンダを求める
 + Q = B ÷ A ÷ 2   ;先に一面のシリンダ数を求める
 + c = R ÷ A - (Q * h)
 +うん!これでよさそうだぞ!
 +では、これらを実際のアセンブラにするってーと・・・・
 +まずはh。
 + ;h = R ÷ (B ÷ 2) (余りは破棄)だから、
 + 
 + PUSH    AX        ;AXには論理セクタ値が入っている。一旦バックアップ。
 + MOV    AX,2880  ;まず、AXに総セクタ数を入れる。
 + MOV    DX,2      ;DXレジスタに2を入れる
 + DIV    DX        ;AX ÷ DX を実行し、商をAXへ。余りをDXへ。
 + MOV    DX,AX    ;AXレジスタの値をDXにコピー
 + POP    AX        ;AXレジスタを元に戻す(論理セクタ値をセット)
 + PUSH    AX        ;もう一回バックアップ。
 + DIV    DX        ;これで、AXにはhの値が入っているはず。
 +ふむ・・・一旦DOSのDEBUGで確認してみよう。
 +・・・あっれえええええ??? 割り算(DIV)がどうしてもうまくいかないぞ??
 +なになに??? 「÷2」などは shr を使うのが早いと? じゃあこうか。
 + PUSH    AX        ;AXには論理セクタ値が入っている。一旦バックアップ。
 + MOV    AX,2880  ;まず、AXに総セクタ数を入れる。
 + SHR    AX,1      ;AX ÷ 2 を実行ししたのと同じ結果になる。
 + 
 + MOV    DX,AX    ;AXレジスタの値をDXにコピー
 + POP    AX        ;AXレジスタを元に戻す(論理セクタ値をセット)
 + PUSH    AX        ;もう一回バックアップ。
 + DIV    DX        ;これで、AXにはhの値が入っているはず。
 +うーーーむ・・・・ 16bit同士の割り算ってどうやったらいいんだ・・・
 +まいったなぁ。やっぱどっかメモリを使わないといけないのかなぁ。メモリは遅いからできれば使いたくない。・・・うーん。遅いっていえばそもそもDIV命令も評判がよくないなぁ。なんかうまい工夫ないもんかな。
 +こういう時って、CXやBX使っちゃいけないのかなぁ・・・・。例えば
 + PUSH    CX        ;CXレジスタの値をバックアップ
 + PUSH    AX        ;AXには論理セクタ値が入っている。一旦バックアップ。
 + MOV    AX,2880  ;まず、AXに総セクタ数を入れる。
 + SHR    AX,1      ;AX ÷ 2 を実行ししたのと同じ結果になる。
 + MOV    CX,AX    ;AXの内容をCXにコピー
 + 
 + POP    AX        ;AXの値を論理セクタに戻す
 + PUSH    AX        ;もう一回バックアップ
 + MOV    DX,0      ;これでDX:AXの値は32bitながら論理セクタ値となるはず。
 + 
 + DIV    CX        ;これで、AXにはhの値が入っているはず。
 + 
 + MOV    DX,AX    ;AXの値(h)をDXレジスタに移す
 + 
 + POP    AX    ;AXを初期値に戻す(論理セクター値)
 + POP    CX        ;CXを初期値に戻す
 + 
 + ;これで全て元通りで、かつ、DXにはhがセットされているはず。
 + 
 +うーむ。とりあえずは成功かな???
 +そんなわけで、[[こんなコード>IPL研究/コード1]]を妄想してみる。
 +debugコマンドで検証してみないと・・・
 +くそ!だめだ。割り算がメタメタだ。たぶん桁のせいだろう・・・
 +シリンダやセクタは同時に計算できないだろうか。
 +そんなわけで、[[こういうコード>IPL研究/コード2]]コードを書いてみた。
 +キタ━━━━━━(゚∀゚)━━━━━━!!!!!!!!
 +たぶん、これで大丈夫なはずだぞ!!!!!
 +''がーーーん!''
 +大勘違いしてたかも!?????。スタックって、メモリなの??????
 +それじゃ、どこかに適当にメモリを確保して書き込んだって同じじゃんかよ!!!
 +課題としては、「DIV命令は遅いので最小で」と、「メモリも遅いので出来るだけレジスタ内で完結」だなこりゃ。
 +コード2を見直そう・・・・・  orz
 +そんなわけで[[こんなコード>IPL研究/コード3]]になった。スタックの使用を最小限にして、割り算も減らした。OK。あとは、実際に繰り返しを行うプログラムを書いた時に、一回一回割り算をしなくてもいいように調整すると。
 +**どこに読み込むか?(格納メモリ番地) [#j27da20b]
 +上記のオベンキョでセクタの指定はできるようになったけど、読んだセクタはどこに格納したらいいでしょう???
 +まずはメモリマップを読んでお勉強
 +K氏のheboOSのIPLでは、読み込みは 0x800:0x100からスタートしている。このアドレスはなんだろう? (たぶんMS-DOSの実行ファイルとの互換だろうが・・・)
 +えーーーーっと・・・・・
 +8086時には、セグメント:オフセットという指定でアドレスを指定できるんだけど、本来は0hからいくらでもアドレスは増やせるはず。(たぶんプロテクトモードなんかではそうなんだろう。
 +セグメントの指定は5桁まで。で、オフセットは4桁まで。そう考えると、8086時には
 +0h 〜 FFFFFh までの空間がアクセル可能と。(5桁だから)
 +0h 〜 FFFFF までのアドレスにアクセルできる。で、この中に勝手に使っていい部分とそうでない部分があるはず。
 +heboOSで読み込んでいるアドレスは、0x800:0100 ってことは、
 +00800 + 0100 = 900番地
 +
 +からは、勝手に使っていい・・・・のかな?  いやたぶんそんなことはないはず。0〜900番地の間はどうなっているんだろう???
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +~
 +~
 +~
 +~
 +~
 +~
 +~
 +~
Line 388: Line 530:
---- ----
 +
 +~
 +~
 +~
 +~
 +~
 +~
 +~
 +~
 +