インターネット&PC120%活用研究:PC活用編

時計の作成

1 プログラムの概要
それでは、今回は時計を作成してみます。
MS-DOSコマンドでいうと、TIMEやDATEのようなものです。
日付、時刻の表示と設定変更ができます。

(1) 使用するファンクションコール
日付の表示、時刻の表示、はMS-DOSファンクションコールの 2AH,2CH
日付の設定、時刻の設定は、2BH,2DHです

(2) プログラムの主要部分の概説
表示の方は、16進数バイナリデータ −−>10進数に変換 −−> アスキーコードに変換して表示
設定の方は、アスキーコードの入力データ (10進数として)−−> 16進数バイナリデータに変換
という作業がメインです。
コードの80%は、この作業の記述です。
上述の変換に関しては、
DEBUGで機械語作制その2アセンブラでCOMファイル作制 で多少説明して
いますので、なんのこっちゃ?という方は参考にして下さい。

BASICあたりで記述すると、 print time$ 1行程度の単純なプログラムですが、アセンブラで記述すると
上述のような変換のためのコードをえんえんと書くはめになります。とりあえず、コードを見てください。
こんな単純なプログラムにこなんに長たらしいコードが必要なんて「もう、ダメダメ」ですね。

2 コード

;システムクロック表示、設定プログラム ver0.1.1
;COPYRIGHTS  TSUYOSHI KASAI   1999

code segment
assume cs:code,ds:code,es:code,ss:code
ORG 100H

START:  ;スタート画面の表示
MOV AH,09H
MOV DX,OFFSET DATA
INT 21H

START1:  ;キー入力待ち
MOV AH, 06H   ;AH=6、DL=FFH キーボード入力、内部ループ無し
MOV DL, 0FFH   
INT 21H
JZ START1  ;キー入力なければSTART1に戻る

START2:   ;1..表示  2..時間設定  3..終了  押されたKEYに従って分岐
CMP AL, '1'
JZ TIMEREAD   ;時間表示ルーチンへ
CMP AL, '2'
JZ TIMESETK   ;時間設定ルーチンへ
CMP AL, '3'
JZ EXITK      ;終了へ
JMP START     ;それ以外のキーならSTARTへ

TIMESETK:     ;時間設定と終了ルーチンはショートジャンプでは届かないので、ジャンプし直し
JMP TIMESET
EXITK:
JMP EXIT

TIMEREAD:  ;時間表示(年月日)
MOV AH,2AH  ;システムクロック読み込み
INT 21H
MOV YEAR, CX
MOV MONTH,DH
MOV DATE, DL
MOV CL,0
MOV AX,1000   ;年を16進から10進に変換し、さらにアスキーコードにして表示
MOV DX,YEAR
CALL COUNT
ADD CL,30H
MOV Y1000,CL
MOV CL,0
MOV AX,100
CALL COUNT
ADD CL,30H
MOV Y100,CL
MOV CL,0
MOV AX,10
CALL COUNT
ADD CL,30H
MOV Y10,CL
ADD DL,30H
MOV Y1,DL
MOV CL,0
MOV DH,0
MOV DL,MONTH  ;月をアスキーコードに変換し表示
MOV AX,10
CALL COUNT
ADD CL, 30H
MOV M10,CL
ADD DL,30H
MOV M1,DL
MOV CL,0
MOV DL, DATE  ;日をアスキーコードに変換し表示
MOV AX,10
CALL COUNT
ADD CL, 30H
MOV D10,CL
ADD DL,30H
MOV D1,DL
MOV AH,9
MOV DX,OFFSET Y1000
INT 21H

SECONDREAD:  ;時間表示(時分秒)
MOV AH,2CH
INT 21H
MOV TIME, CH
MOV MINUTE, CL
MOV SECOND, DH
MOV CL,0
MOV AX,10
MOV DH,0
MOV DL,TIME
CALL COUNT
ADD CL,30H
MOV T10, CL
ADD DL,30H
MOV T1,DL
MOV CL,0
MOV DL,MINUTE
CALL COUNT
ADD CL,30H
MOV MN10, CL
ADD DL,30H
MOV MN1,DL
MOV CL,0
MOV DL,SECOND
CALL COUNT
ADD CL,30H
MOV S10,CL
ADD DL,30H
MOV S1,DL
MOV AH,9
MOV DX,OFFSET T10
INT 21H
MOV AH,6     ;キーボード入力
MOV DL,0FFH
INT 21H
JZ SECONDREAD  ;何かキー入力あればSTARTにもどる。なければ時間の表示を続行
MOV AH, 2
MOV DL, 0AH
INT 21H
JMP START

TIMESET:  ;時間の設定
MOV AH,9
MOV DX, OFFSET YEARSET
INT 21H
MOV AX, 0C0AH   ;AX=0C0AH  バッファを空にしてから、バッファに文字列入力
MOV DX, OFFSET YEARBUF   ;年の入力
INT 21H
MOV AH,2
MOV DL,0AH
INT 21H
MOV AL, YEARBUF[2]  ;年(アスキー文字列)を16進数に変換する
MOV BX, 1000
CALL SETCALC
MOV YEAR, AX
MOV AL, YEARBUF[3]
MOV BX,100
CALL SETCALC
ADD YEAR,AX
MOV AL, YEARBUF[4]
MOV BX,10
CALL SETCALC
ADD YEAR, AX
SUB YEARBUF[5], 30H
MOV DL,YEARBUF[5]
MOV DH,0
ADD YEAR, DX  
MOV AH,9
MOV DX,OFFSET MONTHSET
INT 21H
MOV AX, 0C0AH   ;月の入力
MOV DX, OFFSET MONTHBUF
INT 21H
MOV AH,2
MOV DL, 0AH
INT 21H
MOV AL, MONTHBUF[2]
MOV BX,10
CALL SETCALC
MOV MONTH, AL
SUB MONTHBUF[3],30H
MOV DL,MONTHBUF[3]
ADD MONTH, DL
MOV AH,9
MOV DX, OFFSET DATESET
INT 21H
MOV AX,0C0AH          ;日の入力
MOV DX, OFFSET DATEBUF
INT 21H
MOV AH, 2
MOV DL,0AH
INT 21H
MOV AL,DATEBUF[2]
MOV BX, 10
CALL SETCALC
MOV DATE, AL
SUB DATEBUF[3], 30H
MOV DL,DATEBUF[3]
ADD DATE, DL
MOV AH, 2BH      ;AH=2BH  日付のセット
MOV CX, YEAR
MOV DH,MONTH
MOV DL, DATE
INT 21H
CMP AL,0
JZ TIMESET1
MOV AH, 9
MOV DX, OFFSET FAIL1
INT 21H
JMP START

