ストリング命令

アセンブラの入門書だと、ほとんどが
 2進法だ16進法だ、レジスタがどうとかこうとか
 あまりに基本的な解説が始まり、それで半分終わってしまう。(うんざりですね)
 ここでは、これらは飛ばします。 自分で勉強してください。


とても詳しくて、お勧めなHPとして
  http://hp.vector.co.jp/authors/VA000124/index.htm
 の中の 「アセンブラ入門」 とても良く出来てます。
 ここで、基礎は自習してください。



・・・・・・・・・・・・・・・・・・・・・・・・・・・


通常の?CPU 例えば Z80のような単純?な物と比較して
 x86系のCPUには ストリング命令 なる
 特殊な、そして便利な命令があります。
 いきなり、そこまで飛びます。

 
【基本】
 文字列を一度に書き込んだり、比較できる命令です。
 ① MOVES*,LODS*,STOS*,CMPS* INS* OUTS* の6種類の命令あり。
   *はB(バイト単位)、W(ワード)、D(ダブル・ワード)
 ② REP 命令を頭につけて繰り返し。(繰り返し回数はCXで指定)
 ③ CLD,STD命令で、プラス方向かマイナス方向かを事前に指定。
   (通常は CLD:プラス方向がほとんどでしょうが)
 ④ データ元(ソース)は DS:SI で示す。
   データ先(ディスティネーション)は ES:DI で示す。
 

【応用】
 ・REP MOVSB  で 文字列のコピーに使える。
 ・REP STOSB  で 文字列のクリアに使える。(全て ALの値で埋める)
 ・REPNE SCASB で 文字列内から文字を探すのに使える。
 ・REPNE CMPSB で 文字列同士の比較に使える。
 ・LODS は使い道がわからない???

【サンプル】
     cld             'DF=0 プラス方向
     mov   si,offset SOURCE 'ソースにある文字列を
     mov   di,offset DIST
     mov   cx,8       '8文字
     rep   movsb      'DISTへコピー
      :
SOURCE  db   "1234ABCD"
DIST   db   10 dup(0)


これを踏まえて、OSのコマンドを追加するに当たって
1文字づつ、アスキーコードで比較していたのでは、非常に判り辛いので
わかりやすく、文字列比較で行えるようにプログラムを変更する。


その上で、ファイルの内容を画面に表示する TYPEコマンドを
追加してみます。

COMファイルの構造

ここで、COMファイルの詳細を調べておきます。

 MS-DOSで実行可能な COMファイル は、
 64Kバイトまでのメモリしか使えないが、単純で
 セグメントを意識せずにプログラムが作れます。

 特徴としては、

  • 100hからロードされ、実行される。
  • 先頭部分に PSP*1 と呼ばれる領域がある。
  • セグメントはすべて同じ値。(これは当然ですね)
  • IPは 100h、SPは FFFEh で開始される。
  • スタックの最初(FFFEh,FFFFh)には0hが入っている。(RETすると0番地へ飛ぶ。)

完全に MS-DOS互換を目指すなら、
この PSP の中身をOSがセットしてあげないといけないって事です。

00、01h: INT20hのコード     CDh、20h
        (プログラムの終了処理。)
02,03h: 最大メモリセグメント  使えるメモリが7_FFFFhなら 8000hが入る。
   04h: 固定値 00h?
05〜09h: MSDOS.sysへのFAR CALL CP/Mとの互換のためのもの(使っていない?)

0A〜0Dh: プログラム終了アドレス。 (セグメント、オフセットの順)INT22のコピー 
0E〜11h: プログラム中断アドレス。   INT 23hのコピー。
12〜15h: 致命的エラーの処理アドレス。 INT 24hのコピー。

   16h〜   空き

2C、2Dh: 環境設定?(Path=文字等)へのセグメントアドレス。

   2Eh〜   空き

50,51h: INT21hのコード     CDh、21h
   52h: RETFのコード       CBh    
 プログラムから call 50h でも ファンクションコールができるようにしている。
 でも、ここも使っているプログラムはほとんど無いような気がする・・・

   53h〜   空き

5C〜6Bh: 第1FCB(16バイト) FCB*2は本来32バイト必要?のはず。
6C〜7Fh: 第2FCB(20バイト?) COMコマンドのパラメータ1,2のFCBがセットされる。

    80h: COMコマンドのパラメータの文字数
81h〜FFh: パラメータ文字列(0Dhで終端)

この PSPは EXEコマンドでも同じ構造で、プログラムの先頭に用意されます。

                                                                                                                  • -

