MANIMANIAのレトロエロゲーカウントダウン

人生の残り時間が半分を切ったというのに若き日に目にしたエロゲーに魂を引かれ続けるイタいおっさんがこなしたゲームを紹介。

晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その3)

2012-07-09 23:15:03 | レトロパソコンのお作法
晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その2)からの続き。
最初の1行だけ重複してます。

3B66:0250 E8 0005 call sub_2 ; (0258)
;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0250
;##########################################################################

3B66:0258 sub_2 proc near ; CX=03D6H,DX=03B7H(='ADVH.EXE')
3B66:0258 0E push cs
3B66:0259 07 pop es ; CS=ES,パラメータブロックセグメントアドレス
3B66:025A FE 06 03A0 inc byte ptr [03A0h] ; (3B66:03A0=33H='3')インクリメントして34H='4'
3B66:025E ,BB 041E mov bx,041Eh ; BX=041EH,パラメータブロックオフセットアドレス
; パラメータブロックはCS:041EH
3B66:0261 C7 07 0000 mov word ptr [bx],0 ; DS:[041EH]=0000H ;041EH以下のメモリ書き換え
3B66:0265 89 4F 02 mov [bx+2],cx ; DS:[0420H]=CX=03D6H ;041E 00 00
3B66:0268 8C 5F 04 mov [bx+4],ds ; DS:[0422H]=DS ;0420 D6 03 DS DS 5C 00 DS DS
3B66:026B C7 47 06 005C mov word ptr [bx+6],5Ch ; DS:[0424H]=005CH ;0428 6C 00 DS DS
3B66:0270 8C 5F 08 mov [bx+8],ds ; DS:[0426H]=DS
3B66:0273 C7 47 0A 006C mov word ptr [bx+0Ah],6Ch ; DS:[0428H]=006CH
3B66:0278 8C 5F 0C mov [bx+0Ch],ds ; DS:[042AH]=DS
3B66:027B B8 4B00 mov ax,4B00h ; プログラムのロードと実行
; DS:DX=パス名の位置,ES:BX=パラメータブロックの位置
; BX=(03D6=10 20 5C 4D 45 53 5C 48 4F 30 30 30 30 2E 4D 45 53 0D)
; ^P半角スペース\MES\HO0000.MESリターンキー)
3B66:027E CD 21 int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx INT 0F5Hのアドレスにロードした?
3B66:0280 BA 0383 mov dx,383h ; 文字列'プログラムが起動できません。(4)$'
3B66:0283 C3 retn
sub_2 endp


3B66:0253 5E pop si ; SI復帰,SI=0418H
3B66:0254 72 C2 jc 0218h ; Jump if carry Set エラーなければCF=0でスルー,エラーがあればCF=1なので0218Hへ
3B66:0256 EB C9 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[0418H]=01H
3B66:0223 84 C0 test al,al ; (3B66:0418=01H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03D0H=[0419H]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=03AEH=[041BH]
3B66:0230 83 C6 05 add si,5 ; SI=041DH
3B66:0233 FE C8 dec al ; AL=00H
3B66:0235 74 18 jz 024Fh ; Jump if zero 0なので024FHへ

(省略)
3B66:024F loc_9: ; xref 3B66:0235, 023D
3B66:024F 56 push si ; SI退避,SI=041DH
3B66:0250 E8 0005 call sub_2 ; (0258)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0250
;##########################################################################

3B66:0258 sub_2 proc near ; CX=03D0H,DX=03AEH(='HARE.EXE')
3B66:0258 0E push cs
3B66:0259 07 pop es ; CS=ES,パラメータブロックセグメントアドレス
3B66:025A FE 06 03A0 inc byte ptr [03A0h] ; (3B66:03A0=34H='4')インクリメントして35H='5'
3B66:025E ,BB 041E mov bx,041Eh ; BX=041EH,パラメータブロックオフセットアドレス
; パラメータブロックはCS:041EH
3B66:0261 C7 07 0000 mov word ptr [bx],0 ; DS:[041EH]=0000H ;041EH以下のメモリ書き換え
3B66:0265 89 4F 02 mov [bx+2],cx ; DS:[0420H]=CX=03D0H ;041E 00 00
3B66:0268 8C 5F 04 mov [bx+4],ds ; DS:[0422H]=DS ;0420 D0 03 DS DS 5C 00 DS DS
3B66:026B C7 47 06 005C mov word ptr [bx+6],5Ch ; DS:[0424H]=005CH ;0428 6C 00 DS DS
3B66:0270 8C 5F 08 mov [bx+8],ds ; DS:[0426H]=DS
3B66:0273 C7 47 0A 006C mov word ptr [bx+0Ah],6Ch ; DS:[0428H]=006CH
3B66:0278 8C 5F 0C mov [bx+0Ch],ds ; DS:[042AH]=DS
3B66:027B B8 4B00 mov ax,4B00h ; プログラムのロードと実行
; DS:DX=パス名の位置,ES:BX=パラメータブロックの位置
; BX=(03D0=02 20 33 0D)
; B:半角スペース'3'リターンキー)
3B66:027E CD 21 int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx INT 0F4Hのアドレスにロードした?
3B66:0280 BA 0383 mov dx,383h ; 文字列'プログラムが起動できません。(5)$'
3B66:0283 C3 retn
sub_2 endp

3B66:0253 5E pop si ; SI復帰,SI=041DH
3B66:0254 72 C2 jc 0218h ; Jump if carry Set エラーなければCF=0でスルー,エラーがあればCF=1なので0218Hへ
3B66:0256 EB C9 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[041DH]=00H
3B66:0223 84 C0 test al,al ; (3B66:041D=00H),ZF=1
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=1なのでスルー
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227) 無限ループ
3B66:0229 90 nop

;**********************************************************************************************
;プログラムロードエラー発生時
3B66:0218 sub_1 proc near
3B66:0218 loc_1: ; xref 3B66:0254
3B66:0218 E8 0069 call 0284h ; (0284) エラー文字列表示ルーチンへ

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0218 ; エラー文字列表示ルーチン
;##########################################################################

3B66:0284 sub_3 proc near
3B66:0284 B4 09 mov ah,9 ; DX=0383Hで飛んできた。文字列 'プログラムが起動できません。(5)$'
3B66:0286 CD 21 int 21h ; DOS Services ah=function 09h 文字列の表示,DS:DXから$までの文字列を画面に表示
; display char string at ds:dx
3B66:0288 loc_10: ; xref 3B66:028A
3B66:0288 ,FA cli ; Disable interrupts 外部割込禁止
3B66:0289 F4 hlt ; Halt processor 割込がかかるまでCPUを停止させる
3B66:028A EB FC jmp short loc_10 ; (0288)
sub_3 endp
;**********************************************************************************************


3B66:02B5 90 db 90h

;##########################################################################
;
; External Entry Point 致命的エラー(INT24)発生時の独自割込処理
;
;##########################################################################

3B66:02B6 int_24h_entry proc far ; xref 3B66:0635
3B66:02B6 55 push bp ; 各レジスタ退避
3B66:02B7 57 push di
3B66:02B8 56 push si
3B66:02B9 1E push ds
3B66:02BA 06 push es
3B66:02BB 53 push bx
3B66:02BC 51 push cx
3B66:02BD 52 push dx
3B66:02BE 50 push ax
3B66:02BF F6 C4 80 test ah,80h ; AHの第7bitが1でなければ0
3B66:02C2 75 4E jnz 0312h ; Jump if not zero
; AHの第7bitが0ならALを0にしてAX以外のレジスタ復帰。
3B66:02C4 0E push cs
3B66:02C5 1F pop ds ; CS=DS
3B66:02C6 04 41 add al,41h ; AL=41H 'A'
3B66:02C8 A2 043F mov 043Fh,al ; (3B66:043F=41h)
; エラー表示内のドライブレター表記部分に,
; ドライブレターの文字コードを代入。
3B66:02CB 8B DF mov bx,di ; BX=DI
3B66:02CD 2A FF sub bh,bh ; BH=00H
3B66:02CF 83 FB 0C cmp bx,0Ch ; BXと0CHを比較(BHが00Hなので事実上,BL(DL)と0CHとの比較)
3B66:02D2 73 3E jae 0312h ; Jump if above or =
; BL>=0CHなら,ALを0にして各レジスタ復帰(02C2Hと同じ)
3B66:02D4 B8 A000 mov ax,0A000h ; AX=0A000H
3B66:02D7 8E C0 mov es,ax ; ES=0A000H,テキストVRAMセグメント
3B66:02D9 ,BF 0F00 mov di,0F00h ; DI=0F00H
3B66:02DC ,BE 042E mov si,042Eh ; SI=042EH
3B66:02DF D1 E3 shl bx,1 ; Shift w/zeros fill,SHIFT LOGICAL LEFT 左シフトbit7をCFに,bit0を0に
3B66:02E1 E8 FFA8 call 028Ch ; (028C)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:02E1, 02E8, 02EE
;##########################################################################

3B66:028C sub_4 proc near
3B66:028C FC cld ; Clear direction ; ディレクションフラグを0(増加)にリセット
3B66:028D B4 65 mov ah,65h ; AX=6500H
3B66:028F EB 0B jmp 029Ch ; (029C)
3B66:0291 loc_11: ; xref 3B66:029F
3B66:0291 26: 88 A5 2000 mov es:[2000h],ah ; (A000:2000=65h)
3B66:0296 26: 88 05 mov es:[di],al ; (A000:0F00=00H)
3B66:0299 83 C7 02 add di,2 ; DI=0F02H
3B66:029C loc_12: ; xref 3B66:028F
3B66:029C AC lodsb ; String [si] to al, DS:[SI]で示されるメモリのバイト値をALレジスタに転送し,SIの値を1増加または減少させる
; (042Eh=20H),SIを042Fhに・・・SI=0456HでAL=00H,SI=0457Hでルーチン終了
3B66:029D 0A C0 or al,al ; Zero ? AL=20HなのでZF=0, [SI]=0456Hになるまで00Hなし。ES:[DI]に042EHから0456Hまでのデータをロード
; 半角スペース10個,'ドライブ A: デ エラー ハッセイ ・・・ ',00H,Aはエラーの発生したドライブによって変動
3B66:029F 75 F0 jnz 0291h ; Jump if not zero

3B66:02A1 C3 retn
sub_4 endp

3B66:02E4 8B B7 04FA mov si,[04FAh] ; (3B66:04FA=457h)
3B66:02E8 E8 FFA1 call sub_4 ; (028C)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:02E1, 02E8, 02EE
;##########################################################################

3B66:028C sub_4 proc near
3B66:028C FC cld ; Clear direction ; ディレクションフラグを0(増加)にリセット
3B66:028D B4 65 mov ah,65h ; AX=6500H
3B66:028F EB 0B jmp 029Ch ; (029C)
3B66:0291 loc_11: ; xref 3B66:029F
3B66:0291 26: 88 A5 2000 mov es:[2000h],ah ; (A000:2000=0E1h)
3B66:0296 26: 88 05 mov es:[di],al
3B66:0299 83 C7 02 add di,2 ; DI=0F04H
3B66:029C loc_12: ; xref 3B66:028F
3B66:029C AC lodsb ; String [si] to al, DS:[SI]で示されるメモリのバイト値をALレジスタに転送し,SIの値を1増加または減少させる
; (0457h=CCH),SIを0458hに・・・・・・SI=0474HでAL=00H,SI=0475Hでルーチン終了
3B66:029D 0A C0 or al,al ; Zero ? AL=CCHなのでZF=0
; 'プロテクトシール ヲ ハガシテ クダサイ。 ',00H
3B66:029F 75 F0 jnz 0291h1 ; Jump if not zero

3B66:02A1 C3 retn
sub_4 endp


3B66:02EB ,BE 04ED mov si,[04ED] ; (3B66:04ED=20h)
3B66:02EE E8 FF9B call sub_4 ; (028C)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:02E1, 02E8, 02EE
;##########################################################################

3B66:028C sub_4 proc near
3B66:028C FC cld ; Clear direction ; ディレクションフラグを0(増加)にリセット
3B66:028D B4 65 mov ah,65h ; AX=6500H
3B66:028F EB 0B jmp 029Ch ; (029C)
3B66:0291 loc_11: ; xref 3B66:029F
3B66:0291 26: 88 A5 2000 mov es:[2000h],ah ; (A000:2000=0E1h)
3B66:0296 26: 88 05 mov es:[di],al
3B66:0299 83 C7 02 add di,2 ; DI=0F06H
3B66:029C loc_12: ; xref 3B66:028F
3B66:029C AC lodsb ; String [si] to al, DS:[SI]で示されるメモリのバイト値をALレジスタに転送し,SIの値を1増加または減少させる
; (04EDh=20H),SIを04EEhに・・・,SI=04F8HでAL=00H,SI=04F9Hでルーチン終了
3B66:029D 0A C0 or al,al ; Zero ? AL=20HなのでZF=0
; 半角スペース11個,,00H
3B66:029F 75 F0 jnz 0291h1 ; Jump if not zero

3B66:02A1 C3 retn
sub_4 endp

3B66:02F1 E8 FFAE call sub_5 ; (02A2) ブザー鳴動処理

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:02F1 ブザー鳴動処理
;##########################################################################

3B66:02A2 sub_5 proc near
3B66:02A2 B0 06 mov al,6
3B66:02A4 E6 37 out 37h,al ; port 37h I/O Non-standard
; ポート番号037H(8255Aのコントロールレジスタ)に
; 06Hを出力する。
; 06h ブザー 06h=鳴動
; http://www.webtech.co.jp/company/doc/undocumented_mem/io_syste.txt
3B66:02A6 2B C9 sub cx,cx ; CX=00H

3B66:02A8 locloop_13: ; xref 3B66:02A8 LOOP4つ分のウエイトか?
3B66:02A8 E2 FE loop locloop_13 ; Loop if cx > 0


3B66:02AA locloop_14: ; xref 3B66:02AA
3B66:02AA E2 FE loop locloop_14 ; Loop if cx > 0


3B66:02AC locloop_15: ; xref 3B66:02AC
3B66:02AC E2 FE loop locloop_15 ; Loop if cx > 0


3B66:02AE locloop_16: ; xref 3B66:02AE
3B66:02AE E2 FE loop locloop_16 ; Loop if cx > 0

3B66:02B0 B0 07 mov al,7
3B66:02B2 E6 37 out 37h,al ; port 37h I/O Non-standard
; ポート番号037H(8255Aのコントロールレジスタ)に
; 07Hを出力する。
; 07h ブザー 07h=停止
; http://www.webtech.co.jp/company/doc/undocumented_mem/io_syste.txt
3B66:02B4 C3 retn
sub_5 endp

3B66:02F4 E8 0027 call sub_6 ; (031E)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:02F4, 0737
;##########################################################################

3B66:031E sub_6 proc near
3B66:031E loc_20: ; xref 3B66:032A
3B66:031E B4 01 mov ah,1 ; キーバッファ状態のセンス(キーバッファ内先頭1文字分)
; BH=00H,キー入力データなし
; BH=01H,キー入力データあり,AH=キーコード,AL=キーデータ
3B66:0320 CD 18 int 18h ; ROM basic
3B66:0322 53 push bx ; BX退避
3B66:0323 B4 00 mov ah,0 ; キーデータの読み出し(1文字の入力待ち)
3B66:0325 CD 18 int 18h ; ROM basic キーバッファ内先頭1文字分のキー入力データを取り出し,
; AH=キーコード,AL=キーデータを出力
3B66:0327 5B pop bx ; BX復帰
3B66:0328 84 FF test bh,bh ; BHは00Hか?キー入力データなしなら結果は0
3B66:032A 75 F2 jnz loc_20 ; Jump if not zero キー入力データがあれば031Ehへループ
3B66:032C C3 retn
sub_6 endp

3B66:02F7 ,BF 0F00 mov di,[0F00H] ; (A000:0F00=00h)
3B66:02FA B9 0050 mov cx,50h ; CX=0050H,50H回セット

3B66:02FD locloop_17: ; xref 3B66:030B
3B66:02FD B8 E120 mov ax,0E120h
3B66:0300 26: 88 05 mov es:[di],al
3B66:0303 26: 88 A5 2000 mov es:[2000],ah ; (A000:2000=0E1h)
3B66:0308 83 C7 02 add di,2
3B66:030B E2 F0 loop locloop_17 ; Loop if cx > 0

3B66:030D 58 pop ax ; AX復帰
3B66:030E B0 01 mov al,1 ; AL=01H
3B66:0310 EB 03 jmp short loc_19 ; (0315)
3B66:0312 loc_18: ; xref 3B66:02C2, 02D2
3B66:0312 58 pop ax ; AX復帰
3B66:0313 2A C0 sub al,al ; AL=00H
3B66:0315 loc_19: ; xref 3B66:0310
3B66:0315 5A pop dx ;各レジスタ復帰
3B66:0316 59 pop cx
3B66:0317 5B pop bx
3B66:0318 07 pop es
3B66:0319 1F pop ds
3B66:031A 5E pop si
3B66:031B 5F pop di
3B66:031C 5D pop bp
int_24h_entry endp


;##########################################################################
;
; External Entry Point
;
;##########################################################################

3B66:031D int_06h_entry proc far ; xref 3B66:061F
3B66:031D CF iret ; Interrupt return 割込からのリターン命令
int_06h_entry endp



;* No entry point to code