TIMESET1:      ; 時刻をセットする
MOV AH,9
MOV DX, OFFSET TIMESETW
INT 21H
MOV AX,0C0AH
MOV DX, OFFSET TIMEBUF
INT 21H
MOV AH,2
MOV DL, 0AH
INT 21H
MOV AL,TIMEBUF[2]
MOV BX, 10
CALL SETCALC
MOV TIME, AL
SUB TIMEBUF[3], 30H
MOV DL,TIMEBUF[3]
ADD TIME, DL
MOV AH,9
MOV DX, OFFSET MINUTESET
INT 21H
MOV AX,0C0AH
MOV DX, OFFSET MINUTEBUF
INT 21H
MOV AH,2
MOV DL,0AH
INT 21H
MOV AL,MINUTEBUF[2]
MOV BX, 10
CALL SETCALC
MOV MINUTE, AL
SUB MINUTEBUF[3], 30H
MOV DL,MINUTEBUF[3]
ADD MINUTE, DL
MOV AH,9
MOV DX, OFFSET SECONDSET
INT 21H
MOV AX,0C0AH
MOV DX, OFFSET SECONDBUF
INT 21H
MOV AH,2
MOV DL,0AH
INT 21H
MOV AL,SECONDBUF[2]
MOV BX, 10
CALL SETCALC
MOV SECOND, AL
SUB SECONDBUF[3], 30H
MOV DL,SECONDBUF[3]
ADD SECOND, DL
MOV AH, 2DH
MOV CH, TIME
MOV CL,MINUTE
MOV DH,SECOND
MOV DL,0
INT 21H
CMP AL, 0
JZ SETFINISH
MOV AH,9
MOV DX, OFFSET FAIL1
INT 21H
JMP START
 
SETFINISH:
MOV AH,9
MOV DX, OFFSET SETFINISHW
INT 21H
JMP START

EXIT:      ;終了
INT 20H

SETCALC:  ;アスキーコードを数値に変換
MOV AH,0
SUB AX, 30H
MUL BX
RET

COUNT:    ;それぞれの位(1の位、10の位・・1000の位)がいくつかをカウントする
CMP DX,AX
JB COUNTEND
INC CL     ;CL 各位の数値のカウント用
SUB DX,AX
JMP COUNT
COUNTEND:
RET

DATA DB 'COMPUTER SYSTEM CLOCK ver0.11',0DH,0AH,'<1--システムクロック ヒョウジ  2--システムクロックセット  3--END>',0DH,0AH
      DB '制作  Tsuyoshi KASAI',0DH,0AH,'$'
YEAR DW ?   ;表示用のデータ
MONTH DB ?
DATE DB ?
TIME DB ?
MINUTE DB ?
SECOND DB ?
Y1000 DB ?   ;Y1000 年の1000の位
Y100 DB ?
Y10 DB ?
Y1 DB ?
YY DB '/'
M10 DB ?
M1 DB ?
MMT DB '/'
D10 DB ?
D1 DB ?
DP DB 0DH,0AH,'$'
T10 DB ?
T1 DB ?
TT DB ':'
MN10 DB ?
MN1 DB ?
MM DB ':'
S10 DB ?
S1 DB ?
SDATA DB 0DH, '$'
YEARSET DB 'SYSTEM CLOCK SET (1ケタノスウジハ 01,02,03ノヨウニニュウリョクシテクダサイ)',0dh,0AH,'YEAR(1980-2079)--','$'
MONTHSET DB 'MONTH(01-12)--','$'
DATESET DB 'DATE(01-31)--','$'
TIMESETW DB 'TIME(00-23)--','$'
MINUTESET DB 'MINUTE(00-59)--','$'
SECONDSET DB 'SECOND(00-59)--','$'
YEARBUF DB 5,0,5 DUP(?)       ;設定用のデータ入力用バッファ
MONTHBUF DB 3,0,3 DUP(?)
DATEBUF DB 3,0,3 DUP(?)
TIMEBUF DB 3,0,3 DUP(?)
MINUTEBUF DB 3,0,3 DUP(?)
SECONDBUF DB 3,0,3 DUP(?)
FAIL1 DB 'FAILED  スウチガムコウデス',0DH,0AH,'$'
SETFINISHW DB 'セットカンリョウ',0DH,0AH,'$'



CODE ENDS
END START

実行画面の様子。

C:\newgame\ASM>clocka
COMPUTER SYSTEM CLOCK ver0.11
<1--システムクロック ヒョウジ 2--システムクロックセット 3--END>      
制作 Tsuyoshi KASAI
2001/05/02
23:36:24


コードは長たらしくて、ダメダメ感満点ですが、やってることは単純なので、じっくり見ればすぐ理解できる
と思います。

TopPage


inserted by FC2 system