*1:Program Segment Prefix: コマンドのパラメータをここを通じて渡している

*2:FCB:ファイル・コントロール・ブロック

Hello.com を動くようにする

yang20052005-06-08



MS-DOSでは INT 21h (AH=機能番号)
でほとんどの機能を実行しています。


初期の頃に作った
 Hello.com プログラムでは、
 
 INT 21h の内の

  機能番号  機能

  1. 09h  文字列の表示 (←DS:DX=表示文字ポインタ。'$'まで)
  2. 08h  キー入力  (→ALにキーコード、キー待ち、エコーなし)
  3. 4Ch  DOSへ戻る  (←AL DOSに戻すコード)

の 3つの機能を使っています。

これをまずは作ってみましょう。



同じ機能が BIOS にもあります。 手を抜いてこれを使ってしまいましょう。

 INT 16h が BIOSのキー入力。(AH=00h)

 戻り値: AL=アスキーコード、 AH=スキャンコード または
     AL=0 なら AH=拡張キーコード

 キーコードの詳細表は、OADGリファレンスに載ってます。





さて、先の HeboOSの ソースに少し手を加えて、再アセンブル
 FDにイメージを書き、さらに Hello.com をFDにコピーして
 起動します。
 >dir      で Helloファイルも見えますね。
 >Hello  で実行してみて下さい。


 MS-DOSプログラム Hello.com を動かしてみた証拠が上の写真です。
 (暗くて見えづらいですが・・・)


 その、ソースリストが ↓ です。
    id:yang2005:20050103


DOSやWin上で起動したのと同様、画面に”Hello!”と表示され、
何かキーを押すと、OSに戻ります。

ベクタMAP

 x86の(というか,AT互換機の)割り込みの資料はここを参考に!
    ↓
 http://www.asahi-net.or.jp/~WR7S-NKMR/BeOS/Documents/IRQ.html

ここなら、一覧表になってます。
    ↓
 http://www.ctyme.com/intr/int.htm


AT互換機は、
 INT 00h〜FFh の 256個に対して、幾つかはハードウェアに割り付けられています。

  • INT 00-07  例外ハンドラ (内 INT 02h は NMI)
  • INT 08   IRQ0   システムタイマ
  • INT 09   IRQ1   キーボード
  • INT 0A   IRQ2   次の割り込みコントローラ②へ接続される
  • INT 0B   IRQ3   シリアルポート(COM2/COM4)
  • INT 0C   IRQ4   シリアルポート(COM1/COM3)
  • INT 0D   IRQ5   ISAサウンドカードなど
  • INT 0E   IRQ6   フロッピーディスクコントローラ
  • INT 0F   IRQ7   パラレルポート


 ここが、ソフトウェアで利用可能。 INT 10h〜INT 6Fh

 その先頭の方は、BIOSで使われています。

    • INT 10   ディスプレィ入出力
    • INT 11   装置構成を読み取り
    • INT 12   記憶領域を読み取り
    • INT 13   ディスク入出力
    • INT 14   ASYNC入出力
    • INT 15   システムサービス
    • INT 16   キーボード
    • INT 17   プリンタ
    • INT 18-19  BIOS予約
      • INT 18h = 旧ROM-BASIC 起動(今はほとんど無い)
      • INT 19h = PCにリセットがかかる。
    • INT 1A   時刻
    • INT 1B   キーボードBREAKアドレス
    • INT 1C   タイマ
    • INT 1D-1F  BIOS予約


ただし、すでに BIOSで使っている所は、私たちが使えない。(使わない)

また、INT 21h以外でも、古いMS-DOSでは、次のINTも使ってしまってます。

    • INT 20   プログラムの終了。
    • INT 21   ●DOSのファンクションコール。
    • INT 22   終了アドレス
    • INT 23   CTRL+C抜け出しアドレス
    • INT 24   致命的エラー抜け出しアドレス
    • INT 25   ディスク・リード
    • INT 26   ディスク・ライト
    • INT 27   プログラム常駐
    • INT 28-2E  DOS/V
    • INT 2F   多重割り込み処理
    • INT 30-32  DOS/V用予約
    • INT 33   マウス
    • INT 34-3F  DOS/V用予約
  • INT 70   IRQ8   リアルタイムクロック
  • INT 71   IRQ9   割り込みコントローラ①(IRQ2)からのデージーチェーン。
  • INT 72   IRQ10
  • INT 73   IRQ11
  • INT 74   IRQ12   PS/2マウス
  • INT 75   IRQ13   数値演算コプロセッサ
  • INT 76   IRQ14   Primary IDEコントローラ
  • INT 77   IRQ15   Secondary IDEコントローラ

 この先も、ソフトウェアで利用可能。 INT 78h〜INT FFh