3B66:0367 90 db 90h
3B66:0368 83 81 83 82 83 8A data_73 db 'メモリーが解放できません。$'
3B66:036E 81 5B 82 AA 89 F0
3B66:0374 95 FA 82 C5 82 AB
3B66:037A 82 DC 82 B9 82 F1
3B66:0380 81 42 24
3B66:0383 83 76 83 8D 83 4F db 'プログラムが起動できません。(0)$'
3B66:0389 83 89 83 80 82 AA
3B66:038F 8B 4E 93 AE 82 C5
3B66:0395 82 AB 82 DC 82 B9
3B66:039B 82 F1 81 42 28 30
3B66:03A1 29 24
3B66:03A3 4D 55 53 44 52 56 db 'MUSDRV.COM',0
3B66:03A9 2E 43 4F 4D
3B66:03AD 00
3B66:03AE 48 41 52 45 2E 45 db 'HARE.EXE',0
3B66:03B4 58 45
3B66:03B6
3B66:03B7 41 44 56 48 2E 45 db 'ADVH.EXE',0
3B66:03BD 58 45
3B69:03BF 00
3B69:03C0 00 0D 00 00 02 db 00h, 00h, 0Dh, 00h, 00h, 02h
3B69:03C5 20 31 0D 00 00 02 db 20h, 31h, 0Dh, 00h, 00h, 02h
3B69:03CB 20 32 0D 00 00 10 db 20h, 32h, 0Dh, 00h, 00h, 10h
3B69:03D1 20 5C 4D 45 53 5C db ' \MES\HO0000.MES', 0Dh
3B69:03D7 48 4F 30 30 30 30
3B69:03DD 2E 4D 45 53 0D
3B66:03E2 00 00 db 0,0
3B69:03E4 41 3A 5C 4D 55 53 db 'A:\MUS\HO-OPN.M'
3B69:03EA 5C 48 4F 2D 4F 50
3B69:03F0 4E 2E 4D
3B69:03F3 00 db 0

3B66:07A4 1B 5B 32 4A 24 data_96 db 1Bh, '[2J$' ; xref 3B66:0777 1BHはエスケープコード,[2Jで画面をクリアし,カーソルをホームに
3B66:07A9 1B 5B 6D 41 64 76 data_97 db 1Bh, '[mAdvShell for ADVH System ' ; xref 3B66:0781
3B66:07AF 53 68 65 6C 6C 20
3B66:07B5 66 6F 72 20 41 44
3B66:07BB 56 48 20 53 79 73
3B66:07C1 74 65 6D 20
3B66:07C5 20 56 65 72 2E 31 db ' Ver.1.01', 0Dh, 0Ah, 'Copyright'
3B66:07CB 2E 30 31 0D 0A 43
3B66:07D1 6F 70 79 72 69 67
3B66:07D7 68 74
3B66:07D9 28 43 29 20 54 75 db '(C) Tuneup 1988,89.', 0Dh, 'Copy'
3B66:07DF 6E 65 75 70 20 31
3B66:07E5 39 38 38 2C 38 39
3B66:07EB 2E 0D 43 6F 70 79
3B66:07F1 72 69 67 68 74 28 db 'right(C) Fairytale/カクテル・ソフト',
3B66:07F7 43 29 20 46 61 69
3B66:07FD 72 79 74 61 6C 65
3B66:0803 2F B6 B8 C3 D9 A5
3B66:0809 BF CC C4
3B66:080C 20 31 39 38 38 2C db ' 1988,89.', 0Dh, 0Ah, 0Dh, 0Ah, 0Dh,0Ah
3B66:0812 38 39 2E 0D 0A 0D
3B66:0818 0A 0D 0A
3B66:081B 81 40 90 B0 82 EA db ' 晴れのちおおさわぎ', 0Dh, 0Ah
3B66:0821 82 CC 82 BF 82 A8
3B66:0827 82 A8 82 B3 82 ED
3B66:082D 82 AC 0D 0A
3B66:0831 0D 0A 81 40 81 40 db 0Dh, 0Ah, '  ',
3B66:0837 1B 5B 35 3B 34 33 db 1Bh, '[5;43m [[[ プログラムを読み込み中 ]]] ' ブリンク(点滅・背景黄色)
3B66:083D 6D 81 40 5B 5B 5B ;81 40は全角スペースの文字コード
3B66:0841 20 83 76 83 8D 83
3B66:0847 8D 83 4F 83 89 83
3B66:084D 80 82 F0 93 C7 82
3B66:0853 DD 8D 9E 82 DD 92
3B66:0859 86 20 5D 5D 5D 81
3B66:085F 40
3B66:0860 1B 5B 6D 0D 0A 0D db 1Bh,'[m', 0Dh, 0Ah, 0Dh, 0Ah, 0Dh, 0Ah
3B66:0867 0A 0D 0A
3B66:0869 24 db '$'
3B66:086A 83 68 83 89 83 43 db 'ドライブA:から起動しなおしてく'
3B66:0870 83 75 82 60 81 46
3B66:0876 82 A9 82 E7 8B 4E
3B66:087C 93 AE 82 B5 82 C8
3B66:0882 82 A8 82 B5 82 C4
3B66:0888 82 AD
3B66:088A 82 BE 82 B3 82 A2 db 'ださい。'
3B66:0890 81 42
3B66:0892 07 db 7
3B66:0893 0D 0A 24 db 0Dh, 0Ah, '$'
3B66:0896 83 68 83 89 83 43 data_100 db 'ドライブA:のディスクを確認して' ; xref 3B66:072C
3B66:089C 83 75 82 60 81 46
3B66:08A2 82 CC 83 66 83 42
3B66:08A8 83 58 83 4E 82 F0
3B66:08AE 8A 6D 94 46 82 B5
3B66:08B4 82 C4
3B66:08B6 82 AD 82 BE 82 B3 db 'ください。', 7, '$'
3B66:08BC 82 A2 81 42 07 24
3B66:08C2 0D 81 40 81 40 81 data_103 db 0Dh, '              ' ; xref 3B66:073E
3B66:08C8 40 81 40 81 40 81
3B66:08CE 40 81 40 81 40 81
3B66:08D4 40 81 40 81 40 81
3B66:08DA 40 81 40 81 40
3B66:08DF 81 40 81 40 81 40 db '       ', 0Dh, '$'
3B66:08E5 81 40 81 40 81 40
3B66:08EB 81 40 0D 24
3B66:08EF 90 db 90h
3B66:08F0 CA DA C9 C1 B5 B5 data_104 db 'ハレノチオオサワギA)' ; xref 3B66:070F
3B66:08F6 BB DC B7 DE 41 29
3B66:08FC 00 00 00 00 db 00h, 00h, 00h, 00h

seg_a ends



end start


ほんとはその3でも収まりきらなかったので,半角エラーメッセージデータなどを一部省略しました。

晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その1)はこちら
晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その2)はこちら

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作物の取扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

PC-9821Cx13はえらい奴

2012-07-06 20:14:45 | レトロパソコンのお作法
えらいというのはGreatの意味で使っています。

昔,2ちゃんねるのどっかで,PC-9821にDVD-Multiドライブを積んで使っていることを告白しましたが,まったく反応ありませんでした。
嘘つきとか釣りとか言われるならいいんですが,完全スルーでした。ちょっと悲しかったです。
でも,ここで書いたら信じてもらえそうなので書き残しておきます。

手順
1 DVD-Multiドライブ(内蔵型)を買ってくる。
2 内蔵CDドライブと入れ替える。
3 Windows95をWindows98にアップグレードする。
4 DVDドライブ用のドライバをインストールする。
5 Windows95にダウングレードする。
6 DVDドライブ用ドライバは削除されておらず,書き込みドライブとしては使える。

下のように,リムーバブルディスクとして表示されています。


こちらはデバイスマネージャ画面。


 ただ,自分の場合,書き込み用にDVD-RAMを使っているだけなので,ほんとは+R,-RWが使えるかどうかは不明DVDドライブ実機を確認したところ,DVD-R,RAM対応となっているので,+R,-RWは使える可能性がありません。
 また,DVD-RはWindows95対応の書き込みソフトがないから無理でしょう。

あと記憶があやふやなところ
1 DVDドライブ用ドライバを入れただけではなく,DVD Movie Album SEというソフトも入れたかも。
2 Windows98からのダウングレードなんて簡単にできたっけ?
  エー・アイ・ソフトが出してた,ダウングレードを可能にするソフトを用いてWindows98を入れてたかも。

Windows98を入れたのは,Windows95のままではDVDドライブのドライバ自体,入れてもらえなかったから。
Windows95のままだとCD-ROMドライブとしては使えました。Windows95で使えるCD-R焼きソフトは持ってますが,今さら等倍速焼きとかしても仕方ないのでCD-Rを焼けるかどうかは試してません。
Windows98からダウングレードしたのは,そのままにする必要性がなかったから。
そんなわけで,Windows98の入るPC-98なら,DVDドライブはそのまま使えるのかもしれません。
うちの子はWindows95プレインストールマシンだったので,特に不都合なくWindows98を入れられました。

とまあ,誰にも信じてもらえませんでしたが,今でもこの改造のおかげで,98実機で作成したイメージファイルを最新マシン上に持ってくるメディアとして,DVD-RAMが使えているという実益はあるので,この情報が誰の役に立たなくてもまあいいんですけどね。

なお,この改造をすると,4連装ドライブの顔隠し(ベゼルってやつ?)が使えないため,うちの98Canbeくんは,DVD-RAMドライブ部分だけマスクなしで窪んだところから顔を出してしまいます。


同じPC-9821Cx13シリーズでも,非連装式ドライブ内蔵のやつなら,きれいな顔で収まるかもしれません。

やったらたまたまそうなったというだけの,改造報告でした。ちょっと前までは検索したら,Canbe自慢のユーザーさんホームページとかいっぱいあったのに,今はほとんどなくなっちゃいましたね・・・。

ちなみにうちの子は,メモリは上限まで増設し,CPUも対応機種に載っていなかったけれどいちかばちかでAMD K6-2 400MHz搭載オーバードライブプロセッサ(いわゆる下駄)に載せ替えてみたら見事に動いたという,Cx13界のエリートなのでした。




オーバードライブプロセッサ導入後に,日本橋のソフマップで,Cx13のさらなるエリート化を目指して周辺機器を見てたら,店員に機種を聞かれたのでCanbeですと答えたら,鼻で笑って離れて行かれたことがありました。
Canbeにだって色々あるのに不勉強な奴だと思うけれども,時代遅れの機体に金をかける馬鹿者に見えたのかもしれません。
時代遅れもここまで来るとそれなりに存在意義があるようには思いますが。

そんなわけで,こんな話も生きているうちに書いておかないとロストテクノロジーとなってしまうので,書いてみました。
年寄りの昔話は長くていけませんな。

ではまた。

晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その2)

2012-07-03 12:14:43 | レトロパソコンのお作法
晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その1)からの続き。
最初の1行だけ重複してます。

3B66:074C E8 0001 call sub_13 ; (0750)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0678, 074C ;ディスクリザルト,ディスクリセットルーチン
;##########################################################################

3B66:0750 sub_13 proc near
3B66:0750 2B C0 sub ax,ax ; AX=0000H
3B66:0752 8E C0 mov es,ax ; ES=0000H
3B66:0754 ,BB 0564 mov bx,0564h ;
3B66:0757 B0 C0 mov al,0C0h
3B66:0759 B9 0004 mov cx,4

3B66:075C locloop_27: ; xref 3B66:0762
3B66:075C 26: 08 07 or es:[bx],al
3B66:075F 83 C3 08 add bx,8
3B66:0762 E2 F8 loop locloop_27 ; Loop if cx > 0

3B66:0764 B4 0D mov ah,0Dh
3B66:0766 CD 21 int 21h ; DOS Services ah=function 0Dh
; flush disk buffers to disk
3B66:0768 C3 retn
sub_13 endp

3B66:074F C3 retn ;==================================================================
sub_12 endp


3B66:0793 E8 FEF4 call sub_10 ; (068A)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0793
;##########################################################################

3B66:068A sub_10 proc near
3B66:068A 56 push si ; SI退避
3B66:068B 06 push es ; ES退避
3B66:068C 2B F6 sub si,si ; SI=0000H
3B66:068E B8 0002 mov ax,2 ; AX=0002H
3B66:0691 B1 21 mov cl,21h ; CL=21H
3B66:0693 D3 E8 shr ax,cl ; AXを21H回右シフト。AX=0000H,
; Shift w/zeros fill
3B66:0695 A9 0001 test ax,1 ; ZF=0
3B66:0698 74 39 jz 06D3h ; Jump if zero,ZF=1なら06D3Hへ
3B66:069A 46 inc si ; SI=0001H
3B66:069B 1E push ds ; DS退避
3B66:069C 2B C0 sub ax,ax ; AX=0000H
3B66:069E 8E D8 mov ds,ax ; DS=0000H
3B66:06A0 ,BB 0018 mov bx,0018 ; BX=0018H
3B66:06A3 8B 07 mov ax,[bx] ; AX=DS:[0018H],STOPキーの割込ベクタオフセットのメモリ
3B66:06A5 2E: A3 06DC mov cs:[06DCH],ax ; CS:[06DCH]にSTOPキーの割込ベクタオフセットのメモリを代入
3B66:06A9 8B 47 02 mov ax,[bx+2] ; AX=DS:[001AH],STOPキーの割込ベクタセグメントのメモリ
3B66:06AC 2E: A3 06DE mov cs:[06DEH],ax ; CS:[06DEH]に=STOPキーの割込ベクタセグメントのメモリを代入
3B66:06B0 B8 06E0 mov ax,6E0h ; AX=6E0H
3B66:06B3 89 07 mov [bx],ax ; DS:[0018H],STOPキーの割込ベクタオフセットのメモリを6E0Hに書き換え
3B66:06B5 8C 4F 02 mov [bx+2],cs ; DS:[001AH],STOPキーの割込ベクタセグメントのメモリをCS:に書き換え
; [001AH]:[0018H]=本来のSTOPキーの割込ベクタを[06DEH]:[06DCH]にコピーし,
; STOPキーの割込ベクタをCS:[06E0H]にコピーした
3B66:06B8 2B C0 sub ax,ax ; AX=0000H
3B66:06BA BB 00FF mov bx,0FFh ; BX=00FFH
3B66:06BD 0F ;* pop cs ; DS=CS,Dangerous-8088 only
3B66:06BE BE 2EC3 mov si,2EC3h ; SI=2EC3H
3B66:06C1 C4 16 06DC les dx,dword ptr ds:06DCh ; Load seg:offset ptr,word load reg and ES
; DXに[06DCH],ESにDS:,=本来のSTOPキーの割込ベクタのメモリをロード
3B66:06C5 ,BB 0018 mov bx,0018 ; BX=0018H
3B66:06C8 89 17 mov [bx],dx ; [0018H]にDS:[06DCH]を代入
3B66:06CA 8C 47 02 mov [bx+2],es ; [001AH]にDS:を代入 ;★本来のSTOPキーの割込ベクタの内容に戻っただけか?
3B66:06CD 1F pop ds ; DS復帰
3B66:06CE 0B C0 or ax,ax ; Zero ? AX=0000HなのでZF=1
3B66:06D0 74 01 jz 06D3h ; Jump if zero ZF=1なので06D3Hへ
3B66:06D2 46 inc si ; SI=2EC4H
3B66:06D3 loc_23: ; xref 3B66:0698, 06D0
3B66:06D3 8B C6 mov ax,si ; 06D0HからきたときはSI=23C3H=AX
3B66:06D5 A2 0616 mov [0616h],al ; [0616H]=C3H
3B66:06D8 07 pop es ; ES復帰
3B66:06D9 5E pop si ; SI復帰
3B66:06DA C3 retn
sub_10 endp

3B66:0796 0E push cs ;
3B66:0797 07 pop es ; ES=CS
3B66:0798 BB 061E mov bx,61Eh ; BX=061EH
3B66:079B 83 C3 0F add bx,0Fh ; BX=062DH
3B66:079E B1 04 mov cl,4 ; CL=04H
3B66:07A0 D3 EB shr bx,cl ; BXを4H回右シフト。BX=0062H
; Shift w/zeros fill
3B66:07A2 C3 retn
sub_14 endp

3B66:020E B4 4A mov ah,4Ah ; 割り当てられたメモリブロックのサイズ変更。メモリ開放処理。
3B66:0210 CD 21 int 21h ; DOS Services ah=function 4Ah, ES=メモリ領域のセグメントアドレス
; change memory allocation BX==開放したいメモリの大きさ(パラグラフ)
; bx=bytes/16, es=mem segment
3B66:0212 ,BA 0368 mov dx,0368H ; DX=0368H,文字列'メモリーが解放できません。$'
3B66:0215 73 07 jnc 021Eh ; Jump if carry=0, CF=0(エラーなし)なら0021EHへ

3B66:0217 90 nop


ADVSHELL endp
;**********************************************************************************************
;メモリ解放エラー発生時
3B66:0218 sub_1 proc near
3B66:0218 loc_1: ; xref 3B66:0254
3B66:0218 E8 0069 call 0284h ; (0284) エラー文字列表示ルーチンへ

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0218 ; エラー文字列表示ルーチン
;##########################################################################

3B66:0284 sub_3 proc near
3B66:0284 B4 09 mov ah,9 ; DX=0368Hで飛んできた。文字列 'メモリーが解放できません。$'
3B66:0286 CD 21 int 21h ; DOS Services ah=function 09h 文字列の表示,DS:DXから$までの文字列を画面に表示
; display char string at ds:dx
3B66:0288 loc_10: ; xref 3B66:028A
3B66:0288 ,FA cli ; Disable interrupts 外部割込禁止
3B66:0289 F4 hlt ; Halt processor 割込がかかるまでCPUを停止させる
3B66:028A EB FC jmp short loc_10 ; (0288)
sub_3 endp

;メモリ解放エラー発生時処理終了
;**********************************************************************************************
;使われない処理?
3B66:021B 90 nop
3B66:021C loc_2: ; xref 3B66:021C
3B66:021C EB FE jmp short loc_2 ; (021C) 無限ループ
sub_1 endp

;メモリ解放成功時 プログラムロード準備ルーチン

