その4 基本命令を使った簡単なプログラム1
今回は8086系の基本命令を使って簡単なプログラムを
アセンブラで書いてみます。
どうせならテキストで見かけるようなサンプル的なものではなく
実際に役にたつものを書いてみましょう。
1.機種判定プログラム
よくプログラムを書いているとPC9800系とDOS/V系で処理を分けたい場合があります。
特にハードウェアに密接に関わる部分の場合、PC9800系とDOS/V系では
まったく異なる部分がある為(例えばBIOSコールやI/Oポートの位置など)
現在PC9800系の上で動作しているのか、DOS/V系の上で動作しているのかを
見極める必要があります。(PC9800専用、DOS/V専用といってしまえばそれまでですが)
ここではソフトウェア内で現在動作しているPCの種類を調べるプログラムを書いてみます。
2.プログラムしよう
機種判定には数種類の方法がありますが今回はINT 1Ahを使ったものを書いてみます。
STACK SEGMENT STACK DW 32 DUP(0) STACK ENDS DATA SEGMENT MSG1 DB 0Dh,0Ah,'PC9800',0Dh,0Ah,'$' MSG2 DB 0Dh,0Ah,'DOS/V',0Dh,0Ah,'$' DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK START: MOV AX,DATA MOV DS,AX MOV AH,00h MOV CX,0FFFFh INT 1Ah CMP CX,0FFFFh JNE @F MOV DX,OFFSET MSG1 JMP DISP_MSG @@: MOV DX,OFFSET MSG2 DISP_MSG: MOV AH,09h INT 21H MOV AX,4C00h INT 21h CODE ENDS END START
とりあえずこれでPC9800系とDOS/V系の機種判別ができます。
上のプログラムを実行するとPC9800系なら「PC9800」と
DOS/V系なら「DOS/V」と表示されるはずです。
3.解説
上のプログラムの解説をします。
まず1番上の
STACK SEGMENT STACK DW 32 DUP(0) STACK ENDS
の部分はスタックの設定です。今回はあまり関係無いので無視しましょう。
ようは32WORD分(WORDは2BYTE)スタックを取っているだけです。(スタックについては後日説明予定)
次の
DATA SEGMENT MSG1 DB 0Dh,0Ah,'PC9800',0Dh,0Ah,'$' MSG2 DB 0Dh,0Ah,'DOS/V',0Dh,0Ah,'$' DATA ENDS
はデータセグメントの設定です。
DATAというセグメントのMSG1という場所にあるデータとMSG2という場所にあるデータを
設定しています。ちなみに0Dh,0Ahは改行を表しています。(ASCIIコード参照)
次の
CODE SEGMENT
から
CODE ENDS
までが実際に実行されるプログラム(コード)部分です。
ASSUME CS:CODE,DS:DATA,SS:STACK
はこのプログラムの各セグメントがどこから始まるか示しています。
CSはCODEからDSはDATAからSSはSTACKから始まるということです。
START: MOV AX,DATA MOV DS,AX
ここで何をやっているかというと実はCSとSSはプログラム開始時点で自動的に
CODEとSTACKの値が入るのですが、DSだけは自動的に入らないためセルフサービスで
DSにDATAの値を入れているわけです。それと一度AXに入れてからDSに入れているのは
DSやESなどのセグメントレジスタには直接値を入れられないからです。
MOV AH,00h MOV CX,0FFFFh INT 1Ah
はINT 1Ahを使う為の準備です。ところでここでINT 1Ahを使用して何をやろうとしているのかというと
DOS/V機でAHに00hをいれてINT 1Ahをコールした場合0時からの経過時間がCX:DXにかえってくるんですね。
PC9800ではこのINT 1Ahというのは普通使用されず何も起こらないわけです。
つまりCXに入れたFFFFhという値がDOS/V機では経過時間に書きかえられ、PC9800では変化しないわけです。
CMP CX,0FFFFh JNE @F MOV DX,OFFSET MSG1 JMP DISP_MSG @@: MOV DX,OFFSET MSG2
はINT 1Ahの結果によっての条件分岐を表しています。
JNEは直前の比較が等しくない場合分岐するという意味ですから。
INT 1AhのあとCXがFFFFhから変化した場合すなわちDOS/V機の場合分岐します。
@Fというのは次の@@:と言う意味です。ちなみに前の@@:は@Bです。
分岐しなかった場合DXにはMSG1のOFFSET値(場所)が入り分岐した場合DXにはMSG2のOFFSET(場所)が
入るわけです。
DISP_MSG: MOV AH,09h INT 21H
AHに09hを入れてINT 21hを実行するとDS:DXの場所にある文字列を「$」が現れるまで
画面に表示します。DXには先ほどの条件分岐でPC9800の場合はMSG1の場所が
DOS/Vの場合はMSG2の場所が入っているのでそれぞれ機種にあったメッセージが表示されるわけです。
MOV AX,4C00h INT 21h
AHに4Chを入れてINT 21hを実行するとプログラムの終了処理が行われます。
つまりこれでプログラムは終わりということです。
END START
1番最後にあるこの文はここがプログラムの最後でありSTARTという場所からプログラムが
始まるといった意味と思ってください。
PCの機種判別はわかってしまえば簡単ですが見つけるまでが結構面倒なんですね
今回のプログラムでだいたいの機種判別ができますのでいろいろ使い道があると思います。
次回も引き続きアセンブラの基本について解説する予定です。