この資料から、INT 40h〜6Fh 当たりが安全に使えそうです。



●の部分、INT 21hを、
 DOSのファンクションコールと互換性のあるようにプログラムを作れば
 DOS用に作られた COMプログラム程度は動くようになるはずです。

 別に 自作の独自OS なんで、DOS互換にしなくてもいいんですが、
 画面表示やキー入力ぐらいは、互換性があったほうがデバッグしやすい。



 HeboOSでは、独自の INT 80hを使おうとしているので
  80h * 4 = 200h に オフセット、202h(から2バイト)にセグメントを
 書き込んでいます。


 INT 21hだと、
  21h * 4 = 084h に オフセット、086h(から2バイト)にセグメント
 を書けば良いはずです。


まずは、簡単な DOS互換のシステムコールを作って、
前に作ったDOS用のプログラム(ここ→ id:yang2005:20050526 )
  Hello.COM
が、手作りOSで、動くようにしてみましょう。

メモリMAP

PC/AT互換機(あえてDOS/V機とは呼ばない事!)の
 メモリMAPを調べてみます。

 OSDev で かなり詳細に調べてますね!
 ここはいつも参考になる。 素晴らしい!!
    ↓
 http://community.osdev.info/index.php?%28AT%29memorymap

 ちなみに、LINUXはこんな感じ。↓ (90000hから使っている?)
 http://www016.upp.so-net.ne.jp/e17/lb/setupAT.html


アドレス 内 容  説 明 
_0000h〜_03FFh割り込みベクタ4バイトづつ、(セグメント+オフセット)×256個。
_0400h〜_7BFFh30.72Kバイトの空き?使ってもいいのかな?
_7C00h〜_7DFFh512バイト。●ここにブートプログラムが読み込まれる。
_7E00h〜_7FFFh512バイト。ここもブート用に使って良いのでは?
_8000h〜9_FFFFh622.592Kバイト。ここが自由に使えるRAM領域(ここまでで640KB)
A_0000h〜B_FFFFh画面表示用ビデオRAM ここに書き込むと画面に表示される
C_0000h〜F_FFFFhビデオBIOSとか、いろいろここは使わない方が無難
10_0000h〜EF_FFFFh使えるRAMの可能性大。チェックしてから使用。(ここから先が、A20問題)
F0_0000h〜FF_FFFFh使えるない可能性あり。チェックしてから使用。
100_0000h〜無限大実装されている場合に限り・・・もう少し、大人になってから使ってみます。


ここで重要なのは、●の 7C00h〜 です。
ここに、FDやHDから、最初のプログラムが読み込まれ実行されるようです。

では、なぜ、こんな中途半端な 7C00h なんでしょう?

私が想像するに、

  最初にAT機を(のBIOSを)開発した技術者が、

   ① 1クラスタ(512バイト)もあれば、IPLローダぐらいは書けるだろう!

   ② それでも足りなくなるとか、1クラスタが1024になったら困るんで、

     もう1クラスタ(合計1024バイト)あいてれば、十分だろう?

   ③ IPLで OSを 0400h〜に読み込ませれば・・・

   ④ 0400h〜7BFFh(約30KB)もあれば、OSには十分なはず?
              ↑
          この考えが甘いな(笑)

   ⑤ そうすれば、7C00h〜7FFFhも OS用に使えて無駄にならないし、

    (最悪、OS用のスタックとして使ってもOK)

   ⑥ これなら、8000h〜は、アプリケーション用として、すっきり使える。

    (私って、天才!!)


 っと、こんな風に考えたんだと思います。


よって、そっくりそのまま踏襲しようと思います。

OSの容量が32Kバイトを超えないうちは・・・


 

への未練

TASMの使用を あきらめるには、いまひとつ
 踏ん切りがつかず、文法の違いを明らかにするためにも
 TASMで書き直してみました。

以下が、TASMのアセンブラでエラーなく通るソースです。

 しかし、日記に全ソースを公開するのは、無謀かな?

 とにかく、長いなー。

 何かボタンを押したら表示されるような機能が ハテナにないかな?
 ボタンを押したら、ダウンロードできる機能でもいいんだが・・・
      ↓
 あまりに、ソースが長くて、日記が見づらくなるんで、
 ここにリンクをはりました。 クリックすると見れます。

   id:yang2005:20050102