3B66:021E loc_3: ; xref 3B66:0215
3B66:021E ,BE 03FA mov si,03FAH ; SI=03FAH
3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[03FAH],INT 0FEHの割込ベクタセグメントアドレス
3B66:0223 84 C0 test al,al ; (3B66:03FA=01H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03C0H=[03FBH]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=03A3H=[03FDH]
3B66:0230 83 C6 05 add si,5 ; SI=03FFH
3B66:0233 FE C8 dec al ; AL=00H
3B66:0235 74 18 jz 024Fh ; Jump if zero

3B66:0237 FE C8 dec al
3B66:0239 74 08 jz 0243h ; Jump if zero
3B66:023B FE C8 dec al
3B66:023D 75 10 jnz 024Fh ; Jump if not zero

3B66:023F B0 02 mov al,2 ; AL=02H
3B66:0241 EB 08 jmp short 024Bh ; (024B)

3B66:0243 loc_7: ; xref 3B66:0239
3B66:0243 2A C0 sub al,al ; AL=00H
3B66:0245 8B D9 mov bx,cx
3B66:0247 CD F1 int 0F1h ; ??INT Non-standard interrupt

3B66:0249 B0 01 mov al,1 ; AL=01H

3B66:024B loc_8: ; xref 3B66:0241
3B66:024B CD F1 int 0F1h ; ??INT Non-standard interrupt
3B66:024D EB D2 jmp short 0221h ; (0221)

3B66:024F loc_9: ; xref 3B66:0235, 023D
3B66:024F 56 push si ; SI退避,SI=03FFH
3B66:0250 E8 0005 call sub_2 ; (0258)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0250
;##########################################################################

3B66:0258 sub_2 proc near ; CX=03C0H,DX=03A3H(='MUSDRV.COM')
3B66:0258 0E push cs
3B66:0259 07 pop es ; CS=ES,パラメータブロックセグメントアドレス
3B66:025A FE 06 03A0 inc byte ptr [03A0h] ; (3B66:03A0=30H='0')インクリメントして31H='1'
3B66:025E ,BB 041E mov bx,041Eh ; BX=041EH,パラメータブロックオフセットアドレス
; パラメータブロックはCS:041EH
3B66:0261 C7 07 0000 mov word ptr [bx],0 ; DS:[041EH]=0000H ;041EH以下のメモリ書き換え
3B66:0265 89 4F 02 mov [bx+2],cx ; DS:[0420H]=CX=03C0H ;041E 00 00
3B66:0268 8C 5F 04 mov [bx+4],ds ; DS:[0422H]=DS ;0420 C0 03 DS DS 5C 00 DS DS
3B66:026B C7 47 06 005C mov word ptr [bx+6],5Ch ; DS:[0424H]=005CH ;0428 6C 00 DS DS
3B66:0270 8C 5F 08 mov [bx+8],ds ; DS:[0426H]=DS
3B66:0273 C7 47 0A 006C mov word ptr [bx+0Ah],6Ch ; DS:[0428H]=006CH
3B66:0278 8C 5F 0C mov [bx+0Ch],ds ; DS:[042AH]=DS
3B66:027B B8 4B00 mov ax,4B00h ; プログラムのロードと実行
; DS:DX==実行可能プログラムファイルのASCIIZパス名の位置,パス名はNULLで終わらなければならない。
; ES:BX=パラメータブロックの位置 (03C0=00 0D) ドライブ番号0H:カレント,リターンキーのキャラクターコード
3B66:027E CD 21 int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx INT 0F0Hのアドレスにロードした?
3B66:0280 BA 0383 mov dx,383h ; 文字列'プログラムが起動できません。(1)$'
3B66:0283 C3 retn
sub_2 endp

3B66:0253 5E pop si ; SI復帰,SI=03FFH
3B66:0254 72 C2 jc 0218h ; Jump if carry Set エラーなければCF=0でスルー,エラーがあればCF=1なので0218Hへ

;**********************************************************************************************
;プログラムロードエラー発生時
3B66:0218 sub_1 proc near
3B66:0218 loc_1: ; xref 3B66:0254
3B66:0218 E8 0069 call 0284h ; (0284) エラー文字列表示ルーチンへ

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0218 ; エラー文字列表示ルーチン
;##########################################################################

3B66:0284 sub_3 proc near
3B66:0284 B4 09 mov ah,9 ; DX=0383Hで飛んできた。文字列 'プログラムが起動できません。(0)$'
3B66:0286 CD 21 int 21h ; DOS Services ah=function 09h 文字列の表示,DS:DXから$までの文字列を画面に表示
; display char string at ds:dx
3B66:0288 loc_10: ; xref 3B66:028A
3B66:0288 ,FA cli ; Disable interrupts 外部割込禁止
3B66:0289 F4 hlt ; Halt processor 割込がかかるまでCPUを停止させる
3B66:028A EB FC jmp short loc_10 ; (0288)
sub_3 endp
;**********************************************************************************************
;プログラムロード成功時
3B66:0256 EB C9 jmp short 0221h ; (0221),SI=03FFH

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[03FFH]
3B66:0223 84 C0 test al,al ; (3B66:03FF=01H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03C4H=[0400H]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=03AEH=[0402H]
3B66:0230 83 C6 05 add si,5 ; SI=0404H
3B66:0233 FE C8 dec al ; AL=00H
3B66:0235 74 18 jz 024Fh ; Jump if zero

(省略)
3B66:024F loc_9: ; xref 3B66:0235, 023D
3B66:024F 56 push si ; SI退避,SI=0404H
3B66:0250 E8 0005 call sub_2 ; (0258)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0250
;##########################################################################

3B66:0258 sub_2 proc near ; CX=03C4H,DX=03AEH(='HARE.EXE')
3B66:0258 0E push cs
3B66:0259 07 pop es ; CS=ES,パラメータブロックセグメントアドレス
3B66:025A FE 06 03A0 inc byte ptr [03A0h] ; (3B66:03A0=31H='1')インクリメントして32H='2'
3B66:025E ,BB 041E mov bx,041Eh ; BX=041EH,パラメータブロックオフセットアドレス
; パラメータブロックはCS:041EH
3B66:0261 C7 07 0000 mov word ptr [bx],0 ; DS:[041EH]=0000H ;041EH以下のメモリ書き換え
3B66:0265 89 4F 02 mov [bx+2],cx ; DS:[0420H]=CX=03C4H ;041E 00 00
3B66:0268 8C 5F 04 mov [bx+4],ds ; DS:[0422H]=DS ;0420 C4 03 DS DS 5C 00 DS DS
3B66:026B C7 47 06 005C mov word ptr [bx+6],5Ch ; DS:[0424H]=005CH,第1FCB ;0428 6C 00 DS DS
3B66:0270 8C 5F 08 mov [bx+8],ds ; DS:[0426H]=DS
3B66:0273 C7 47 0A 006C mov word ptr [bx+0Ah],6Ch ; DS:[0428H]=006CH,第2FCB
3B66:0278 8C 5F 0C mov [bx+0Ch],ds ; DS:[042AH]=DS
3B66:027B B8 4B00 mov ax,4B00h ; プログラムのロードと実行
; DS:DX=パス名の位置,ES:BX=パラメータブロックの位置(03C4=02 20 31 0D)
;ドライブ番号2=B:半角スペース'1'リターンキー
3B66:027E CD 21 int 21h ; DOS Services ah=function 4Bh
; run progm @ds:dx, parm @es:bx INT 0F1Hのアドレスにロードした?
3B66:0280 BA 0383 mov dx,383h ; 文字列'プログラムが起動できません。(2)$'
3B66:0283 C3 retn
sub_2 endp

3B66:0253 5E pop si ; SI復帰,SI=0404H
3B66:0254 72 C2 jc 0218h ; Jump if carry Set エラーなければCF=0でスルー,エラーがあればCF=1なので0218Hへ
3B66:0256 EB C9 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[0404H]=02H
3B66:0223 84 C0 test al,al ; (3B66:0404=02H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03EAH=[0405H]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=0000H=[0407H]
3B66:0230 83 C6 05 add si,5 ; SI=0409H
3B66:0233 FE C8 dec al ; AL=01H
3B66:0235 74 18 jz 024Fh ; Jump if zero 0じゃないのでスルー
3B66:0237 FE C8 dec al ; AL=00H
3B66:0239 74 08 jz 0243h ; Jump if zero 0なので0243Hへ

(省略)
3B66:0243 loc_7: ; xref 3B66:0239
3B66:0243 2A C0 sub al,al ; AL=00H
3B66:0245 8B D9 mov bx,cx ; BX=03EAH(03EA=42 3A 5C 4D 55 53 5C 48 4F 2D 4F 50 4E 2E 4D 00)
;'B:\MUS\HO-OPN.M'
3B66:0247 CD F1 int 0F1h ; INT 0F1H ;HARE.EXEを実行

3B66:0249 B0 01 mov al,1 ; AL=01H

3B66:024B loc_8: ; xref 3B66:0241
3B66:024B CD F1 int 0F1h ; INT 0F1H ;AL=01Hで再びHARE.EXEを実行か?
3B66:024D EB D2 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[0409H]=01H
3B66:0223 84 C0 test al,al ; (3B66:0409=01H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03CAH=[040AH]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=03AEH=[040CH]
3B66:0230 83 C6 05 add si,5 ; SI=040EH
3B66:0233 FE C8 dec al ; AL=00H
3B66:0235 74 18 jz 024Fh ; Jump if zero 0なので024FHへ

(省略)
3B66:024F loc_9: ; xref 3B66:0235, 023D
3B66:024F 56 push si ; SI退避,SI=040EH
3B66:0250 E8 0005 call sub_2 ; (0258)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0250
;##########################################################################

3B66:0258 sub_2 proc near ; CX=03CAH,DX=03AEH(='HARE.EXE')
3B66:0258 0E push cs
3B66:0259 07 pop es ; CS=ES,パラメータブロックセグメントアドレス
3B66:025A FE 06 03A0 inc byte ptr [03A0h] ; (3B66:03A0=32H='2')インクリメントして33H='3'
3B66:025E ,BB 041E mov bx,041Eh ; BX=041EH,パラメータブロックオフセットアドレス
; パラメータブロックはCS:041EH
3B66:0261 C7 07 0000 mov word ptr [bx],0 ; DS:[041EH]=0000H ;041EH以下のメモリ書き換え
3B66:0265 89 4F 02 mov [bx+2],cx ; DS:[0420H]=CX=03CAH ;041E 00 00
3B66:0268 8C 5F 04 mov [bx+4],ds ; DS:[0422H]=DS ;0420 CA 03 DS DS 5C 00 DS DS
3B66:026B C7 47 06 005C mov word ptr [bx+6],5Ch ; DS:[0424H]=005CH ;0428 6C 00 DS DS
3B66:0270 8C 5F 08 mov [bx+8],ds ; DS:[0426H]=DS
3B66:0273 C7 47 0A 006C mov word ptr [bx+0Ah],6Ch ; DS:[0428H]=006CH
3B66:0278 8C 5F 0C mov [bx+0Ch],ds ; DS:[042AH]=DS
3B66:027B B8 4B00 mov ax,4B00h ; プログラムのロードと実行
; DS:DX=パス名の位置,ES:BX=パラメータブロックの位置(03CA=02 20 32 0D)
3B66:027E CD 21 int 21h ; DOS Services ah=function 4Bh =B:半角スペース'2'リターンキー
; run progm @ds:dx, parm @es:bx INT 0F2Hのアドレスにロードした?
3B66:0280 BA 0383 mov dx,383h ; 文字列'プログラムが起動できません。(3)$'
3B66:0283 C3 retn
sub_2 endp

3B66:0253 5E pop si ; SI復帰,SI=040EH
3B66:0254 72 C2 jc 0218h ; Jump if carry Set エラーなければCF=0でスルー,エラーがあればCF=1なので0218Hへ
3B66:0256 EB C9 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[040EH]=03H
3B66:0223 84 C0 test al,al ; (3B66:0404=03H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=0000H=[040FH]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=0000H=[0411H]
3B66:0230 83 C6 05 add si,5 ; SI=0413H
3B66:0233 FE C8 dec al ; AL=02H
3B66:0235 74 18 jz 024Fh ; Jump if zero 0じゃないのでスルー
3B66:0237 FE C8 dec al ; AL=01H
3B66:0239 74 08 jz 0243h ; Jump if zero 0じゃないのでスルー
3B66:023B FE C8 dec al ; AL=00H
3B66:023D 75 10 jnz 024Fh ; Jump if not zero 0なのでスルー
3B66:023F B0 02 mov al,2 ; AL=02H
3B66:0241 EB 08 jmp short 024Bh ; (024B)

(省略)
3B66:024B loc_8: ; xref 3B66:0241
3B66:024B CD F1 int 0F1h ; AL=02HでHARE.EXE?
3B66:024D EB D2 jmp short 0221h ; (0221)

3B66:0221 loc_4: ; xref 3B66:024D, 0256
3B66:0221 ,8A 04 mov al,[si] ; AL=[0413H]=01H
3B66:0223 84 C0 test al,al ; (3B66:0413=01H),AL=00Hでなければ,ZF=0
3B66:0225 75 03 jnz 022Ah ; Jump if not zero, ZF=0なら022AHへ
3B66:0227 loc_5: ; xref 3B66:0227
3B66:0227 EB FE jmp short loc_5 ; (0227)
3B66:0229 90 db 90h
3B66:022A loc_6: ; xref 3B66:0225
3B66:022A 8B 4C 01 mov cx,[si+1]  ; CX=03D6H=[0414H]
3B66:022D 8B 54 03 mov dx,[si+3] ; DX=03B7H=[0416H]
3B66:0230 83 C6 05 add si,5 ; SI=0418H
3B66:0233 FE C8 dec al ; AL=00H
3B66:0235 74 18 jz 024Fh ; Jump if zero 0なので024FHへ

(省略)
3B66:024F loc_9: ; xref 3B66:0235, 023D
3B66:024F 56 push si ; SI退避,SI=0418H
3B66:0250 E8 0005 call sub_2 ; (0258)

以下,その3に続く。

晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その1)はこちら
晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その3)はこちら

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作物の取扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その1)

2012-06-27 19:09:14 | レトロパソコンのお作法
もう2年になりますでしょうか,「晴れのちおおさわぎ!」(PC-98,カクテル・ソフト)のIPLからの立ち上げ後,起動するADVSHELL.COMの解析を試みておりましたが,ようやく自分としてはこれ以上時間をかけても新たな発見が見込まれないであろうというところまでの作業をすませましたので,とりあえず発表してしまいます。

SYMDEB.EXEでADVSHELL.COMのトレース実行を試みましたが,NP21では,-Tのトレースモードに入ったところで作動停止。T98-Nextでは,トレース実行ができないようで,いきなりプログラムの実行を完了してプログラムに基づくエラー表示。。無償使用できるようになった最新版Anex86では,実機より少し先でやはり作動停止。
そんなわけで,プログラムの流れは完全には検証できていません。

解析結果のフローチャートは以下のとおり。





コメント付きソースは6万字を超えたので,4回くらいに分けないとアップできません・・・。たった2,048バイトのプログラムなのに。私のコメントが過剰なのか?
次の行から,下はコメント付きソースの第1弾。先は長いよ。
なお,SOUCERによる逆アセンブルリストをベースにしています。

seg_a segment byte public
assume cs:seg_a, ds:seg_a


org 100h

ADVSHELL proc far

3B66:0100 start:
3B66:0100 E9 00FD jmp real_start ; (0200)
3B66:0103 00FD[00] db 253 dup (0)

;##########################################################################
;
; External Entry Point
;
;##########################################################################

;レジスタ群初期化
3B66:0200 real_start: ; xref 3B66:0100
3B66:0200 FA cli ; Disable interrupts 外部割込禁止
3B66:0201 8C C8 mov ax,cs ; AX=CS
3B66:0203 8E D8 mov ds,ax ; DS=AX
3B66:0205 8E D0 mov ss,ax ; SS=AX CS=DS=SS
3B66:0207 BC 0200 mov sp,200h ; SP=0200H
3B66:020A FB sti ; Enable interrupts 割込フラグをセット
; 次の命令の最後で、外部割込を可能に。
3B66:020B E8 055C call sub_14 ; (076A)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:020B
;##########################################################################

3B66:076A sub_14 proc near
3B66:076A E8 FEB1 call sub_7 ; (061E)

;##########################################################################
; SUBROUTINE
;
; 割込禁止等処理ルーチン~065CH,COPYキー,STOPキー,Ctrl-Cキーの無効化
; 致命的ディスクエラーに対する独自処理?,0514H:0512Hにファンクションコールにシステムコールアドレス確保?
; (MS-DOSシステムコールハンドブック,河西朝雄著,ナツメ社発行,'91/11/11,P.~)
; (MS-DOS エンサイクロペディア Volume2 リファレンス編,マイクロソフトプレス編,株式会社アスキー発行P.~)
; Called from: 3B66:076A
;##########################################################################

3B66:061E sub_7 proc near
3B66:061E FA cli ; Disable interrupts 外部割込禁止
3B66:061F ,BA 031D mov dx,offset int_06h_entry ; DX=031DH
3B66:0622 52 push dx ; DX退避
3B66:0623 B8 2505 mov ax,2505h ; 割込ベクタの設定,割込タイプ番号 05H COPYキー
3B66:0626 CD 21 int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
; DS:DX(031DH)=割り込み処理ルーチンのアドレス
; DS:031DH IRET 割込からのリターン命令
; COPYキー割込に何もせずリターン。以下,同様。

3B66:0628 5A pop dx ; DX復帰。DX=031DH
3B66:0629 52 push dx ; DX退避

3B66:062A B8 2506 mov ax,2506h ; 割込ベクタの設定,割込タイプ番号 06H STOPキー
3B66:062D CD 21 int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
; DS:DX(031DH)=割り込み処理ルーチンのアドレス
; DS:031DH IRET 割込からのリターン命令
; STOPキー割込に何もせずリターン。
3B66:062F 5A pop dx ; DX復帰。DX=031DH

3B66:0630 B8 2523 mov ax,2523h ; 割込ベクタの設定,割込タイプ番号 23H Ctrl-Cキー
3B66:0633 CD 21 int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
; DS:DX(031DH)=割り込み処理ルーチンのアドレス
; DS:031DH IRET 割込からのリターン命令
; Ctrl-Cキー割込に何もせずリターン。

3B66:0635 ,BA 02B6 mov dx,offset int_24h_entry ; DX=02B6H
3B66:0638 B8 2524 mov ax,2524h ; 割込ベクタの設定,割込タイプ番号 24H 致命的ディスクエラー発生
3B66:063B CD 21 int 21h ; DOS Services ah=function 25h
; set intrpt vector al to ds:dx
; DS:DX(02B6H)=割り込み処理ルーチンのアドレス

3B66:063D B8 3521 mov ax,3521h ; 割込ベクタの取得 割込番号 21H システムコール
3B66:0640 CD 21 int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
; ES:BX=割込ルーチンのアドレス

3B66:0642 89 1E 0512 mov word ptr data_81,bx ; DS:0512Hのアドレスのメモリに割込ハンドルのオフセットアドレスを代入,DS:0512H=BX
3B66:0646 8C 06 0514 mov word ptr data_81+2,es ; DS:0514Hのアドレスのメモリに割込ハンドルのセグメントアドレスを代入,DS:0514H=ES
; 割込ハンドルES:BX=[0514H]:[0512H]

3B66:064A BA 032E mov dx,32Eh ; DX=032EH
3B66:064D ,BB 0084 mov bx,data_2e ; BX=0084H
BB data16 MOV BX,data16 word move data to BX
3B66:0650 2B C0 sub ax,ax ; AX=0000H
3B66:0652 8E C0 mov es,ax ; ES=0000H
3B66:0654 26: 89 17 mov es:[bx],dx ; ES:[0084H]=032EH, 0086:0084は本来のシステムコールアドレス,システムコールの無効化?
3B66:0657 26: 8C 5F 02 mov es:[bx+2],ds ; ES:[0086H]=DS, [0086H]:[0084H]=DS:032EH, 032EHは,PUSHF
3B66:065B FB sti ; Enable interrupts 割込フラグセット,次の命令の最後で割込を可能に
3B66:065C C3 retn
sub_7 endp

;キーバッファ設定
3B66:076D 2B C0 sub ax,ax ; AX=0000H
3B66:076F 8E C0 mov es,ax ; ES=0000H
3B66:0771 26: 80 0E 0500 20 or byte ptr es:[0500H],20h ; 98のワークエリアのセグメント0000H,オフセット0500Hの第5ビットを1にする
; キーバッファオーバーフロー時にビープを鳴らさない設定
; http://www.webtech.co.jp/company/doc/undocumented_mem/memsys.txt
;画面クリア
3B66:0777 ,BA 07A4 mov dx,offset data_96 ; (3B66:07A4='ESC[2J') 画面をクリアし,カーソルをホームに移動
3B66:077A B4 09 mov ah,9 ; 文字列の表示,DS:DX=07A4Hで始まる$までの文字列を画面に表示する
3B66:077C CD 21 int 21h ; DOS Services ah=function 09h
; display char string at ds:dx 1Bはエスケープキーの文字コード

3B66:077E E8 FEDD call sub_8 ; (065E)

;##########################################################################
; SUBROUTINE
; ストリング2000H本ノックルーチン
; Called from: 3B66:077E
;##########################################################################

3B66:065E sub_8 proc near
3B66:065E FC cld ; Clear direction 割込フラグをクリア,外部割込禁止
3B66:065F B8 A000 mov ax,0A000h ; AX=0A000H テキストVRAMセグメント
3B66:0662 8E C0 mov es,ax ; ES=0A000H
3B66:0664 2B FF sub di,di ; DI=0000H
3B66:0666 B8 0020 mov ax,20h ; AX=0020H
3B66:0669 B9 1000 mov cx,1000h ; CX=1000H
3B66:066C F3/ AB rep stosw ; Rep when cx >0 Store ax to es:[di] ES:[DI]から始まるメモリにAXレジスタの内容0020Hをストア
; CXレジスタの回数分1000H回繰り返して終了。0A000:0000HからAXレジスタの内容を1000H回分ストア
; TVRAMに1000H回0020H(2バイト)をストア,終了時DI=2000H
3B66:066E B8 00E1 mov ax,0E1h ; AX=00E1H
3B66:0671 B9 1000 mov cx,1000h ; CX=1000H,終了時DI=4000H
3B66:0674 F3/ AB rep stosw ; Rep when cx >0 Store ax to es:[di] 同上。ただし,ストアされる内容は00E1H
3B66:0676 C3 retn
sub_8 endp

;メーカー名,タイトル表示,プログラム読み込み中表示
3B66:0781 ,BA 07A9 mov dx,07A9H ; (3B66:07A9=' [mAdvShell for ')
3B66:0784 B4 09 mov ah,9 ; 文字列の表示,DS:DXで始まる$までの文字列を画面に表示する
3B66:0786 CD 21 int 21h ; DOS Services ah=function 09h
; display char string at ds:dx

3B66:0788 B4 12 mov ah,12h ; カーソルの表示停止(UNDOCUMENTED 9801/9821,P.65)
3B66:078A CD 18 int 18h ; ROM basic

3B66:078C B0 0F mov al,0Fh ;DISP ENABLE テキストとグラフィック両方の画面表示のON。
; http://www.webtech.co.jp/company/doc/undocumented_mem/io_disp.txt
3B66:078E E6 68 out 68h,al ; port 68h I/O Non-standard

3B66:0790 E8 FF8B call sub_12 ; (071E)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0790
;##########################################################################
;カレントドライブ確認ルーチン
3B66:071E sub_12 proc near
3B66:071E B4 19 mov ah,19h ;Current Disk カレントドライブ番号の取得
3B66:0720 CD 21 int 21h ; DOS Services ah=function 19h
; get default drive al (00H=A:,01H=B:)
3B66:0722 84 C0 test al,al ; ドライブ番号のANDを取る。
3B66:0724 74 1F jz loc_26 ; Jump if zero ドライブAならZF=1になり,0745Hへ

;***********************************************************************************************
;ここからエラー表示
;起動ドライブエラー
3B66:0726 BA 086A mov dx,86Ah ; ドライブAでない場合,DX=086AH
3B66:0729 E8 FAEC call sub_1 ; (0218)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0729 ;異常時文字列表示ルーチン
;##########################################################################

3B66:0218 sub_1 proc near
3B66:0218 loc_1: ; xref 3B66:0254
3B66:0218 E8 0069 call sub_3 ; (0284) エラー文字列表示ルーチンへ

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0218 ;起動ドライブ違いエラールーチン
;##########################################################################

3B66:0284 sub_3 proc near
3B66:0284 B4 09 mov ah,9 ; DX=086AHで飛んできた。文字列 'ドライブA:から起動しなおしてください。'
3B66:0286 CD 21 int 21h ; DOS Services ah=function 09h 文字列の表示,DS:DXから$までの文字列を画面に表示
; display char string at ds:dx
3B66:0288 loc_10: ; xref 3B66:028A
3B66:0288 ,FA cli ; Disable interrupts 外部割込禁止
3B66:0289 F4 hlt ; Halt processor 割込がかかるまでCPUを停止させる
3B66:028A EB FC jmp short loc_10 ; (0288)
sub_3 endp

3B66:021B 90 nop
3B66:021C loc_2: ; xref 3B66:021C
3B66:021C EB FE jmp short loc_2 ; (021C) 無限ループ
sub_1 endp

;以上,エラー表示終了
;**********************************************************************************************
;カレントドライブAのときここへ
3B66:0745 loc_26: ; xref 3B66:0724
3B66:0745 E8 FF30 call sub_9 ; (0678) ドライブAからの起動確認後ここに来た。AL=00H確認ずみ。

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0745
;##########################################################################

3B66:0678 sub_9 proc near
3B66:0678 E8 00D5 call sub_13 ; (0750)

;##########################################################################
; SUBROUTINE
;
; Called from: 3B66:0678, 074C ;ディスクリザルト,ディスクリセット+ディスク確認呼出ルーチン
;##########################################################################

3B66:0750 sub_13 proc near
3B66:0750 2B C0 sub ax,ax ; AX=0000H
3B66:0752 8E C0 mov es,ax ; ES=0000H
3B66:0754 BB 0564 mov bx,0564 ; BX=0564H
3B66:0757 B0 C0 mov al,0C0h ; AX=00C0H
3B66:0759 B9 0004 mov cx,4 ; CX=0004H カウンタを4回にセット

3B66:075C locloop_27: ; xref 3B66:0762
3B66:075C 26: 08 07 or es:[bx],al ; DISK RESULT
; 98のワークエリア0000H:0564Hの第6,7ビットを1にする。
; 第1FDDのInterrupt Codeの0と1をセット。
; http://www.webtech.co.jp/company/doc/undocumented_mem/memsys.txt
3B66:075F 83 C3 08 add bx,8 ; BX=056CH
3B66:0762 E2 F8 loop locloop_27 ; Loop if cx > 0
;(ループ内容)
;残り3回
3B66:075C 260807 OR ES:[BX],AL ; 98のワークエリア0000H:056CHの第6,7ビットを1にする。
; 第2FDDのInterrupt Codeの0と1をセット。
3B66:075F 83C308 ADD BX,0008H ; BX=0574H
3B66:0762 E2F8 LOOP 075CH ; CXの値を1減じて0でなければ065CHへ。CX=0002H。
;残り2回
3B66:075C 260807 OR ES:[BX],AL ; 98のワークエリア0000H:0574Hの第6,7ビットを1にする。
; 第3FDDのInterrupt Codeの0と1をセット。
3B66:075F 83C308 ADD BX,0008H ; BX=057CH
3B66:0762 E2F8 LOOP 075CH ; CXの値を1減じて0でなければ065CHへ。CX=0001H。
;残り1回
3B66:075C 260807 OR ES:[057C],AL ; 98のワークエリア0000H:057CHの第6,7ビットを1にする。
; 第4FDDのInterrupt Codeの0と1をセット。
3B66:075F 83C308 ADD BX,0008H ; BX=0584H
3B66:0762 E2F8 LOOP 075CH ; CXの値を1減じて0なので無視。CX=0000H。

3B66:0764 B4 0D mov ah,0Dh ; Disk Reset ディスクのリセット
3B66:0766 CD 21 int 21h ; DOS Services ah=function 0Dh 全ファイルバッファの内容をディスクに書き出し,
; flush disk buffers to disk ファイルバッファを空にする。(DOS6.2PRM P.61)
3B66:0768 C3 retn ; AX=0D0CH
sub_13 endp


3B66:067B 2A C0 sub al,al ;AX=0D00H
3B66:067D E8 006A call sub_11 ; (06EA)

;##########################################################################
; SUBROUTINE(ソーサーが作ってくれなかったサブルーチン)
;
; Called from: 3B66:067D ; ディスク確認ルーチン
;##########################################################################

;ドライブAディスク確認ルーチン~057D,AX=0D00H
3B66:06EA 1E PUSH DS
3B66:06EB 07 POP ES ; DS=ES
3B66:06EC 50 PUSH AX ; AX退避,AX=0D00H。
3B66:06ED 8AE0 MOV AH,AL ; AX=0000H。
3B66:06EF 054160 ADD AX,6041H ; AX=6041H。
3B66:06F2 88269F08 MOV [089FH],AH ; DS:[089FH]=60H 'A' ; [089FH]のメモリに全角Aの文字コードを入力した
3B66:06F6 A2FA08 MOV [08FAH],AL ; DS:[08FAH]=41H 'A' ; [08FAH]のメモリに半角Aの文字コードを入力した
3B66:06F9 58 POP AX ; AX=0D00H ; AX復帰。AX=0D00H
3B66:06FA BB0009 MOV BX,0900H ; BX=0900H
3B66:06FD 8BFB MOV DI,BX ; DI=0900H
3B66:06FF B90100 MOV CX,0001H ; CX=0001H
3B66:0702 BA0300 MOV DX,0003H : DX=0003H
3B66:0705 57 PUSH DI ; DI退避
3B66:0706 CD25 INT 25H ; Absolute disk read, drive al
; if disk under 32MB, dx=start
; cx=#sectors, ds:bx=buffer
; else cx=-1, ds:dx=parm block
; (MS-DOS エンサイクロペディア Volume2 リファレンス編,マイクロソフトプレス編,株式会社アスキー発行P.813~)
; (応用MS-DOS改訂新版,村瀬康治著,株式会社アスキー発行,'89/12/31,P189~)
; (MS-DOSシステムコールハンドブック,河西朝雄著,ナツメ社発行,'91/11/11,P.60~)
; ftp://ftp.abk.nu/pub/text/dos/msdos.txt
; 物理セクタ番号によるディスク読み出し
; AL=ドライブ番号(A:=00H,B:=01H,,,),AL=00HなのでA:
; BX=ディスク転送アドレスのオフセット,読み出すデータの先頭アドレス DS:BX=DS:0900H
; 読み出すセクタ数 CX=0001H 1セクタ
; 読み出しを開始する相対的(論理)セクタ番号 DX=003H 3セクタ
; ディレクトリ領域を正常に読めればCF=0
; セグメントレジスタ(CS,SS,DS,ES)以外の全てのレジスタ破壊。
; フラグはスタックに積まれる(PUSHF)ので,終了後はPOPFまたはADD SP,2。
; ディスク操作が正しく行われるとCF=0
; DS:0900Hに論理セクタ番号3(ディレクトリエントリ)のデータ'ハレノチオオサワギA)',00H*4以下がロードされた。

3B66:0708 58 POP AX ; フラグレジスタをAXに載せる
3B66:0709 5F POP DI ; DI=0900H
3B66:070A BAFFFF MOV DX,0FFFFH ; DX=0FFFFH
3B66:070D 720C JC 071BH ; Jump if carry Set,CF=1(正常に読めない)なら071BHへ。
3B66:070F BEF008 MOV SI,08F0H ; ADVSHELL.COMの[08F0H]には,
; 'ハレノチオオサワギA)',00H*4が書かれている。
;[SI]=CA DA C9 C1 B5 B5 BB DC B7 DE 41 29 00 00 00 00
3B66:0712 B90800 MOV CX,0008H ;
3B66:0715 FC CLD ;ディレクションフラグを0(増加)にリセット
3B66:0716 F3/ A7 repe cmpsw ; Rep zf=1+cx >0 Cmp [si] to es:[di] ; ZF=1で,かつCXが0でない間CXを1減じつつCMPSWを繰り返す。
; ES=DS:[DI]とDS:[SI] にある一致していないワードを探す。
; データブロックの比較
; DS:[SI]とES:[DI]で示されるメモリをワード値で比較し,
; SIとDIの値を2増加させる。8ワード分比較する。
; ES:[DI]には論理セクタ番号3(ディレクトリエントリ)
; 先頭データ'ハレノチオオサワギA)',00H*4が格納されているので一致する
3B66:0718 7501 JNE 071BH ; Jump if not zero, ZF=0(不一致)なら071BHへ
;**********************************************************************************************
;正常時処理
3B66:071A 42 INC DX ; DX=0000H,ZF=1
;エラー時は1行飛ばし 3B66:071B 8BC2 MOV AX,DX ; 正常時AX=0000H,ZF=1,エラー時AX=0FFFFH,ZF=0
3B66:071D C3 RET ;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3B66:0680 85 C0 test ax,ax ; AX=0000HならZF=1,エラー時AX=0FFFFHなのでZF=0
3B66:0682 75 05 jnz 0689H ; Jump if not zero ZF=0ならRET直行
3B66:0684 B0 01 mov al,1 ; ZF=1(一致)なら,AL=01H。AX=0001H。
3B66:0686 E8 0061 call sub_11 ; (06EA) Bディスク確認ルーチンへ。

;ドライブBディスク確認ルーチン
以下,第2弾へ。
3B66:06EA 1E PUSH DS ;
3B66:06EB 07 POP ES ; DS=ES
3B66:06EC 50 PUSH AX ; AX退避,AX=0001H。
3B66:06ED 8AE0 MOV AH,AL ; AX=0101H
3B66:06EF 054160 ADD AX,6041H ; AX=6142H
3B66:06F2 88269F08 MOV [089FH],AH ; DS:[089FH]=61H 'B'
3B66:06F6 A2FA08 MOV [08FAH],AL ; DS:[08FAH]=42H 'B'
3B66:06F9 58 POP AX ; AX=0001H
3B66:06FA BB0009 MOV BX,0900H ; BX=0900H
3B66:06FD 8BFB MOV DI,BX ; DI=0900H, 読み出したデータの先頭アドレス
3B66:06FF B90100 MOV CX,0001H ; CX=0001H, 1セクタ読み出し
3B66:0702 BA0300 MOV DX,0003H : DX=0003H, 論理セクタ3(ディレクトリエントリ)のデータ
3B66:0705 57 PUSH DI ; DI退避
3B66:0706 CD25 INT 25H ; アブソリュートディスクリード
; AL=ドライブ番号(A:=00H,B:=01H,,,),AL=01HなのでB:
3B66:0708 58 POP AX ; フラグレジスタをAXに載せる
3B66:0709 5F POP DI ; DI=0900H
3B66:070A BAFFFF MOV DX,0FFFFH ; DX=0FFFFH
3B66:070D 720C JB 071BH ; CF=1(正常に読めない)なら071BHへ。
3B66:070F BEF008 MOV SI,08F0H ; DS:[08F0H]には,'ハレノチオオサワギB)',00H*4が書かれている。
; 06F6HでA→Bに書き換えずみ
; [SI]=CA DA C9 C1 B5 B5 BB DC B7 DE 42 29 00 00 00 00
3B66:0712 B90800 MOV CX,0008H ;
3B66:0715 FC CLD ; ディレクションフラグを0(増加)にリセットした。
3B66:0716 F3/ A7 repe cmpsw ; Rep zf=1+cx >0 Cmp [si] to es:[di]
; ZF=1で,かつCXが0でない間CXを1減じつつCMPSWを繰り返す。
; ES:[DI]とDS:[SI] にある一致していないワードを探す。
; データブロックの比較
; DS:[SI]とES:[DI]で示されるメモリをワード値で比較し,
; SIとDIの値を2増加させる。8ワード分比較する。
; ES:[DI]には論理セクタ番号3(ディレクトリエントリ)
; 先頭データ'ハレノチオオサワギB)',00H*4が格納されている。
3B66:0718 7501 JNE 071BH ; ZF=0(データ不一致)なら071BHへ。DX=0FFFFH
3B66:071A 42 INC DX ; DX=0000H
3B66:071B 8BC2 MOV AX,DX ; AX=0000H,ZF=1,0718Hから来たときは,AX=0FFFFH,ZF=0
3B66:071D C3 RET ; 0689Hへ復帰。

3B66:0689 loc_ret_22: ; xref 3B66:0682
3B66:0689 C3 retn
sub_9 endp

3B66:0748 85 C0 test ax,ax ; AX=0000Hなので,ZF=1
3B66:074A 75 E0 jnz 072CH ; Jump if not zero ,ZF=1なのでスルー
; エラー時は072CHへ
;**********************************************************************************************
エラー時表示ルーチン
3B66:072C loc_25: ; xref 3B66:074A
3B66:072C ,BA 0896 mov dx,0896h ;'ドライブA:のディスクを確認してください。$'
3B66:072F B4 09 mov ah,9 ; Bディスク確認エラーなら06F2Hで089FHをAからBに書き換えずみ
3B66:0731 CD 21 int 21h ; DOS Services ah=function 09h 文字列の表示
; display char string at ds:dx DXを先頭アドレスとする$までの文字列
3B66:0733 B4 11 mov ah,11h ; カーソルの表示開始(UND P.65)
3B66:0735 CD 18 int 18h ; ROM basic
3B66:0737 E8 FBE4 call sub_6 ; (031E)キー入力確認ルーチンへ

;キー入力確認ルーチン~0637H
3B66:031E B401 MOV AH,01H ;キーバッファ状態のセンス 出力 BH=00 キー入力データなし
3B66:0320 CD18 INT 18H ;(UNDOCUMENTED 9801/9821,P.41)  BH=01 キー入力データあり
;AH=キーコード,AL=キーデータ
;キーバッファにキー入力データがなければすぐに終了する。
3B66:0322 53 PUSH BX ;BX=BH00H
3B66:0323 B400 MOV AH,00H ;キーデータの読み出し(1文字の入力待ち)
3B66:0325 CD18 INT 18H ;(UNDOCUMENTED 9801/9821,P.40) AH=キーコード,AL=キーデータ
;入力を待つので進まない。
3B66:0327 5B POP BX ;BX=BH00H
3B66:0328 84FF TEST BH,BH ;キー入力なしならZF=1,キー入力ありZF=0
3B66:032A 75F2 JNE 021EH ;キー入力あり(ZF=0)なら,021EHへ。無限ループ?
3B66:032C C3 RET ;

3B66:073A B4 12 mov ah,12h ; カーソルの表示停止
3B66:073C CD 18 int 18h ; ROM basic,(UNDOCUMENTED 9801/9821 小高輝真・河野健著 株式会社インプレス発行 '94/03/21,P.65)
3B66:073E ,BA 08C2 mov dx,08C2h ; (3B66:08C2='全角スペース21個',0DH,'$')
3B66:0741 B4 09 mov ah,9 ; '$'検出までの文字列の表示
3B66:0743 CD 21 int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
エラー時表示ルーチン終了
;**********************************************************************************************

3B66:074C E8 0001 call sub_13 ; (0750)

以下,晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その2)に続く。
晴れのちおおさわぎ!(PC-98,カクテル・ソフト)ADVSHELL.COM解析(その3)はこちら

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作物の取扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

FD解析ソフトまたはFD解析ツールについて

2012-06-19 13:22:12 | レトロパソコンのお作法
以前,いや驚いたでご紹介した,国立国会図書館内の,電子情報の長期利用保証に関する 平成 18 年度調査報告書内の4. FDマイグレーションの調査の箇所を読んだときのことです。

DiskExplorerNeko Project IIなどのフリーソフトはもちろん,「システムポート社のファイルコンバートソフト『コンバートスター16』」とか,メーカー名並記で特定企業の商品を明記することを避けておらず,FDデータのマイグレーションに必要な情報を広く開示する姿勢に感動しました。

ところが,「FD解析ソフト」,「FD解析ツール」に関しては,「FD の詳細調査に当たっては、FDの記録情報をトラック単位、セクタ単位に読み書き、移動等が可能な環境(PC-98 とFD 解析ソフト)を用いて実施した。」などとマイグレーション作業において明らかに使用されており,「マイグレーション不可となった FD の詳細調査」の中では,「1DD」規格の FD のイメージ作成や,データ異常のために不可となったFDへの対処においても大活躍の超重要ツールであるにもかかわらず,メーカー名も名称もまったく明らかにされてませんでした。

「FDの記録情報をトラック単位、セクタ単位に読み書き、移動等が可能な環境(PC-98 とFD 解析ソフト)」という表現から,分かる人には分かるものの,多額の税金を投じた調査結果の報告において,重要な働きをしている「FD解析ソフト」,「FD解析ツール」が何であるかを明記しないのはあまりに不親切だ!と不満に思っておりました。

その後,国会図書館の報告書について,しばらく忘れていたのですが,ふと思い立って今日,その後の調査を見たところ,フロッピーディスクのマイグレーション作業についての追加報告を含む平成19年度電子情報の長期利用保証調査に関する調査報告書 第1.1版 平成20年3月31日内の(5)問題 FDの再調査詳細の項目に,ついに発見しました。報告書の18頁,データでは21頁部分です。



ジャジャーン!出た!
メーカー名も商品名も明らかにしてはもらえていないが,そこにはしっかりと,
「Disk Analyzer Wizard V3/98 Ver.1.0 Format Reproduce Editor&Intelligent Analyzer」の文字が。

それにしても,FDDがDrive7って,ちょっと増設し過ぎでしょ。
2013/06/14追記
ManualモードでFDDを640KBで指定するとDrive7って表示されました。
そういう仕様なんですねー。
2013/06/14追記



(注・画像はいずれも報告書から引用しました)

キター!当時は知らない者のない西側の魔術師!
もはやメーカーでもサポートしていないあのツールが,国会図書館で活用されてる!
しかも活躍してるし!

まあこれで,安心してうちのサイトでも,国立国会図書館公認ツールWizardの使い方解説とかも少しは書けそうってもんです。
そんなことしてると,またゲームレビューが遅延するわけですが。

2013/06/14追記
懸案のWIZARD記事,書きました。
WIZARD V5 ファイラーバックアップ編
2013/06/14追記終了

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作物の取扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

「晴れのちおおさわぎ」ゲームディスクをDiskExplorerで見てみる

2011-01-24 21:27:04 | レトロパソコンのお作法
フロッピーディスクのブートセクタ分析の記事に,かかっくんさんからコメントを頂戴しまして,何とその記事の中で私が試みた作業である,D88ファイルをDiskExplorerで開くことはできないというご指摘をいただきました。

ガーン。
顔に縦線を入れつつ,Virtual Floppy Image Converterで,「晴れのちおおさわぎ」AディスクのディスクイメージをD88→BKDSK形式に変換してみました。

まず,D88形式のディスクイメージを開いてみますと,やはりエラー表示。


次に,BKDSK形式のディスクイメージを開いてみます。何か開き方を聞いてきますがよく分からないので言われるままにします。


すると,


何ということでしょう。ブートセクタのデータなんて分析するまでもなく,ディスク内のデータが表示されてしまいました。
嬉しいのに悔しい,ひぃっ,ビクンビクンてところでしょうか。それは下品だろ。

ちなみに,カクテルソフトを初めとするアイデス系ユーザーなら,DOSからフロッピーを読もうとしたときの「かっくん,かっくん」は皆さんご経験のことかと思います。
なので,1枚目のディスクからプロテクト情報が消えたBKDSK形式のイメージを用いてのゲーム起動はできまいと思い,試してみました。



っておい!普通に起動してるし。

いやいや,オープニングは見られるけど,先へ進めないってのもよくあるパターンだし。



・・・どうやら普通にプレイできるみたいです。

何だったんだろう,アイデス系のプロテクトって・・・。

(11/01/26追記・ADVSHELL.COMのプログラムを解析した結果,冒頭部分に置かれた割り込みベクタ設定処理群の中で致命的なディスクエラー発生の割り込み処理を自前のプログラムで乗っ取ることにより,かっこんディスクを普通に読めるディスクとして取り扱っているらしいことが判明しました。MS-DOS上のEXEあるいはCOMファイルの逆アセンブラであるSDASM(こだまさん開発)では,割り込みベクタを乗っ取ったプログラム部分の逆アセンブルが行われなかったため,現在,ちまちま逆ハンドアセンブル中です。でも,かなりの確率で正解の自信ありです。)

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

ご無沙汰しております

2010-12-22 18:22:06 | レトロパソコンのお作法
今年は赤字決算の自営業者です。

さて,何とかIPLを解析した「晴れのちおおさわぎ」でしたが,IPLによって飛ばされた先のADVSHELL.COMの解析に手間取ってしまいました,ってまだ終わってないし。

IPLの解析同様,実機上でWizardV5を使って逆アセンブルした結果をテキスト化し,コメントを付けてプログラムの流れを理解するという作業をしていたのですが,MS-DOS上のEXEあるいはCOMファイルの逆アセンブラであるSDASM(こだまさん開発)を使ってみると,こりゃすごい。
今まで逆アセンブル結果からちまちま拾っていたCALL命令の飛び先,戻り先まで含めて,プログラムの流れを楽々追える。

と,喜んだのも束の間,逆アセンブルリストには謎の命令が。

2305:06BD 0FBE cts 0BEh

CTSって何?
コール元に戻る直前にこの命令があったので,すごく気になる。

ネットで検索してもニーモニックでCTSと書かれている記事はほとんどない。
解説のありそうな本を何冊か入手しても書かれていない。

万策尽きたかと思われた中,ようやくCTSの解説された書籍を入手。
「80x86 80x87―ファミリー・テクニカルハンドブック」
Robert L. Hummel (著), 槌田 浩一 (翻訳) ,技術評論社 (1993/11)刊。

答はあっけなかった。
「CTS
タスク・スイッチ・フラグ(TS)のクリア :Clear Task Switch Flag
CTSはCLTSの別ニーモニックである。命令の内容はCLTSの項目を参照。」
とある(337ページ)。

で,
「CLTS
タスク・スイッチ・フラグ(TS)のクリア :Clear Task Switch Flag in CR0/MSW
CLTSは,CR0制御レジスタ(80386と80486の場合)やマシン・ステータス・ワード(MSW)(80286の場合)のタスク・スイッチ(TS)フラグをクリアする。
タスク・スイッチ・フラグは,タスク・スイッチが起こるたびにプロセッサによってセットされるが,クリアするには,この命令を使わなければならない。オペレーティング・システムは,このフラグを利用して,新しいタスクがシステム資源にアクセスする前に,(数値演算コプロセッサの状態などの)必要な情報を保存することができる。」とのこと(329ページ)。

意味が分かりません(T_T)

最新のインテルの仕様書
IA-32 インテル ® アーキテクチャソフトウェア・デベロッパーズ・マニュアル中巻 A:命令セット・リファレンス A-Mの129ページによると,

「CLTS―Clear Task-Switched Flag in CR0
オペコード 0F 06
命令 CLTS
説明 CR0 の TS フラグをクリアする。

説明
CR0 レジスタ内のタスクスイッチ(TS)フラグをクリアする。この命令は、オペレーティング・システム内で使用することを目的としている。これは CPL = 0 でのみ実行できる特権命令である。この命令は、保護モード向けの初期化を可能にするため、実アドレスモードで実行できるようになっている。
プロセッサはタスクスイッチが行われるたびに TS フラグをセットする。このフラグは、マルチタスキング・アプリケーションでの FPU コンテキストのセーブを同期させるために使用される。このフラグの詳細については、『IA-32 インテル ® アーキテクチャ・ソフトウェア・デベロッパーズ・マニュアル、下巻』の第 2 章の「制御レジスタ」の TS フラグに関する説明を参照のこと。」
とある。
マルチタスク処理をするときに必要なフラグのようです。

IA-32 インテル® アーキテクチャソフトウェア・デベロッパーズ・マニュアル下巻:システム・プログラミング・ガイドの54ページ以下を読んだけど,制御レジスタなんて初めて聞いたからわけ分かんね。8086CPUにもあるんだろうか。

PC-9801VM以降という範囲でいえば,CPUは8086互換どまりで,80286以上は予定してないだろうから,結局,8086CPUにおけるCTS命令の詳細は分からず終い。
何とも不完全燃焼ですが,まあとりあえず逆アセンブルリストからまったく知らないマシン語が消えたのは何より。
年内に「晴れのちおおさわぎ」を終わらせないと,今年はレビューできるゲームがなくなってしまう・・・。

「晴れのちおおさわぎ」IPL分析(後半)

2010-11-17 22:50:24 | レトロパソコンのお作法
後半です。
「晴れのちおおさわぎ」IPL分析(前半)でもそうですが,Tabキーで設けた落差がHTMLには反映されないんですかね。
読みにくいですが,読む気のある人にとってはさほどの障害にはならんでしょう。

B000:0050からの続き。

;ディスク読み出し
B000:0052 E8F100 CALL 0146H ;ディスク読み出しサブルーチン呼出し~01A5H +++++++++++++++++

;ディスク読み出しサブルーチン
;(UNDOCUMENTED 9801/9821 小高輝真・河野健著 株式会社インプレス発行 '94/03/21,P.181~)
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.25)
;(PC-9801プログラマーズBible第2版,東京理科大学EIC編,技術評論社刊 '96/08/05 P.264~,P.276~)
B000:0146 06 PUSH ES ;ES退避
B000:0147 2BC0 SUB AX,AX ;AX=0000H
B000:0149 8EC0 MOV ES,AX ;ES=0000H
B000:014B 26A08405 MOV AL,ES:[0584H] ;disk_boot ALにブートドライブ情報を代入。
;0000H:0584HにはOSのブートしたディスク装置の情報が書かれている。
;0584Hの数値は下位4ビットがUA(ユニット番号,Unit Adress),
;    上位4ビットがDA(デバイスタイプ識別コード,
; Drive Adress)。
;ex. 90H=1001 0000
; UA 0000 ドライブ1
; 0001 ドライブ2
; 0010 ドライブ3
; 0011 ドライブ4
;DA アクセスモード 640KB 0xxx
; 1MB/HDD 1xxx
; ハードディスク x000
; 1MBインターフェース x001
; 640KBインターフェース x111
B000:014F B456 MOV AH,56H ;DISK BIOS(シングルトラック(bit7=0),
;倍密度MFM(bit6=1),8回リトライ(bit5=0),
;シーク動作する(bit4=1)),データ読み出し。
B000:0151 8BF8 MOV DI,AX ;DI=56UAH DISK BIOS格納AX退避
B000:0153 B86000 MOV AX,0060H ;
B000:0156 8EC0 MOV ES,AX ;ES=0060H 読み出すセグメント
B000:0158 2BED SUB BP,BP ;BP=0000H 読み出すオフセット
;(データバッファ領域先頭アドレス,ES:BP=0060H:0000H)
B000:015A BB0004 MOV BX,0400H ;BX=0400H 読み込むバイト数(1024バイト),データ長(DTL)
B000:015D B90003 MOV CX,0300H ;CX=0300H CH(N)=03H,CL(C)=00H(シリンダNo.0,セクタ長1024バイト(2の(3+7)乗))

;FATセクタ読み出し
B000:0160 BA0200 MOV DX,0002H ;DX=0002H DH(H)=00H,DL(R)=02H(ヘッドNo.0,セクタNo.2)FAT読み出し
B000:0163 E85EFF CALL 00C4H ;ディスク読み出しサブルーチン2呼出し ~00DD++++++++++++++++++

;ディスク読み出しサブルーチン2(正常に読み出せるまで5回トライ,成功すればCF=0,AX=0000H,
;失敗すればCF=1,AX=0FFFFH)
B000:00C4 BE0500 MOV SI,0005H ;カウンタを5回にセットした。
B000:00C7 8BC7 MOV AX,DI ;AXを復帰(0151Hで退避させたDISK BIOS格納AX)。
;MOV AH,56H(データの読み出し),
;MOV AL,90(ドライブ1)
; or91(ドライブ2)
B000:00C9 CD1B INT 1BH ;正常に読み出せればAH=00,CF=0
;Drive Not ReadyならAH=60,CF=1
B000:00CB 730E JNB 00DBH ;正常に読めた(CF=0)とき,00DBHへ。-----------------------------------
B000:00CD 8BC7 MOV AX,DI ;正常に読めなかったとき(CF=1),再度AXを復帰。00C7のやり直し。
B000:00CF B407 MOV AH,07H ;DISK BIOS RECALIBRATE
B000:00D1 CD1B INT 1BH ;ヘッドのシリンダ0への移動
B000:00D3 4E DEC SI ;カウンタを1減らす。
B000:00D4 75F1 JNE 00C7H ;ZF=0(カウンタ残あり)のとき,00C7Hへ。-----------------------------
B000:00D6 B8FFFF MOV AX,0FFFFH ;ZF=1(正常に読めず,カウンタ残なし)ならAX=0FFFFHにして復帰。
B000:00D9 EB02 JMP 00DDH ;--------------------------------------------------------------------
B000:00DB 2BC0 SUB AX,AX ;AXを0000Hにして復帰(ZF=1)。
B000:00DD C3 RET ;====================================================================

B000:0166 7305 JNB 016DH ;正常に読み出して帰れば(CF=0)016DHへ。AX=0000Hで復帰。-------
B000:0168 BA3802 MOV DX,0238H ;94 07 'データを読み込むことができません。'00 FF FF 00
B000:016B EB37 JMP 01A4H ;01A4H(POP ESしてRET)。0055Hへ。-----------------------------
B000:016D 268A4600 MOV AL,ES:[BP+00H] ;FAT先頭データ(0FFH)をALに代入。
B000:0171 FEC0 INC AL ;0FFH+1=00H
B000:0173 7405 JE 017AH ;ZF=1なので017AHへ。-----------------------------------------
B000:0175 BABC02 MOV DX,02BCH ;94 07 'ディスクの形式が違います。'00 FF FF
B000:0178 EB2A JMP 01A4H ;01A4Hに飛んでPOP ESしてRET。--------------------------------

;ディレクトリエントリ(ルートディレクトリ)セクタ読み出し
B000:017A B204 MOV DL,04H ;DL=04H。C=0,H=0,R=04,N=03
;トラック0,ヘッド0,第4セクタ(ディレクトリエントリ),レングス3を読む。
;AX=0000H
B000:017C E845FF CALL 00C4H ;ディスク読み出しサブルーチン2呼出し ~00DDH ++++++++++++++++
;CALL後省略

B000:017F 72E7 JB 0168H ;CF=1(正常に読めなかったとき)なら,0168Hへ。AX=0FFFFH -------
B000:0181 8BDD MOV BX,BP ;BX=0000H(BP=0000H,0158H以降変動なし)
B000:0183 B92000 MOV CX,0020H ;カウンタに0020Hをセット。
B000:0186 268A07 MOV AL,ES:[BX] ;第4セクタ先頭データ(0CAH)をALに代入。
B000:0189 3CE5 CMP AL,0E5H ;0CAHと0E5Hを比較。ZF=0
B000:018B 740D JE 019AH ;ZF=1なら019AHへジャンプ。(無限ループ)-----------------------
B000:018D 0AC0 OR AL,AL ;AL=0CAH
B000:018F 74E4 JE 0175H ;ZF=1なら0175Hへ。-------------------------------------------
B000:0191 268B470A MOV AX,ES:[BX+0AH] ;第4セクタ先頭から000AHの中身2バイトを2941HをAXに代入。
;Bディスクなら2942H
B000:0195 80FC29 CMP AH,29H ;AH=29Hと29Hを比較。
B000:0198 7404 JE 019EH ;ZF=1なので019EHへ。 ----------------------------------------
B000:019A E2EA LOOP 0186H ;0186Hへのループを32回。
B000:019C EBD7 JMP 0175H ;0175Hへ。---------------------------------------------------
B000:019E 2C41 SUB AL,41H ;AL=41Hから41Hを減ずる。AL=00H
;Bディスクならディスク違い。AL=01H
B000:01A0 98 CBW ;バイト(AL)からワード(AX)への変換。
;ビット7をAHの全てのビットにコピーする。AX=0000H
;BディスクならAX=0001H
B000:01A1 BE3802 MOV SI,0238H ;94 07 'データを読み込むことができません。'00 FF FF 00
B000:01A4 07 POP ES
B000:01A5 C3 RET ;0055Hへ。 ==================================================

;ディスク読み出し結果分岐ルーチン
B000:0055 85C0 TEST AX,AX ;ZF=1(AX=0000Hのとき)
B000:0057 7513 JNE 006CH ;ZF=0(AX=FFFFH,正常に読めなかった)なら,006CHへ。--------

;############################################################################################
(ここからエラー表示)
0168Hから来た(第2または第4セクタを読み出せなかった)とき ;94 07 'データを読み込むことができません。'00 FF FF 00
0175Hから来た(FATデータ不一致)とき ;94 07 'ディスクの形式が違います。'00 FF FF
01A5Hから来たが,ディスク違いの場合
B000:006C 2E00067A02 ADD CS:[027AH],AL ;半角Aと半角Bの文字コード差分を「A」の文字コードに加算する。
B000:0071 BE6002 MOV SI,0260H ;'このディスクは 「No.A(+文字コード差分)」 です。'
B000:0074 EB06 JMP 007CH ;007CHへ。-----------------------------------------------------------
B000:007C E89400 CALL 0113H ;文字列表示サブルーチン呼出し~0119h +++++++++++++++++++++++++++++++++
(以下省略,ハイレゾモードエラー表示部分参照)
(エラー表示終了)
;#############################################################################################

B000:0059 E83600 CALL 0092H ;第5セクタ以下読み出しルーチンへ~00C3H +++++++++++++++++++

;第5セクタ以降が正常に読み出せるか(58セクタ分)?
B000:0092 06 PUSH ES ;ES退避。
B000:0093 B86000 MOV AX,0060H
B000:0096 8EC0 MOV ES,AX ;ES=0060H 読み出すセグメント
B000:0098 BB0004 MOV BX,0400H ;BX=0400H 読み出すバイト数,データ長(DTL)
B000:009B B90003 MOV CX,0300H ;CX=0300H CH(N)=03H,CL(C)=00H
B000:009E BA0500 MOV DX,0005H ;DX=0005H DH(H)=00H,DL(R)=05H セクタ5読み出し
B000:00A1 E82000 CALL 00C4H ;ディスク読み出しサブルーチン2呼出し ~00DDH ++++++++++++++++
;CALL後省略

B000:00A4 85C0 TEST AX,AX ;ZF=1(正常に読み出されたとき)
B000:00A6 751A JNE 00C2H ;ZF=0(正常に読み出せなかったとき)なら00C2Hへ。POP ESしてRET。------
B000:00A8 03EB ADD BP,BX ;BP+0400H
B000:00AA 81FD00E8 CMP BP,0E800H ;BPと0E800Hを比較(E800H/0400H=3Aなので58セクタ分読む意味か。)。
B000:00AE 7312 JNB 00C2H ;CF=0(BP>0E800H)なら,00C2Hへ。POP ESしてRET。-----------------------
B000:00B0 FEC2 INC DL ;読み出しセクタ番号を1増やす。
B000:00B2 80FA08 CMP DL,08H ;セクタ番号8か?
B000:00B5 76EA JBE 00A1H ;CF=1またはZF=1のとき(DL<=8),00A1Hにジャンプ。----------------------
B000:00B7 B201 MOV DL,01H ;セクタ番号8まで来たので読み取りセクタを1に。
B000:00B9 80F601 XOR DH,01H ;ヘッド番号を1に。
B000:00BC 75E3 JNE 00A1H ;ZF=0(既にヘッド番号が1)のとき,00A1Hへジャンプ。------------------
B000:00BE FEC1 INC CL ;シリンダ番号を増やす。
B000:00C0 EBDF JMP 00A1H ;--------------------------------------------------------------------
B000:00C2 07 POP ES ;ES復帰。
B000:00C3 C3 RET ;====================================================================

B000:005C 85C0 TEST AX,AX ;ZF=1
B000:005E 7516 JNE 0076H ;ZF=0(正常に読み出せなかった)のとき,0076Hへ。-----------------------------------------------

;##############################################################################################
(ここからエラー表示)
B000:0076 EB04 JMPS 007CH ;007CHへ。「データを読み込むことができません。」を表示して異常終了。
;SIは01A1Hで積んできた
B000:007C E89400 CALL 0113H ;文字列表示サブルーチン呼出し~0119h +++++++++++++++++++++++++++++++++
(以下省略,エラー表示終了)
;##############################################################################################

B000:0060 B00E MOV AL,0EH ;DISP ENABLE 画面表示OFF テキスト・グラフィックとも
B000:0062 E668 OUT 68H,AL ;http://www.webtech.co.jp/company/doc/undocumented_mem/io_disp.txt

;GOAL
B000:0064 EA00006000 JMP 0060H, 0000H ;データバッファ先頭領域(第5セクタ以下格納)へ。----------------------------------
B000:0069 90 NOP

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

「晴れのちおおさわぎ」IPL分析(前半)

2010-11-11 16:52:13 | レトロパソコンのお作法
文字容量の関係で2回に分けてアップします。
後半はこちら。

初稿では,清十郎さんの作成されたDISKに関する資料 第2稿の様式に則って,データの記録順にベタ書きしてましたが,構造を把握しにくかったので,改訂稿では,フローチャートと,プログラムの実行順にデータを記載します。



こうしてまとめてしまうと,ほとんど中身がありませんな。これを理解するのに日数を費やした私って一体・・・。

ま,いいか。

B000:0000 EB1C JMP 001EH
B000:0002 90 NOP

;BPB
B000:0003 49504C20302E3230 'IPL 0.20'
B000:000B 0004 0400h ;1セクタあたりバイト数(1024)
B000:000D 01 01h ;1クラスタあたりセクタ数(1)
B000:000E 0100 0001h ;IPL(1)
B000:0010 01 01h ;FATの数(1)
B000:0011 2000 0002h ;ルートディレクトリの総エントリ数(32)
B000:0013 D004 04D0h ;ディスクのセクタ総数(1232)
B000:0015 FF 0FFh ;メディア・ディスクリプタ
B000:0016 0200 0002h ;1FATあたりセクタ数(2)
B000:0018 0800 0008h ;1トラックの物理セクタ数(8)
B000:001A 0200 0002h ;ヘッド数(2)
B000:001C 0000 0000h ;不可視セクタの数(0)
;まとめ ブートセクタ1つ1セクタ,FAT1つ2セクタ,ディレクトリエントリ1つ1セクタ,
; データ領域は第5セクタ(論理セクタ番号4)から。

;レジスタ初期化,SS=ES=0000h
B000:001E FA CLI ;割り込みフラグクリア。外部割り込みを禁止。
B000:001F 2BC0 SUB AX,AX ;ワーク・セグメント=0000H
B000:0021 8ED0 MOV SS,AX ;SS=0000H
B000:0023 BC8A02 MOV SP,028AH ;スタックの設定(0000:0028AH)
B000:0026 FB STI ;割り込みフラグセット。次の命令の最後で、外部割り込みを可能に。
B000:0027 8EC0 MOV ES,AX ;ES=0000h(=SS)

;キーバッファ設定
B000:0029 26800E000520 OR BYTE ES:[0500H],20H
;KEYBOARD BIOS
;98のワークエリア0000H:0500Hの第5ビットを1にする。
;キーバッファオーバーフロー時にビープを鳴らさない設定。
;http://www.webtech.co.jp/company/doc/undocumented_mem/memsys.txt
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.23)

;CSとDSを同一セグメントに設定
B000:002F 0E PUSH CS ;
B000:0030 1F POP DS ;CS=DS

;テキストVRAM設定(ハイレゾ,非ハイレゾ)
B000:0031 B800A0 MOV AX,0A000H ;AX=0A000H テキストVRAMセグメント
B000:0034 26F606010508 TEST BYTE ES:[0501H],08H ;BIOS_flg 98
;http://www.webtech.co.jp/company/doc/undocumented_mem/memsys.txt
;ワークエリア0000:0501Hの第3ビット確認。1ハイレゾ0ノーマル
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.23)
B000:003A 7403 JE 003FH ;ZF=1(bit3=0)のとき(ノーマル),003FHへ。---------------
B000:003C B800E0 MOV AX,0E000H ;ハイレゾのとき,ハイレゾテキストVRAMセグメント。AX=0E000H
B000:003F 8EC0 MOV ES,AX ;ハイレゾの場合,ES=0E000H
;ノーマルの場合,ES=0A000H

;画面表示初期化
B000:0041 E89A00 CALL 00DEH ;画面表示初期化サブルーチン呼出し~00F6h +++++++++++++++++++

;0041Hから来た
;画面表示初期化サブルーチン
;(MS-DOS基本プログラミング第2集 PC9801の割り込みとBIOS活用法,トラ技コンピュータ編集部 編 '92/12/20)
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.23)

B000:00DE B8000A MOV AX,0A00H ;画面あたり行数25行,行あたり桁数80字,バーチカル・ライン有効,コードアクセス有効
B000:00E1 CD18 INT 18H ;CRT BIOS テキスト画面モードの設定
B000:00E3 B40D MOV AH,0DH
B000:00E5 CD18 INT 18H ;CRT BIOS テキスト画面表示停止
B000:00E7 B412 MOV AH,12H
B000:00E9 CD18 INT 18H ;CRT BIOS カーソル表示停止
B000:00EB B416 MOV AH,16H ;テキストVRAMの初期化。AH=16H
B000:00ED BA20E1 MOV DX,0E120H ;DX=0E120H,テキスト全領域をクリア
;DH=0E1h,標準アトリビュート,DL=020h,スペースで埋める
B000:00F0 CD18 INT 18H
B000:00F2 B40C MOV AH,0CH
B000:00F4 CD18 INT 18H ;CRT BIOS テキスト画面表示開始
B000:00F6 C3 RET ;0044Hへ復帰。=======================================================

;IPL読み込み中メッセージ
B000:0044 BEB001 MOV SI,01B0H ;00 00 'IPL: 読み込み中です。しばらくお待ちください。',00,FF,FF
B000:0047 FC CLD ;ディレクションフラグを0(増加)にリセットした。
B000:0048 E8C800 CALL 0113H ;文字列表示サブルーチン呼出し~0119h +++++++++++++++++++++++

;0048Hまたは007CHから来た
;文字列ロードルーチン
B000:0113 AD LODSW ;DS:[SI]のメモリのワード値をAXに転送し,SIの値を2増加させる。
B000:0114 8BF8 MOV DI,AX ;AX退避。
B000:0116 40 INC AX ;AXの値を1増やす。
B000:0117 75F7 JNE 0110H ;ZF=0(INC前のAXがFFFFHでないとき)なら,0110Hへ。---
;*******************************************************************************************
B000:0110 E82D00 CALL 0140H ;バイトデータロードサブルーチンへ。~0145H +++++++++

;0110Hから来た
;バイト文字列終了確認ルーチン このために文字列には終了判別用に後に0FFHを2つ配置している。
;0113Hではワード値として文字列0FFFFHかどうかを調べているがここではバイト値で調べている。
B000:0140 AC LODSB ;DS:[SI]で示されるメモリのバイト値をALに転送し,
;SIの値を1増加させる。バイトデータロード。
B000:0141 84C0 TEST AL,AL ;ALを比較。AL=00HならZF=1
B000:0143 75D5 JNE 011AH ;ZF=0ならば011AHにジャンプ。---------------
;*******************************************************************************************
;0143Hから来た
;ANK文字判別ルーチン
;(PC-9801スーパーテクニック 小高輝真,清水和文,速水祐著 株式会社アスキー発行 '92/04/01・P66~)
B000:011A 2AE4 SUB AH,AH ;AH=00H
B000:011C 3C80 CMP AL,80H ;ANK文字(半角英数)か?ALと80H(全角文字は80H以降)を比較。
B000:011E 721F JB 013FH ;CF=1のとき(AL<80H,半角英数なら),013FHへ。----------------------- B000:0122 7608 JBE 012CH ;CF=1またはZF=1のとき(80H<=AL<=9EH),012CHへ。-----------------------
B000:0124 3CE0 CMP AL,0E0H ;ANK文字(半角カナ)か?ALと0E0H(全角文字は0E0H以降)を比較。
B000:0126 7217 JB 013FH ;CF=1のとき(9EH<AL<0E0H,半角カナなら),013FHへ。------------------ B000:012A 7713 JNBE 013FH ;CF=0,かつZF=0のとき(0FCH<AL),013FHへ。----------------------------- ;0122Hから来た
;全角文字コードテキストVRAMロードルーチン
B000:012C 8AE0 MOV AH,AL ;全角文字の1バイト目をAHに。012EHと併せてAXにS-JIS文字コードをロード。
B000:012E AC LODSB ;DS:[SI]で示されるメモリのバイト値をALに転送し,SIの値を1増加させる。
B000:012F E8C6FF CALL 00F8H ;シフトJIS→TVRAM書き込みデータ変換ルーチン~010EH +++++++++++++++++++

;012FHから来た
;シフトJIS文字コード→テキストVRAM書き込み変換ルーチン。シフトJISコードからJISコードへの準変換含む。
;(98ハードに強くなる本,東京工業大学・電算機愛好会 著 技術評論社刊 '76/11/10 P.120~)
;(98ハードに強くなる本II,東工大電算機愛好会著&小高輝真 著 技術評論社刊 '88/02/25 P.120~)
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.61~)
;(PC-9801プログラマーズBible第2版,東京理科大学EIC編,技術評論社刊 '96/08/05 P.79~)
;http://www.eonet.ne.jp/~ookumaneko98/kanji.htm
;http://www.infonet.co.jp/ueyama/ip/binary/shiftjis.html
B000:00F8 D0E4 SHL AH,01 ;左シフト,文字コード第1バイト×2。bit7-0→bit6-0,0,CF=1。
B000:00FA FECC DEC AH ;AH-1
B000:00FC 3C9E CMP AL,9EH ;ALと09EHを比較。
B000:00FE 7606 JBE 0106H ;CF=1またはZF=1のとき(AL<=09EH),0106Hへ。---------------------------
B000:0100 2C7E SUB AL,7EH ;09EH<ALのとき,ALから7E減ずる。 B000:0104 EB08 JMP 010EH ;CALL元に復帰。------------------------------------------------------
B000:0106 3C7E CMP AL,7EH ;ALと7EHを比較。
B000:0108 7602 JBE 010CH ;CF=1またはZF=1のとき(AL<=07EH),010CHへ。ALから1FH減じて復帰--------
B000:010A FEC8 DEC AL ;07EH<AL<=09EHのとき,ALから20H減じて復帰 B000:010E C3 RET ;0132Hに復帰。=======================================================
;まとめ AL<=07EH AHを2倍して1減ずる。ALから1FH減ずる。 ex.。 シフトJIS 8142→TVRAM 0223 cf.JIS 2123
; 07EH<AL<=09EH AHを2倍して1減ずる。ALから20H減ずる。 ex.込 シフトJIS 8D9E→TVRAM 197E cf.JIS 397E
; 09EH<AL AHを2倍する。    ALから7EH減ずる。 ex.読 シフトJIS 93C7→TVRAM 2649 cf.JIS 4649

;テキストVRAM書き込みルーチン
;(PC-9801スーパーテクニック 小高輝真,清水和文,速水祐著,株式会社アスキー発行 '92/04/01・P66~)
B000:0132 86E0 XCHG AH,AL ;AHとAL入れ替え
B000:0134 3C09 CMP AL,09H ;ALと09Hを比較。2バイト半角文字か?ALを20H減じてから来たことに注意
B000:0136 7204 JB 013CH ;CF=1(全角文字ならAL<09H,JIS漢字コードは3021H~)のとき,013CHへ。-- B000:013A 7603 JBE 013FH ;CF=1またはZF=1のとき(09H<=AL<=0BHなら2バイト半角文字),013FHへ。---

;全角文字データテキストVRAM書き込み
B000:013C AB STOSW ;テキストVRAMへワードデータ書き込み。全角文字の左側を書く。
;ES:[DI]で示されるメモリに,AXのワード値を格納し,
;DIの値を2増加させる。データのストア。
;DIで指定するブロックへALの内容を次々とストアする。
B000:013D 0C80 OR AL,80H ;ALのbit7を1にする。全角右側のフラグを立てる。次の013FHで書き込み。

;011EH,0126H,012AHから来た場合あり
;半角文字データテキストVRAM書き込み
B000:013F AB STOSW ;013CHと同じ。013DH経由で来たときは全角文字の右側を書く。
;ここへジャンプしてきた場合(ANK文字),AH=00H,ALに文字コードをストア。

;バイト文字列終了確認ルーチン このために文字列には終了判別用に後に0FFHを2つ配置している。
;0113Hではワード値として文字列0FFFFHかどうかを調べているがここではバイト値で調べている。
B000:0140 AC LODSB ;DS:[SI]で示されるメモリのバイト値をALに転送し,
;SIの値を1増加させる。バイトデータロード。
B000:0141 84C0 TEST AL,AL ;ALを比較。AL=00HならZF=1
B000:0143 75D5 JNE 011AH ;ZF=0ならば011AHにジャンプ。---------------

B000:0145 C3 RET ;0113Hへ復帰。 ============================

B000:0119 C3 RET ;004BHへ。====================================

;ハイレゾ分岐
B000:004B 8CC0 MOV AX,ES ;テキストVRAMセグメントをAXに代入。
B000:004D 3D00A0 CMP AX,0A000H ;テキストVRAMセグメントアドレスを確認。
B000:0050 7526 JNE 0078H ;ZF=0のとき(ハイレゾ),0078Hへ。---------------------------

;########################################################################################
(ここからエラー表示)
;ハイレゾモードエラー
B000:0078 BEE201 MOV SI,01E2H ;02h,07h,'ハイレゾモードでは動作しません。',00h,D4h,08h,
;'ノーマルモードに設定し、リセットしてください。',00h,FFh,FFh,1Eh,2Hh
B000:007B 90 NOP
B000:007C E89400 CALL 0113H ;文字列表示サブルーチン呼出し~0119h +++++++++++++++++++++++++++++++++

;0048Hまたは007CHから来た
;文字列ロードルーチン
B000:0110 E82D00 CALL 0140H ;バイトデータロードサブルーチンへ。~0145H +++++++++++++++++++++++++++

;ワード文字列終了確認ルーチン
B000:0113 AD LODSW ;DS:[SI]のメモリのワード値をAXに転送し,SIの値を2増加させる。
B000:0114 8BF8 MOV DI,AX ;AX退避。
B000:0116 40 INC AX ;AXの値を1増やす。
B000:0117 75F7 JNE 0110H ;ZF=0(INC前のAXがFFFFHでないとき)なら,0110Hへ。---------------------
B000:0119 C3 RET ;====================================================================

;異常終了処理
;(トランジスタ技術SPECIAL No.45 CQ出版社 '94/05/01 P.122)
B000:007F B417 MOV AH,17H ;ブザーの起呼。AH=17H
B000:0081 CD18 INT 18H ;
B000:0083 2BC9 SUB CX,CX ;CX=0000H
B000:0085 E2FE LOOP 0085H ;CXの値を1減じて,0でなければ0085Hへ。
B000:0087 E2FE LOOP 0087H ;CXの値を1減じて,0でなければ0087Hへ。
B000:0089 6418 MOV AH,18H ;ブザーの停止。AH=18H
B000:008B CD18 INT 18H ;
B000:008D 90 NOP ;
B000:008E FA CLI ;外部割り込み禁止。
B000:008F F4 HLT ;割り込みがかかるまでCPUを停止させる。
B000:0090 EBFC JMPS 008EH ;無限ループ-----------

(エラー表示終了)
;##########################################################################################

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

FATの読み方

2010-08-01 22:34:49 | レトロパソコンのお作法
FATの読み方は難しい。
人間の生理を離れた作業が必要となるので,忘れたが最後,もう思い出せません。
そんなわけで,FATの読み方を整理しておきます。

FATってのは,ディスク内のファイルデータの配置を記録したデータですので,まずターゲットとなるファイルを設定しないことには具体的な話ができません。
今回は,自然数である0から638までを改行だけして並べたTESTファイルを作成して,これをDOS6.2のシステムだけ転送したフロッピーイメージに保存しました。

早速,ディレクトリ領域をSYMDEB.EXEで覗いてみます。


この機会に読み方も覚えておきましょう。





ファイル名は読んで字の如し。ファイル名が8文字に達しない場合は,20h(スペースの文字コード)で空白を埋められます。
ファイル名欄が00hから始まる行はその後方に有効なファイル情報が存在しないことを示します。
後述しますが,ファイル名欄が05Ehから始まるディレクトリエントリは削除されたファイルの痕跡です。



属性は,10の位と1の位を分けて考えます。
まず,10の位が2の場合,未バックアップファイル(アーカイブファイル)であることを意味します。これはBACKUPコマンドによってアーカイブされたことがあるかどうかを示すもので,大抵のファイルの10の位は2です。
また,10の位が1の場合,ファイルではなくサブディレクトリであることを示します。
次に,1の位は1,2,4,8の合計値に分解します。
例えば,上の画面中のIO.SYSやMSDOS.SYSの属性値の1の位は7ですから,
7=1+2+4
です。
このうち,1は,リードオンリーファイル属性,消去や変更の不可能な書き込み禁止ファイルというやつです。
2は,隠しファイル属性,DIRコマンドで表示されず,DELコマンドも及びません。
4は,システムファイル属性,リードオンリーかつ隠しファイルです。
このディスクにはボリュームラベルを付けませんでしたが,もしボリュームラベルを付けていれば,1の位には属性値8が表示されることになっていました。
コンピュータは,この部分に書き込まれた数値を見て,各ファイルの属性を判断するので,このIO.SYSやMSDOS.SYSの属性値を例えば20などに書き替えてしまえば,通常のファイル同様,DIRコマンドで表示させることができますし,変更も消去も自由にできるわけです。



次は更新日時です。データの並びからは更新時刻が先に来ていますので,まずこちらを説明します。
更新時刻は「D6 61」と並んでいますから,リトルエンディアン形式の表記に即して,「61 D6」と読み替えます。
この61D6hは2進数で,
0110000111010110
となります。電卓で2進数化すると上位の0が省略されて16桁にならない場合があるので,その場合は16桁になるよう頭に0を追加してください。

ちなみに,16進数を2進数化するのは簡単でして,「6」,「1」,「D」,「6」を順番に2進数にして並べればいいのです。
すなわち,各数値を8,4,2,1の和に分解して,あれば1,なければ0を順番に並べた数列を,さらに順番に並べればいいのです。
06hは,4+2ですから,0110,
01hは,1ですから,0001,
0Dhは,10進数で13,8+4+1ですから,1101。

そうすると,
06h,01h,0dh,06hは,0110,0001,1101,0110の並びになりますから,上述の数字になるわけです。
この数字を,5桁,6桁,5桁と切り分けます。
そうすると,
01100  001110   10110
(時)   (分)   (秒)
となります。
2進数の 01100は,10進数の,8+4で,12です。
2進数の001110は,10進数の,8+4+2で,14です。
2進数の 10110は,10進数の,16+4+2で,22です。
これは,このファイルが,12時14分22秒に更新されたことを示しています。

というのは少し誤り。
秒の欄を示す5桁の2進数は11111,10進数で16+8+4+2+1=31が上限の数字ですから,1秒ごとに数値をあてはめると32秒から59秒を表現できません。
そこで,秒については,半分の数値で記録しています。
つまり,記録された数値は22ですが,読み出す段階で2倍して44秒と読みます。
かくして,正解は,12時14分44秒となります。(秒部分訂正追記・10/10/27)

更新年月日についても同様に,「01 3D」→「3D 01」を2進数化したうえで,7桁,4桁,5桁に切り分けます。
そうすると,
03h,0Dh,00h,01hをそれぞれ2進数化すると,0011,1101,0000,0001となりますから,3D01hは0011110100000001です。これを7桁,4桁,5桁に切り分けると,

0011110  1000  00001
(年+1980) (月) (日)
となります。
2進数の0011110は,10進数の16+8+4+2で,30です。
2進数の   1000は,10進数の 8です。
2進数の  00001は,10進数の 1です。
これは,このファイルが,1980+30=2010年8月1日に更新されたことを示しています。



ファイルサイズは,DWord(Double Word)形式で記述されています。
「0D 0C 00 00」はリトルエンディアン形式で表記されていますから,まず,下位2バイトと上位2バイトを入れ替え,「00 00」「0D 0C」の並びにしてから,さらにいつもどおりこれら2バイト内の上下を入れ替えます。すると,
00 00 0C 0D
となります。
0C0Dhは,10進数で3085ですから,このファイルサイズは3085byteということが分かります。
ファイル属性がサブディレクトリの場合,このサイズは0となります。



さて,残るは「先頭クラスタ番号」です。
先ほどのTESTファイルの先頭クラスタ番号を見てみましょう。
「009Fh」ですね(リトルエンディアン形式参照)。

フロッピーディスクのブートセクタ解析の説明の中でも書きましたが,FAT領域は,先頭にFAT-ID,次にFFが2つ続いて記録されています。
後述するFAT指定の様式に従うと,これら3バイト分のデータは,本来,クラスタ0とクラスタ1を指定すべきものですが,このとおり冒頭の2クラスタ分が使えない仕様となっています。
そのため,囲んではいませんが,ディレクトリ領域の最初のファイルであるIO.SYSのFATの先頭クラスタ番号は0002hとなっていますね。
そんなわけで,FATの示す先頭クラスタ番号から論理セクタ番号を計算するにあたってはこの2クラスタ分を減ずる必要があります。

また,フロッピーディスクのブートセクタ解析で説明したとおり,このディスクのデータ領域の先頭セクタは,論理セクタ番号で0Bhです。

したがって,TESTファイルの格納された論理セクタ番号は,
0Bh+(09Fh-2)=09Fh+9=0A8h
ということになります。
(実は,ここはセクタとクラスタのサイズ比が影響する場合があるのですが,今回のディスクは1クラスタあたり1セクタなので,あえて無視して記述を進めていますのでご注意ください。)

TESTファイルの先頭部分の格納された論理セクタ番号0A8hのセクタのデータをロードしてみます。


見事読み出せました,パチパチパチ。
って,FATは続けて読んでなんぼですから,ここで喜んでるようじゃ話になりません(喜んでたじゃないか)。

先のLコマンドの後,
-D 0 3FF
とやると,09Fhの指示するセクタに格納されたデータの末尾が見られます。



226までは,最初のクラスタに収まったようです。

では,「009Fh」のファイルの続きはFATのどこを見れば分かるのでしょうか。
今度は単なる足し算ではすみません。

09Fhを2で除して,小数点以下を切り捨て(整数部のみ残す),3を乗じます。
計算式で言えば,INT(09Fh/2)*3ということです。答は0EDhです。
Excelは16進数の計算をするのにいちいち10進数化しないといけないことが分かりました。イライラ。関数電卓のほうが優秀ってどういうことよ。



0EDh部分は,こちら。


そして,FATエントリの読み方のややこしさはリトルエンディアンの比じゃない。
まず,まず,左右の各1バイトをそれぞれ反対に付け替える。


真ん中で切り分ける。


さらに左右逆転。


クラスタ番号の偶数が前の分,クラスタ番号の奇数が後ろの分を取る。
クラスタ番号が2から始まることを覚えておけば偶数が先だと思い出せるはずです。
今回は,クラスタ番号が09Fhで,奇数なので,後ろの分である「0A0h」が次のFATエントリと判明しました。

「009Fh」の次が「0A0h」って,単なる続きやん!というツッコミが入りそうですが,いつもいつもこうとは限らないので基本の確認は大事なんです!

まあ一応続きも。
INT(0A0h/2)*3=0F0h

A1 20 0A を 0A 20 A1 と並べ替えて,0A2 と 0A1 に分けて,再び左右並べ替えると,0A1h 0A2h。
0A0hは偶数なので,前を取って,次のFATエントリは0A1h。
(哲哉様のコメントで誤りをご指摘いただいたので、修正しました。2022/11/22 14:21)

続いて,
INT(0A1h/2)*3=0F0h
0A1hは奇数なので,後ろを取って,次のFATエントリは0A2h。

そろそろ飽きてきましたが,
INT(0A2h/2)*3=0F3h

FF 0F 00 を 00 0F FF と並べ替えて,000 と FFF とに分けて,再び左右並べ替えると,FFF 000。
0A2hは偶数なので,前を取って,次のFATエントリはFFF。
というわけではなく,ファイルの最後のクラスタに対応するFATには,0FFFhが書き込まれています。

ちなみに,FATエントリの000hは未使用クラスタ,0FF7hは不良クラスタでスキップセクタがあるため使用しません,また001hの値は使われません。

結局,09Fh→0A0h→0A1h→0A2hというクラスタチェーンを経て,TESTファイルがすべて格納されました。
念のため,0A2hのクラスタ内のデータを確認しておきます。

論理セクタ番号は,
0Bh+(0A2h-2)=0A2h+9=0ABh
ですから,
論理セクタ番号0ABhのセクタのデータをロードしてみます。



はい。638までなんて中途半端なTESTファイルにしてしまったためにオチの画面が締まりませんが,ちゃんと最終セクタのデータまで辿り着くことができました。
ちなみに,1セクタあたり1024byteですから,3セクタ分3072byteに「36 0D 0A 36 33 37 0D 0A 36 33 38 0D 0A」の13byteが加わって,ファイルサイズは3085byteとなり,ディレクトリ領域に書かれていたファイルサイズとも一致するわけです。

さて,ここまで読み進めてしまえば,最初のディレクトリ領域のダンプ画面から,IO.SYSやMSDOS.SYS,COMMAND.COMの各ファイルの各先頭クラスタを読み取って,FATエントリを目で追えるようになったのではないでしょうか。



とまあ,健全なFATだけ見てもつまらないので,消してしまったファイルの復活方法でも勉強しますか。

では,早速,フロッピードライブであるBドライブから,TESTファイルを削除してしまいましょう。



TESTファイルが削除されたことで,ディレクトリエントリやFATにはどのような変更が加わったでしょうか。

まず,ディレクトリエントリを見てみます。


0060 54 45 53 54 20 20 20 20 ・・・ TEST
となっていたディレクトリエントリが,
0060 E5 45 53 54 20 20 20 20 ・・・ eEST
となってしまいました。
ファイルを削除するとディレクトリエントリのファイル名の1文字目の1バイトがE5で上書きされることが分かります。

次に,FATを見てみます。


INT(09Fh/2)*3=0EDh
ですから,0EDhに注目です。


削除前の同一箇所はこうでした。


09Fh→0A0h→0A1h→0A2h(FFFh)と続いていたクラスタチェーンがすべて 00 で上書きされていることがお分かりかと思います。
前述したとおり,FATエントリの000hは未使用クラスタを意味します。
TESTファイルが削除されたことで,FAT上はTESTファイルの使用されていた領域が未使用クラスタとして登録されてしまったわけです。

ついでですから,TESTファイルの格納されていた論理セクタ番号である
0Bh+(09Fh-2)=09Fh+9=0A8h
を読み出してみましょう。


ご覧のとおり,元のデータ領域には何の手も加えられていなかったというわけです。

結局,うっかり削除してしまったファイルを復元するためには,
1 ディレクトリエントリのファイル名を元に戻す
2 FATのクラスタチェーンを復元する
という2工程が必要となります。

今回の場合,FATのクラスタチェーンの元の状態を分かっていますから,FATを読み出した上で,
メモリの内容を変更するE(Enter)コマンドでアドレス「EDh」からのメモリを「FF 0F 0A A1 20 0A FF 0F 00」と編集して,

-E ED FF 0F 0A A1 20 0A FF 0F 00
メモリをロードして,中身を確認します。
-D 0 FF


予定どおりのメモリ内容に変更されていますので,
メモリ内容をディスクに書き込むW(Write)コマンドで変更したメモリ内容をディスク内データに反映させます。コマンドは,ドライブ1の論理セクタ1に1セクタ分書き込むわけですから,
-W 0 1 1 1
と入力します。終わればQ(Quit)コマンドでデバッグ画面から抜けます。


早速成果を確認したいところですが,まだ1工程残っていました。
ディレクトリエントリのファイル名の修正です。
ディレクトリエントリを読み出した上で,60hのメモリをTの文字コードである54に書き替えます。
-E 60 54
-D 0 FF


メモリを編集しただけで満足せず,ちゃんとディスクに書き込みましょう。
-W 0 1 5 1


Qコマンドでデバッグ画面を抜けたら,DIRコマンドで,TESTファイルの復活を確認します。


ついでにSEDIT.EXEで中身を確認しておきます。
冒頭から,


最後まで無事に復元できました。



無事,復活できたようです。
しかし,FATデータがいったん消されてしまうと,ファイルの復活は容易ではないですね。
今回は,元のFATデータを把握していたので,000で上書きされた箇所に埋める数値が分かっていましたが,実際には,ディレクトリエントリから読み取ったファイルサイズに基づいて,先頭クラスタ番号から隣接するFATエントリにクラスタチェーンを作成していく(ラストは0FFFhとなることに注意)ことになるでしょうか。
ディスクに保存されたファイルが少なく,削除や更新を重ねていないファイルばかりなら楽でしょうが,そうでもなければあまり現実的な復元方法とは言えません。

参考文献
「応用MS-DOS 改訂新版 アスキーラーニングシステム③応用コース」(村瀬康治著・89/12/31・株式会社アスキー発行)
「MS-DOS6.2 プログラム開発ツールマニュアル」(NEC)拡張機能セットに付いてきた冊子。というか,あの構成要素はほとんど冊子だ。
「PC-9801/E/F/M ディスクシステム 解析マニュアル[第4巻]」(山内 直著・'85/01/15・秀和システムトレーディング発行)
「はじめて読む8086」(蒲池輝尚著・村瀬康治監修・'87/04/01・株式会社アスキー発行)

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

フロッピーディスクのブートセクタ分析

2010-07-28 15:08:53 | レトロパソコンのお作法
さて,「晴れのちおおさわぎ」クリア前の寄り道2です。

実は,このゲームの中盤で,主人公がテニスをやってみるシーンがあるんですが,タイミングよく打ち返すと,HCGが見られます。
確認できたCGは4枚なんですが,このどれが見られるかはどうもランダムくさい。
ランダムなのは構わないんだけど,何せ中盤なので,見逃しがあるとここまで戻ってリプレイってのが面倒でならない。

そこで,DiskExplorerで中身を見ようと思ってイメージファイルを開こうとしても,下のようにエラーが出る始末。



とりあえず,Manual FDモードで,


手動設定ディスクに入れるべき数値を入力して,中身が閲覧できるように,フロッピーディスクの記録方式を研究するのが今回の記事の目的です。




フロッピーディスクの記録方式を勉強しようとすると,必ず解説されるのが,C,H,R,N。

C Cylinder Address シリンダ番号(0-xx),最外周(シリンダ0)から最内周(シリンダxx)までの同心円状の記録帯を指します。文献によってはトラック番号とも表記されます。


H Head Address ヘッド番号(0,1),サーフェス番号とも呼ばれる。ラベルを貼る面の裏側が0,ラベルを貼る面が1。


R Record Address セクタ番号(1-xx),トラックをピザ状に切り分けた各セクタに付される番号。下の図では8分割にしてますが,9分割や18分割の場合もあります。ここは,ピザをどのサイズで切るかの話なので,ある程度融通が利きます。コンピュータの世界にしては珍しく,開始番号が0でないことに注意。



N Record Length 1セクタあたりのバイト数 2の(N+7)乗によって求められます。

これらC,H,R,NはPC-88時代においては,コピープロテクトとしてそれなりに意味を持っていたようですが(HSDL:PC88フロッピーディスクのプロテクトを参照しました),PC-98時代ではCD,1Bサーチによるプロテクトチェック回避の手法が主流となったため,あんまりこだわって覚える必要はないかもしれません。



本稿では,ヘッド表裏+シリンダ番号で特定される片面の円状記録帯を,以下のようにトラック番号を付けて特定します。
ヘッド番号 シリンダ番号 トラック番号セクタ番号論理セクタ番号
0 0(最外周) 0 1-x0-(x-1)
1 0(最外周) 1 ・・・・・・
0 1(最外周から1本中心寄り) 2 ・・・・・・
1 1(最外周から1本中心寄り) 3 ・・・・・・
0 2(最外周から2本中心寄り) 4 ・・・・・・
・・・・・・・・・・・・・・・


この裏面の最外周シリンダであるトラック0には,システムを起動するためのブートプログラムが書き込まれており,システム予約領域,またはブートセクタと呼ばれます。

早速,トラック0の実物を見ましょう。
MS-DOS6.2のシステムを転送した空きフロッピーディスクのトラック0をデバッガで読み出します。
MS-DOS3.x以降では拡張機能セットにのみ含まれているSYMDEB.EXEを用いました。
LコマンドはLoad,DコマンドはDumpです。





では,トラック0のブートセクタはどのようになっているでしょうか。
ダンプ画面の主要部分の下に,ブートセクタの構造解説図を付けました。





ブートセクタのうち,0Bh~17hを構成するBPB(Bios Parameter Block)には,デバイスの物理的なパラメータとデバイスの他の領域の位置と大きさが記録されています。
図中に黄色で着色しました。


DOS6.2のシステムを含む空きディスクのBPBからは,次のことが分かります(トラックあたりセクタ数はBPB外ですが)。
4桁の数字表記がダンプ画面と違うことに気付いた方はちょっとえらい。
興味があれば「リトルエンディアン」で検索。

セクタあたりのバイト数 (セクタ長)0400h=4*256=1024byte
クラスタあたりのセクタ数01h=1
予約セクタ(ブートセクタ)数0001h=1
FATの数02h=2
ルートディレクトリエントリの最大エントリ数00C0h=16*12=192
ディスクのセクタ総数04D0h=4*256+16*13=1232
メディア記述子(メディアディスクリプタバイト)=FAT ID0FEh=3.5/5"2HD,8"2D
FATあたりのセクタ数0002h=2
トラックあたりのセクタ数0008h=8


これで,FAT領域の先頭の論理セクタ番号が分かりました。
システムの予約セクタが1でしたから,トラック0のセクタ1(論理セクタ番号0)から1領域ずれて,トラック0のセクタ2(論理セクタ番号1)です。

また,ディレクトリ領域(ルートディレクトリを格納する領域)の先頭の論理セクタ番号は,FAT1つで2セクタを使用し,FATが2つありますから,FAT領域は合計4セクタを使用することになります。
FATが論理セクタ番号1からと,論理セクタ番号3からそれぞれ2セクタが使用されましたから,ディレクトリ領域の先頭の論理セクタ番号は5です。

さらに,ディレクトリ領域は,ディレクトリ数*32/セクタサイズですから,
192*32/1024=6セクタを使用し,トラック0の6,7,8セクタ(論理セクタ番号5,6,7)と,トラック1の1,2,3セクタ(論理セクタ番号8,9,0Ah)を使用しますから,データ領域の先頭の論理セクタ番号は0Bhとなります。

デバッガで,各領域の開始位置である論理セクタ番号のデータをロードして,論理セクタ番号を正確に算出できているかを確認します。

FAT(1) FAT領域は,FAT IDに続けて,FFが2つ続く決まりなので,間違いなさそうです。


FAT(2) FAT(1)と同じ内容です。


ディレクトリ領域


データ領域


どの領域もそれっぽい内容となっており,論理セクタ番号の算出には間違いがなさそうです。

ディスクの実物上の位置関係に割り付けると,下図のようになります。
 



では,これらディスク情報に基づいて,MS-DOS6.2のシステムを転送した空きフロッピーディスクをDiskExplorerで開いてみましょう。



「FATの位置」は,「予約セクタ(ブートセクタ)数」(ウ)である1を,「セクタあたりのバイト数 (セクタ長)」(ア)である1024byteに乗じて算出しました。
「FATの数」(エ)は,2です。
「FATサイズ」は,FATあたりのセクタ数(ク)である2を,「セクタあたりのバイト数 (セクタ長)」(ア)である1024byteに乗じて算出しました。
「ルートの位置」は,予約セクタ1024byte+FAT(2048byte)*2=5120byteとなります。
「データ領域の位置」は,予約セクタ(1セクタ)+FAT領域(4セクタ」+ディレクトリ領域(6セクタ)の計11セクタ,11*1024byteの位置にありますから,11264byteとなります。
「クラスタサイズ」は,1クラスタあたり1セクタで(イ),1セクタあたり1024byteですから,1024byteとなります。
「総クラスタ数」には,「ディスクのセクタ総数」(カ)から,予約セクタ(1セクタ)+FAT領域(4セクタ」+ディレクトリ領域(6セクタ)の計11セクタデータを減じたクラスタ数である,1232-11=1221を入力しました。



空き領域が641,024byteって・・・。こりゃ作戦失敗です。
その後,ここには書かない長い苦闘を経て,思い出しました。
イメージファイルを作成したツールであるMAKE_HD.EXEを含むP88SRを作成されたぶるー牧場さんのホームページには,MAKE_HD.EXEで作成したディスクイメージのファイル構成が技術情報として公開されていたのです。
そして,分かりました。このイメージにはヘッダーが付いているので,トラック0のダンプ画面と見比べてもらえば分かるとおり,ディスクイメージの本体は,2C0hから始まっているわけです。



そこで,DiskExplorerの開始位置として,2C0h=704を指定してみます。


せっかくなので,自動読み込みをクリックしてみます。


ちぇっ,何だよ。フロッピーディスクのブートセクタなんて勉強しなくても数値が埋まってるよ(>_<)



空き容量からいってどうやら無事に開けたようです。

ちなみに,目的であった「晴れのちおおさわぎ」のディスクですが,開始位置704を設定して,自動読み込みをして開いてみましたが,何のファイルも表示されませんでした。空ディスクよりははるかに空き容量は少なくなってましたが。
ファイル上の属性変更もしてみましたが,変わらず。

ま,ユーザースキルレベルの今よりはるかに高かった時代のソフトが,そう簡単に中身を見せてくれるわけもないか。

参考文献
「応用MS-DOS 改訂新版 アスキーラーニングシステム③応用コース」(村瀬康治著・89/12/31・株式会社アスキー発行),
「MS‐DOSエンサイクロペディア Volume1 システム解説編」(マイクロソフトプレス編・翻訳/監修エー・ピー・ラボ・89/03/11・株式会社アスキー発行)

ほんとはこの機会にFATの読み方とかも勉強すべきなんだろうけど,とりあえずは必要ないから,またの機会に。

追記・FAT領域にも,データ領域にも欠落のないイメージデータがあるということは,FATに書かれたファイルの切り出しはできるわけで,DiskExplorerを用いたデータ閲覧に限らなければ,意外と簡単にディスク内データが閲覧できそう・・・。

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

ちょっとはCONFIG.SYSにもこだわってみよう

2010-07-20 19:32:30 | レトロパソコンのお作法
えーと,プレイを予告した「晴れのちおおさわぎ」は半分やりました。
で,ちょっとしたことから,プレイを中断して,フロッピーディスクのブートセクタを大研究中。
そっちは別稿に回すとして,今回は寄り道その1,CONFIG.SYSの内容による空きメモリの分析。

「とことんこだわるCONFIG.SYS NEC MS-DOS6.2対応」(寺口俊伸著・エーアイ出版'95/08/14)で紹介されていた,兵藤嘉彦さんの開発された VMAPを使って,空きメモリをたくさん確保できる効率的な内容のCONFIG.SYSを作りたいと思います。

FILES=30
BUFFERS=10
SHELL=¥COMMAND.COM /P
LASTDRIVE=Q
DEVICE=A:¥DOS¥HIMEM.SYS
DEVICE=A:¥DOS¥EMM386.EXE /P=45 /UMB /T=A:¥DOS¥EXTDSWAP.SYS
DEVICE=A:¥dos¥MOUSE.SYS
DOS=HIGH,UMB

上が従来使っていたCONFIG.SYSの内容。¥マークは本来は半角です。

ツァイ メタ女ハードディスクイメージ起動プロセス検証-fdnp21改の下の方で紹介した要領で,オプションnを付けてVMAPを実行します。
なお,AUTOEXEC.BATにおいてDOSSHELLを起動し,マウスドライバも常駐している状態です。

「とことんこだわるCONFIG.SYS NEC MS-DOS6.2対応」によると,BUFFERSを小さくすると,DOSの起動するまでの時間が遅くなるとのことですが,エミュレータ上では誤差の範囲内でしょうから,気にせずガンガン削ってみましょう。

そんなわけで,私の初期設定,BUFFERS=10から1まで削ったCONFIG.SYSで起動したMS-DOS6.2の空きメモリの検証結果です。単位はいずれもbyte。

BUFFERS 最大実行可能プログラムサイズ config占有メモリbuffers占有メモリ
10 573,664 13,696 10,448
9 574,704 12,656 9,408
8 575,760 11,600 8,352
7 576,800 10,560 7,312
6 580,960 4,272 1,024
5 580,960 4,272 1,024
4 583,088 4,272 1,024
3 583,088 4,272 1,024
2 583,088 4,272 1,024
1 583,088 4,272 1,024


BUFFERSの値が5また6では最大実行可能プログラムサイズが少し小さくなり,BUFFERSの値が7以上では最大実行可能プログラムサイズがさらに小さくなり,その後は,BUFFERSの値が大きくなるに連れてさらに最大実行可能プログラムサイズが小さくなっていることが分かります。
下のグラフは,BUFFERSの値と最大実行可能プログラムサイズとを対比したものです。Y軸の基準は560KBで,1目盛り1KBです。


下のグラフは,CONGIG.SYSの記述内容がコンベンショナル・メモリ中に占めるbyte数と,その中でBUFFERSの占めるbyte数を対比したもの。
BUFFERSの値が7以上になると消費メモリが激増するのは,CONGIG.SYSの内容がHMAメモリに収まらず,コンベンショナル・メモリを食い潰し始めるからだそうです。


どうやら,私のシステムでは,BUFFERS=4と記述するのが正解のようです。

さらに,「とことんこだわるCONFIG.SYS NEC MS-DOS6.2対応」によると,特に記述しないと値が4に設定されるFCBSも1で足りるとのこと。
そこで,FCBS=1にすると,

FCBS 最大実行可能プログラムサイズ config占有メモリfcbs占有メモリ
1 583,264 4,096 80

となります。

さらにDOSSHELLを終了してマウスのメモリも解放すると,最大実行可能プログラムサイズは,605,120byteまで増加します。

以上,おさらいすると
BUFFERS=10 573,664
BUFFERS=4583,088
FCBS=1 583,264
DOSSHELL終了605,120
こんな感じ。

上げ底グラフではこんな感じ。


結論として,自分のシステムでは,CONFIG.SYSを

FILES=30
FCBS=1
BUFFERS=4
SHELL=¥COMMAND.COM /P
LASTDRIVE=Q
DEVICE=A:¥DOS¥HIMEM.SYS
DEVICE=A:¥DOS¥EMM386.EXE /P=45 /UMB /T=A:¥DOS¥EXTDSWAP.SYS
DEVICE=A:¥dos¥MOUSE.SYS
DOS=HIGH,UMB

として,AUTOEXEC.BATではDOSSHELLを使わない設定にするのがよさそうです。

なお,ツァイ メタ女ハードディスクイメージ起動プロセス検証-fdnp21改内で検討したCONFIG.SYSにおいては,BUFFERSの値を小さくしても空きメモリの増大は認められませんでした。

<<著作権に関して>>
本記事に引用している全てのソフトの名称・画像の著作権・その他権利は、制作、販売されたソフトハウス、メーカー、または作者様に帰属します。本サイトでの上記著作権物扱いは、著作権など各権利関係を侵害することが目的ではありません。問題などある場合は、メール(gekigangarあっとmail.goo.ne.jp)にてその旨お知らせください。

BATファイルを1行ずつ実行するコマンド

2009-09-06 16:21:42 | レトロパソコンのお作法
COMMAND 某.bat(ただし,ドライブ名からディレクトリ名まで完全に指定すること) /C /Y

または,

COMMAND 某.bat(同上) /K /Y

/Cの場合,終了後にコマンドプロンプトに戻るが,/Kの場合,コマンドプロンプトに戻らない。
1行ずつ確認するスイッチは /Y だが,/C または /K との併用を要する。

BATファイルのプロセス確認に用いる場合があるので,備忘メモ。

参考文献 PC-98版 MS-DOS6.2活用ハンドブック(1995/06/25)
フリーディア著・翔泳社刊

自分用メモ

2009-09-06 15:33:54 | レトロパソコンのお作法
自分用メモ
¥は半角で置換する必要あり。

Autoexec.batの内容

@ECHO OFF
PATH A:¥DOS;A:¥;a:¥mld219
mscdex.exe /d:cd_101 /l:q
SET TEMP=A:¥DOS
SET DOSDIR=A:¥DOS
MOUSE
DOSSHELL
MOUSE /R

CONFIG.SYSの内容

FILES=30
BUFFERS=4
SHELL=¥COMMAND.COM /P
LASTDRIVE=Q
DEVICE=A:¥DOS¥HIMEM.SYS
DEVICE=A:¥DOS¥EMM386.EXE /P=45 /UMB /T=A:¥DOS¥EXTDSWAP.SYS
DEVICE=a:¥dos¥MOUSE.SYS
rem DEVICE=A:¥DOS¥SETVER.EXE
DEVICE?=a:¥cddrv.sys /d:cd_101 /i0
rem device?=a:¥cdsdmini.sys /d:cd_101 /i0 /u
rem DEVICE?=a:¥cdx.sys /d:cd_101
DOS=HIGH,UMB