;######################################################################### ;## DELAY ルーチン ## ;##  指定された時間だけ待つルーチン(単位ms) ## ;## ## ;## 基準となるCPUクロック ## ;## V30:10MHZ (PC-9801UV21) ## ;## 286:12MHZ (PC-9801RX2) ## ;## 386:20MHZ (PC-98RL N-MODE) ## ;## NPC:33MHZ (PC-H98 Model70) ## ;## ## ;##  注:現行機の場合、基準クロック以外では、多少誤差がでます ## ;## ## ;## 入力:CXに 待ち時間(ms)をいれる。 ## ;## 出力:なし ## ;## 破壊するレジスタ:CX、フラグ ## ;## ## ;##---------------------------------------------------------------------## ;##  変更履歴 ## ;## DATE | Ver | ## ;## -------------------------------------------------------------- ## ;## 90-04-24 | 1.00 | Original ## ;## ## ;######################################################################### ;---------------------- LOOP回数 -------------------------------------- _V30_DELAY_ EQU 550 ;V30 調整はここでやって _286_DELAY_ EQU 1070 ;286 ください _386_DELAY_ EQU 1600 ;386  _DELAY_COUNT_ EQU 307 ;NPC ;-------------------------------------------------------------------------- ;######################################################################## ;# データ部 # ;######################################################################## ;;;;; _BIOS_FLAG1_ DB 0 ;[0:458H]の内容 (del 90.10.6) ;;;;; _BIOS_FLAG2_ DB 0 ;[0:480H]の内容 (del 90.10.6) ;;;;; _CPU_ DW 0 ;現行機の、ダミーループ回数 (del 90.10.6) ;;;;; _TIME_ DW 0 ;目標時間 (del 90.10.6) ;;;;; _MUKASI_ DW 0 ;一つ前の時間 (del 90.10.6) ;************************************************************************ ;* タイムスタンパ:待ち時間制御に使用するダミーループおよび * ;* I/Oリカバリータイムの保証に使用する。 * ;* ここでは、高分解能ARTICポートを用いた。 * ;* 分解能: 3.26   μs * ;* 最大値: 106.8  ms * ;* アドレス: 005C H(ワード) * ;************************************************************************ _ARTIC_LOW_ EQU 005CH ;タイムスタンパI/O port MSR_DELAY: PUSH AX ;使用するレジスタを退避 PUSH BX ;使用するレジスタを退避 PUSH DX ;使用するレジスタを退避 push es ; (90.10.6) PUSH DS ;データセグメントレジスタを退避 push ds ; (90.10.6) pop es ; (90.10.6) ;************************************************************************ ;* CPUのきりわけ * ;* −−−−−−−BIOSFLAGを参照する * ;************************************************************************ mov ax, 40h ; mov ds, ax ; ;----------------NPCかどうかを判断------------------------------------ MOV AL,BYTE PTR DS:[58H] ;40:58の内容をALに入れる MOV BYTE PTR ES:_BIOS_FLAG1_,AL ;----------------現行機のどのCPUかを判断------------------------------ MOV AL,BYTE PTR DS:[80H] ;40:80の内容をALに入れる MOV BYTE PTR ES:_BIOS_FLAG2_,AL MOV AL,BYTE PTR DS:[5BH] ;40:5Bの内容をALに入れる (93.03.09) MOV BYTE PTR ES:_BIOS_FLAG3_,AL ;(93.03.09) POP DS ;データセグメントレジスタを復帰 AND BYTE PTR _BIOS_FLAG1_,80H ;第7ビット以外を0でマスクする JNZ _NPC_ AND BYTE PTR ES:_BIOS_FLAG3_,04H ;(93.03.09) JNZ _NPC_ ;(93.03.09) AND BYTE PTR _BIOS_FLAG2_,03H ;第0,1ビット以外を0でマスクする JZ _V30_ ;第0,1ビットが「00」ならばV30 CMP BYTE PTR _BIOS_FLAG2_,01H ;第0,1ビットが「01」ならば286 JE _I286_ ;######################################################################## ;# 現行機の時 # ;######################################################################## _I386_: ;CPUは386 MOV WORD PTR _CPU_,_386_DELAY_ ;386の時はCPU=_386_DELAY_にする JMP short _EXIT_CPU_ _V30_: ;CPUはV30 MOV WORD PTR _CPU_,_V30_DELAY_ ;V30の時はCPU=_V30_DELAY_にする JMP short _EXIT_CPU_ _I286_: ;CPUは286 MOV WORD PTR _CPU_,_286_DELAY_ ;286の時はCPU=_286_DELAY_にする _EXIT_CPU_: ;---------------------------------------------- ここからの処理で、1msと ; なるようにする ; PUSH CX ;カウンタの内容を退避 MOV CX,_CPU_ ;CX=_CPU_ ; ~~~~この値が機種ごとに変わる _LOOP2_: ; LOOP _LOOP2_ ;CX=CX-1 : IF ( CX == 0 ) GOTO _LOOP2_ POP CX ;カウンタの内容を復帰 ; ;---------------------------------------------- LOOP _EXIT_CPU_ ;CX=CX-1 : IF ( CX == 0 ) GOTO LOOP1 pop es POP DX ;退避したレジスタを復帰 POP BX ;退避したレジスタを復帰 POP AX ;退避したレジスタを復帰 RET ;RETURN ;######################################################################## ;# NPCの時 # ;######################################################################## _NPC_: CALL _NPC_DELAY_ ;1ms消費ルーチン LOOP _NPC_ ;CX=CX-1 ; : IF ( CX == 0 ) GOTO LOOP1 pop es ;(INS.91.1.14) POP DX ;退避したレジスタを復帰 POP BX ;退避したレジスタを復帰 POP AX ;退避したレジスタを復帰 RET _NPC_DELAY_: PUSH CX MOV DX,_ARTIC_LOW_ ;ARTICポートの内容を ;DXにいれる IN AX,DX ;ARTICポートからAXに ;データを入れる MOV BX,AX ;初期時間を保存 MOV CX,_DELAY_COUNT_ ;設定時間をCXに入れる ADD CX,BX ;目標時間設定 MOV _TIME_,CX ;目標時間をCAKEに格納 JNC _POPO_ ;****************************************************************************** ;* 0 7FFF FFFF * ;* 1========▲-----------------1-----------×==========○============1 * ;* ↑ ↑   ↑ * ;*      目標時間:CAKE 初期時間:BX  現在時間:AX   * ;* * ;* * ;* の時 * ;* * ;****************************************************************************** MOV _MUKASI_,BX ;初期時間を_MUKASI_に入れておく _YOMU1_: IN AX,DX ;現在時間をAXに入れる CMP _MUKASI_,AX ;一つ前の時間と現在の時間を比較 ; 現在時間が、目標時間よりも ; 大きいため、 ; 現在時間と一つ前の時間を ; 比較する。 ; 現在時間が小さくなった場合 ; タイムスタンパが0に戻った ; ことになる JA _POPO_ ;現在時刻の方が小さくなった! MOV _MUKASI_,AX ;一つ前の時間を_MUKASI_に ; 入れておく JMP _YOMU1_ ;ループ ;****************************************************************************** ;* 0 7FFF FFFF * ;* 1--------×============○====1=============▲---------------------1 * ;* ↑ ↑ ↑ * ;*  初期時間:BX   現在時間:AX    目標時間:CAKE * ;* * ;* * ;* の時 * ;* * ;****************************************************************************** _POPO_: IN AX,DX ;現在時間をAXに入れる CMP _TIME_,AX ;目標時間までなったか? JA _POPO_ ;No:まだ目標時間ではない POP CX RET ;END NPC_RTN