BIOSコールのアセンブラのHello World

アセンブラのHello Worldについては、第5回ではLinux/FreeBSD/Solarisのシステムコールを利用したアセンブラ、第16回ではDOSのシステムコールを利用したアセンブラを取り上げましたが、今回第21回は、BIOSコールを利用するアセンブラです。

今回はまず、DOS上の*.com形式の実行ファイルの中からBIOSコールを行うようなアセンブラプログラムを作成します。そして最後に、OSを通さずに、ブートディスクのブートセクタに書き込んで、ブートローダのように、OS起動前に単独で動作するHello Worldのプログラムを作成します。

BIOSコール(1文字出力)を使う

まずはDOS上からBIOSコールを使ってみましょう。リスト1は、画面への1文字出力のBIOSコールを利用したプログラムです。

BIOSコールのためのソフトウェア割り込みには、複数の種類がありますが、画面出力関係には「int $0x10」を使います。alレジスタには出力文字を、ahにはBIOSコール番号を代入します。BIOSコールの後、プログラムの終了には第16回と同様に、DOSのシステムコールである「int $0x21」を利用しています。

なお、プログラムはgcc(GNU as)のアセンブラの文法で記述しており、リスト中の「.code16」という疑似命令は、以下のコードが16bitモードであることを指定するものです(第16回参照)。

リスト1 BIOSコールの1文字出力を利用(as_bios.s)

このプログラムは、x86系CPU版のLinuxまたはFreeBSD上のgccを使ってアセンブルします。出力はDOS上で実行可能な*.comファイル形式になります(実行例1)。コマンドラインの各オプションの意味については第16回を参照してください。

実行例1 gccでアセンブルして*.comファイルを作成

このファイル(as_bios.com)をDOS上に転送し、実行すると実行例2のようになります。

実行例2 DOS上でas_bios.comファイルを実行

BIOSコール(文字列出力)を使う

BIOSには、1文字ずつではなく、文字列を出力するBIOSコールも存在します。これを利用する場合は、あらかじめ画面のカーソル位置を取得しておく必要があります。この、カーソル位置の取得にもBIOSコールを使います(リスト2)。

文字列の出力では、axレジスタにBIOSコール番号、bxに文字属性、cxにバイト数、dxにカーソル座標、そしてbpに文字列の先頭アドレスを代入してBIOSコールを行います。

リスト2 BIOSコールの文字列出力を利用(as_bios2.s)

ブートセクタで動作するプログラム

BIOSコールだけを使ったプログラムは、フロッピーディスクなどのブートセクタに書き込んで、OSを起動せずに、自立したプログラムとして動作させることができます。

リスト3は、ブートセクタで動作するプログラムです。前掲の文字列を出力するBIOSコールを利用したプログラムをもとに、ブートセクタ上で動作するように修正を加えています。

ブートセクタのプログラムがロードされるメモリの絶対アドレスは、DOS上の0x100とは異なります。そこで、call命令を使って文字列の先頭アドレスを相対的に取得し、プログラムがどのアドレスにロードされても動作するように(ポジションインディペンデントなプログラムに)しています。具体的には、call命令を実行すると、call命令の直後のアドレスがリターンアドレスとしてスタックにpushされることを利用し、call命令の直後に文字列を配置し、call命令実行後にスタックの値をpopして、文字列の先頭アドレスを取得します。

このプログラムは、*.comファイルとして、DOS上でも実行可能なようにしてあります。このため、文字列の表示後、プログラム終了のDOSのシステムコールを実行します。DOS環境の場合は、ここでプログラムが終了します。ブートセクタとして実行された場合は、DOSのシステムコールは無視されて、次に進みます。

次に、キーボードからの読み込みのBIOSコールを実行します。ここで、何かキーボードを入力しないと先に進まない状態になります。その後、PCをリブートするBIOSコールを実行します。つまり、Hello World表示後、何かキーボードを入力するとリブートするという仕組みです。

さらに、このプログラム自体がBIOSによってブートセクタのプログラムとみなされるように、1セクタ(512バイト)の最後の2バイトの部分に、ブートセクタを表す0x55、0xaaというデータを書き込んでおきます。

リスト3 ブートセクタで動作するプログラム(as_bios3.s)

このプログラムは、アセンブルするとちょうど512バイトになるはずです。これは、前述のとおりas_bios3.comファイルとしてDOS上でも実行可能です。ブートセクタとして実行する場合は、「dd if=as_bios3.com of=/dev/fd0」のように、フロッピーディスクにイメージファイルとして書き込み、このディスクをドライブに入れてPCを起動すればOKです。実際のPCで試すのが困難な場合は、実行例3のように、PCエミュレータ(QEMU)を利用することもできます。QEMUは「qemu -fda as_bios3.com」で起動します。

実行例3 フロッピーディスクに書き込んでブート(エミュレータ利用)