DisAssembler FX
2009年3月17日
はじめに
アセンブラのニーモニックはやっと覚えたんだけど、命令の組み合わせ方が分からないのでプログラムが組めないよう、という方や、パソコンを持ってなくて(あるいはマックのファンで)パソコンのディスアセンブラが使えないよう、という方に最適です。また、最近のPJにソースリストが掲載されないので、困っているという方などです。16進数の羅列を見ても、何も分かりませんからね。例外もいますが。他人のプログラムから、マシン語プログラムの作り方や、プログラムのテクニックを盗みましょう。
特徴
以下、[MENU]→[5]で呼び出されるアセンブラを「内蔵アセンブラ」と呼びます。内蔵アセンブラではアセンブルできない命令を含め、(私の知る範囲内での)全80186命令に対応しています。例えば、
- SHL AX,3
- MOV [BX+1234H],CX
- CMP [DI-01H],0DH
などがあります。実際、上に挙げた命令はよく使うんですが、なぜか内蔵アセンブラでは対応されていないんですね。
下準備
このプログラム単体では、ROMを解析するくらいしか使いみちがありません。それも十分便利ですが、やはり一番良いのは、PJ読者の皆さんが作ったプログラムを解析することでしょう。
このプログラムは、プログラムがメモリ上のどこかに存在すれば(FD上は不可)、どこの番地に対しても、ディスアセンブルができます。また、ディスアセンブルの結果は、ファイルエリア上、またはFD上に記録することになります。それは、リスト中の140行、変数Kの値によって変わります。
ファイルエリアに記録するときは、F9をNEWしておいてください。これは、180行の"F9"を任意の値にすることにより変更できます。
FDに記録するときは、FDDにアクセスできる状態にしておいてください。ファイル名は「$DISASM.LST」となります。180行にファイル名が指定されていますので、変更したい方はここを書き換えてください。
使ってみましょう
それでは、実際に練習してみましょう。これからやることは、練習ですので、やり方を覚えたらそれで結構です。まず、
CLEAR 4096,5,6144
MON
E2000
B410CD41CF
Q
と入力してください。今、メモリの2000H~2004Hに、あるプログラムがかかれました。早速これをディスアセンブルしてみましょう。
プログラムを実行すると、タイトルが表示されます。最初に、開始アドレスを聞いてきます。デフォルト(=02000H)のままでいいので、そのまま[RET]を押してください。次に終了アドレスを聞いてきます。デフォルトはマシン語エリア終了アドレス(=02004H)です。そのままでいいので、[RET]を押してください。すると、ディスアセンブルを開始します。画面上にはリアルタイムで、現在処理中のアドレスと、ディスアセンブルした結果が表示されていきます。プログラムが終了したら、[MENU]→[1]として、F9を覗いてみてください。次のような結果が得られたでしょうか(ヘッダーとアドレスは省略します)。
MOV AH,10H
INT 41H
IRET
確かに、正しくディスアセンブルされていますね。ちなみに今、
DEFSEG=0
CALL &H2000
とすると、画面が消えたとおもいます。これは画面消去のBIOSを呼び出しています。
注意
バックスクロールさせながらリアルタイムにディスアセンブルして、解析したりすることはできません。パソコン通信で言うlogをとって、それを参照するようなかたちになっています。更にいうならば、ちょっとディスアセンブル速度が遅いですが、それは仕様です。
技術ネタ
番地は、絶対番地形式に直します。条件ジャンプ命令などでは、相対距離の情報が格納されているわけですが(一部命令を除く)、絶対番地形式に計算しなおします。これは「仕様」です。なぜそんなことをするのかといえば、検索機能で簡単にジャンプ先を探せるようにしたかったからです。
また、いわゆる「自動ラベル付加機能」はありませんので、全くソースリストと同じものができるわけではありません。さらに、前後関係から、文字列を探すといったことはできません。つまり、ディスアセンブルリストをもう一回アセンブルすることはできません。
さらに、どうしてもディスアセンブルができないデータは、DB擬似命令を使って処理します。これには、0FH(この位置は、オペコード表ではPOP CSにあたるが実際にはない)、64H(386以上のCPUでは、FS:にあたる)などがあります。
また、どんなデータでもディスアセンブルします。ソースリスト上では、DB擬似命令を使用して文字列のアスキーコードを書き込んだとします。しかし、そのアスキーコード群の最後が、2バイト以上続く命令にディスアセンブルされてしまったらどうすればよいでしょうか。オペコードとオペランドの関係が狂ってしまうので、続く数バイトが変にディスアセンブルされる可能性があります。
例をあげましょう。
90 NOP
41 A: DB 'A'
B8 34 12 B: MOV AX,1234H
このようなソースリストをアセンブルしてディスアセンブルしたとします。ディスアセンブルすると次のようになるはずです。
NOP
ADC AL,0B8H
XOR AL,012H
ディスアセンブル前とディスアセンブル後で、結果が異なりましたね。このように、DB擬似命令を使う場合は注意してください。この問題を回避するための方法は幾つか考えられますが、部分部分に分けてディスアセンブルするか、または、おかしいと思う部分を自分でディスアセンブルするのがいいと思います。
プログラムリスト
100 '**************************
110 'Dis-Assembler FX ver0.91
120 ' By ABCP software
130 '**************************
140 CLS:CLEAR:DIM J$(1),P(5):K=0:T=65536
150 R$="Dis-Assembler FX ver0.9 By ABCP":PRINT R$
160 LOCATE 4,1:PRINT "Address="
165 X=12:Y=1:D$="02000":GOSUB *SUJI:S$=D$
167 LOCATE 19,1:PRINT "to"
170 X=22:Y=1:B=&H2000+FRE(6):GOSUB *ADR:D$=A$:GOSUB *SUJI:E$=D$
175 IF S$>E$ THEN 170
180 IF K THEN OPEN "0:$DISASM.LST" FOR OUTPUT AS #1 ELSE RESTORE#("F9")
200 FOR I=1 TO 31:N$=N$+"-":NEXT:W$=N$:GOSUB *DISK
210 W$=R$:GOSUB *DISK
220 W$="Address="+S$+"H to "+E$+"H":GOSUB *DISK
230 W$=N$:GOSUB *DISK
240 J$(0)="BBBBBBFFBBBBBBFABBBBBBFFBBBBBBFFBBBBBBDDBBBBBBDDBBBBBBDDBBBBBBDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCJJKAAAAAJXJXHHHHNNNNNNNNNNNNNNNN"
250 J$(1)="BBBBIIIIMMMMMKMJUIIIIIIIOONOOOOOSSSSHHHHTTHHHHHHEEEEEEEEEEEEEEEEQQUUKKQQUUUUUUUUQQQQYYAUVVVVVVVVNNNNRRRRNNNNRRRRPAPPPPLLGGGGGGWW"
260 *MAIN
270 S=VAL("&H"+RIGHT$(S$,4)):IF S<0 THEN S=S+T
280 FOR I=0 TO 5:B=S+I:J=VAL("&H"+LEFT$(S$,1))
285 IF B>=T THEN J=(J+1) AND 15:B=B-T
290 DEFSEG=J*4096:P(I)=PEEK(B):NEXT
300 N$="":P$="":W=0:F=0:M=0:L=1:I=0:P=P(0)
310 ON ASC(MID$(J$(P\128),(P MOD 128)+1,1))-64 GOSUB *DB,*CALC,*INCDEC,*PREFIX,*MOVE1,*PUSHS,*WARIFRAG,*AGAIN,*XCHG,*PUSHA,*BOUND,*F6F7,*MOVE2,*JMP,*FRAG,*REP,*SHIFT,*PORT,*MOVE3,*TEST,*RET,*ESC,*FEFF,*IMUL,*AAM
320 IF RIGHT$(N$,1)=" " THEN N$=LEFT$(N$,LEN(N$)-1):GOTO 320
330 W$=S$+":"+N$:IF P$<>"" THEN W$=W$+" "+P$
340 GOSUB *DISK:CLS:PRINT W$
360 S=S+L+VAL("&H"+LEFT$(S$,1))*T:B=S:GOSUB *ADR:S$=A$
365 IF S$<=E$ AND SEG<>16 GOTO *MAIN
370 DEFSEG=0:END
380 *DB
390 L=1:N$="DB":W=0:N=0:GOSUB *GETS2:P$=D$
395 RETURN
400 *CALC
410 IF P>=&H80 THEN I=(P(1) AND &H38)/8 ELSE I=P\8
420 N$=MID$("ADDOR ADCSBBANDSUBXORCMP",I*3+1,3)
430 W=P AND 1:F=(P AND 2)/2:IF W=0 THEN F=0
440 IF (P AND 4) THEN N=1:GOSUB *GETS2:M$=D$:G=0:GOSUB *REGS:R$=W$:L=W+2 ELSE IF P<&H80 THEN GOSUB *OP:L=M+2:IF F=0 THEN GOSUB *CHANGE
450 IF P>=&H80 THEN GOSUB *OP:R$=M$:N=M+2:GOSUB *GETS2:M$=D$:L=M+W-F+3
460 P$=R$+","+M$
465 RETURN
470 *INCDEC
480 N$=MID$("INC DEC PUSHPOP",(P AND &H38)/2+1,4)
490 W=1:G=P AND 7:GOSUB *REGS:P$=W$
495 RETURN
500 *PREFIX
510 N$=MID$("ES:DAACS:DASSS:AAADS:AAS",((P AND &H18)/4+(P AND 1))*3+1,3)
520 RETURN
530 *MOVE1
540 N$="MOV":W=(P AND 8)/8
550 G=P AND 7:GOSUB *REGS:P$=W$:L=W+2:N=1:GOSUB *GETS2:P$=P$+","+D$
560 RETURN
570 *PUSHS
580 L=1:N$=MID$("PUSHPOP",(P AND 1)*4+1,4)
590 P$=MID$("ESCSSSDS",(P AND &H18)/4+1,2)
600 RETURN
610 *WARIFRAG
620 L=1:N$=MID$("CLCSTCCLISTICLDSTD",(P-&HF8)*3+1,3)
630 RETURN
640 *AGAIN
650 L=1:IF P<=&H6F THEN N$=MID$("OUTSINS",(1-(P AND 2)/2)*4+1,4) ELSE N$=MID$("MOVSCMPS STOSLODSSCAN",((P-&HA4)\2)*4+1,4)
660 IF (P AND 1) THEN N$=N$+"W" ELSE N$=N$+"B"
670 RETURN
680 *XCHG
690 N$="XCHG":IF P<=&H85 THEN N$="TEST"
700 IF P>=&H91 THEN G=0:W=1:GOSUB *REGS:R$=W$:G=P AND 7:GOSUB *REGS:M$=W$:L=1 ELSE W=P AND 1:GOSUB *OP:L=M+2
710 P$=R$+","+M$
720 RETURN
730 *PUSHA
740 IF P<=&H61 THEN L=1:N$=MID$("PUSHAPOPA",(P-&H60)*5+1,5) ELSE IF P<=&H6A THEN N$="PUSH":W=1-(P AND 2)/2:N=1:GOSUB *GETS2:P$=D$:L=W+2 ELSE N$="POP":W=1:GOSUB *OP:P$=M$:L=2+M
750 RETURN
760 *BOUND
770 I=0:N$="BOUND":IF P>=&HC4 THEN N$=MID$("LESLDS",(P-&HC4)*3+1,3):I=1 ELSE IF P=&H8D THEN N$="LEA"
780 W=1:GOSUB *OP:L=M+2
790 IF I=1 THEN M$="D"+M$:IF D=3 GOTO *DB
800 P$=R$+","+M$
805 RETURN
810 *F6F7
820 W=P AND 1:GOSUB *OP:I=(P(1) AND &H38)/8:N$=MID$("TEST NOT NEG MUL IMULDIV IDIV",I*4+1,4)
830 IF I=0 THEN N=M+2:GOSUB *GETS2:P$=M$+","+D$:L=M+W+3 ELSE P$=M$:L=M+2:IF I=1 GOTO *DB
840 RETURN
850 *MOVE2
860 W=P AND 1:IF P=&H8C OR P=&H8E THEN W=1:I=1
870 N$="MOV":GOSUB *OP:L=M+2:IF I=1 THEN R$=MID$("ESCSSSDS",(P(1) AND &H18)/4+1,2):IF (P AND &H20) GOTO *DB
880 IF (P AND 2)=0 THEN GOSUB *CHANGE
890 P$=R$+","+M$
900 RETURN
910 *JMP
920 W=0:IF P<=&H7F THEN N$=MID$("JO JNOJC JNCJZ JNZJNAJA JS JNSJP JNPJL JNLJNGJG",(P-&H70)*3+1,3) ELSE IF P=&H9A OR P=&HE8 THEN N$="CALL":W=1 ELSE IF P<=&HE3 THEN N$=MID$("LOOPNZLOOPZ LOOP JCXZ",(P-&HE0)*6+1,6) ELSE N$="JMP":W=-(P<>&HEB)
930 IF W=1 THEN Z=P(1)+P(2)*256:IF Z>=T/2 THEN Z=Z-T
940 IF W=0 THEN Z=P(1):IF Z>=128 THEN Z=Z-256
950 B=Z+S+W+2+VAL("&H"+LEFT$(S$,1))*T:GOSUB *ADR:P$=A$+"H":L=W+2
960 IF P=&HEA OR P=&H9A THEN N=1:D$=HEX$(P(N)+P(N+1)*256):GOSUB *PLUS0:C$=D$+"H":D$=HEX$(P(N+2)+P(N+3)*256):GOSUB *PLUS0:D$=D$+"H:"+C$:P$=D$:L=5
970 RETURN
980 *FRAG
990 L=1:N$=MID$("CBW CWD WAIT PUSHFPOPF SAHF LAHF",(P-&H98)*5+1,5)
1000 RETURN
1010 *REP
1020 L=1:N$=MID$("LOCK REPNZREP HLT CMC",(P-&HF0)*5+1,5)
1030 RETURN
1040 *SHIFT
1050 I=0:W=P AND 1:GOSUB *OP:N$=MID$("ROLRORRCLRCRSHLSHR SAR",(P(1) AND &H38)/8*3+1,3):IF P=&HC6 OR P=&HC7 THEN N$="MOV":I=1 ELSE IF (P(1) AND &H38)=&H30 GOTO *DB
1060 IF I=1 AND (P(1) AND &H38) GOTO *DB ELSE IF I=0 THEN W=0
1070 IF P<=&HC7 THEN N=M+2:GOSUB *GETS2:R$=D$:L=M+W+3 ELSE L=M+2:IF P<=&HD1 THEN R$="1" ELSE R$="CL"
1080 P$=M$+","+R$
1090 RETURN
1100 *PORT
1110 N$=MID$("IN OUT",(P AND 2)/2*3+1,3):W=P AND 1:G=0:GOSUB *REGS:R$=W$
1120 IF P<=&HE7 THEN N=1:W=0:GOSUB *GETS2:M$=D$:L=2 ELSE W=1:L=1:G=2:GOSUB *REGS:M$=W$
1130 IF (P AND 7)>=6 THEN GOSUB *CHANGE
1140 P$=R$+","+M$
1145 RETURN
1150 *MOVE3
1160 W=P AND 1:N$="MOV":B=P(3):P(3)=P(2):P(2)=P(1):P(1)=6:GOSUB *OP:L=M+1:P(1)=B:P(1)=P(2):P(2)=P(3):P(3)=B
1170 IF (P AND 2) THEN GOSUB *CHANGE
1180 P$=R$+","+M$
1185 RETURN
1190 *TEST
1200 W=P AND 1:N$="TEST":N=1:GOSUB *GETS2:L=M+1:G=0:GOSUB *REGS
1210 P$=W$+","+D$
1215 RETURN
1220 *RET
1230 L=1:IF P>=&HC8 THEN N$=MID$("ENTERLEAVERETF RETF INT INT INTO IRET",(P-&HC8)*5+1,5) ELSE IF P=&H90 THEN N$="NOP" ELSE N$="RET"
1240 IF P=&HD7 THEN N$="XLAT"
1250 IF (P AND 7)=2 THEN N=1:W=1:GOSUB *GETS2:P$=D$:L=3
1260 IF P=&HCC THEN P$="03H" ELSE IF P=&HC8 THEN N=1:W=1:GOSUB *GETS2:P$=D$:N=3:W=0:GOSUB *GETS2:P$=P$+","+D$:L=4
1270 IF P=&HCD THEN N=1:W=0:GOSUB *GETS2:P$=D$:L=2
1280 RETURN
1290 *ESC
1300 N$="ESC":W=0:GOSUB *OP:I=(P AND 7)*8+(P(1) AND &H38)/8:P$=RIGHT$(HEX$(I),2)+"H,"+M$
1310 RETURN
1320 *FEFF
1330 I=(P(1) AND &H38)/8:W=P AND 1:IF (W=0 AND I>=2)+(W=1 AND I=7) GOTO *DB
1340 GOSUB *OP:L=M+2:N$=MID$("INC DEC CALLCALLJMP JMP PUSH",I*4+1,4):GOSUB *OP:IF D=3 AND (I=3 OR I=5) GOTO *DB
1350 IF W=1 AND (I=3 OR I=5) THEN M$="D"+M$
1360 P$=M$
1365 RETURN
1370 *IMUL
1380 N$="IMUL":W=1:GOSUB *OP:IF R$<>M$ THEN P$=R$+","+M$ ELSE P$=R$
1390 W=1-((P AND 2)/2):N=M+2:GOSUB *GETS2:P$=P$+","+D$:L=M+W+3
1395 RETURN
1400 *AAM
1410 IF P(1)-&H0A GOTO *DB
1420 N$=MID$("AAMAAD",(P-&HD4)*3+1,3):L=2
1425 RETURN
1430 *ADR
1440 A=B:IF A<0 THEN A=A+1048576
1460 A$=RIGHT$(HEX$(A\T),1)+HEX$(A MOD T)
1465 RETURN
1470 *OP
1480 R=P(1) AND 7:G=(P(1) AND &H38)/8:D=(P(1) AND &HC0)/64
1490 GOSUB *REGS:R$=W$
1500 M$=MID$("BXBXBPBPSIDIBPBX",R*2+1,2):M=D
1510 IF R<=3 THEN M$=M$+"+"+MID$("SD",(R MOD 2)+1,1)+"I"
1520 IF D=1 OR D=2 THEN GOSUB *GETS:M$=M$+D$
1530 IF D=0 AND R=6 THEN D$=HEX$(P(2)+P(3)*256)+"H":M=2:GOSUB *PLUS0:M$=D$
1540 M$=MID$("BYTEWORD",W*4+1,4)+" PTR ["+M$+"]"
1550 IF D=3 THEN G=R:GOSUB *REGS:M$=W$:M=0
1560 RETURN
1570 *REGS:W$=MID$("ALCLDLBLAHCHDHBHAXCXDXBXSPBPSIDI",W*16+G*2+1,2)
1575 RETURN
1580 *GETS:I$="+":Z=P(2):IF D=1 THEN M=1:IF Z>=128 THEN D$=RIGHT$(HEX$(ABS(256-Z)),2):I$="-" ELSE D$=RIGHT$(HEX$(Z),2)
1590 Z=Z+P(3)*256:IF D=2 THEN M=2:IF Z>=T/2 THEN D$=HEX$(ABS(T-Z)):I$="-" ELSE D$=HEX$(Z)
1600 GOSUB *PLUS0:D$=I$+D$+"H"
1610 RETURN
1620 *GETS2:IF W=1 AND F=0 THEN D$=HEX$(P(N)+P(N+1)*256) ELSE D$=RIGHT$(HEX$(P(N)),2)
1630 GOSUB *PLUS0
1640 IF F=1 THEN IF P(N)>=128 THEN D$="-"+RIGHT$(HEX$(ABS(256-P(N))),2) ELSE D$="+"+D$
1650 D$=D$+"H"
1655 RETURN
1660 *CHANGE:W$=M$:M$=R$:R$=W$
1665 RETURN
1670 *PLUS0
1680 IF ASC(D$)>=65 THEN D$="0"+D$
1690 RETURN
1700 *DISK
1710 IF K THEN PRINT #1,W$ ELSE WRITE# W$
1720 RETURN
1730 *SUJI
1740 I=0
1750 LOCATE X,Y:PRINT D$;"H"
1760 LOCATE X+I,Y:I$=INPUT$(1):IF I<5 AND (I$>="0")*(I$<="9")+(I$=>"A")*(I$=<"F") THEN D$=LEFT$(D$,I)+I$+RIGHT$(D$,4-I):I=I-(I<4)
1770 IF I$=CHR$(29) AND I>0 THEN I=I-1 ELSE IF I$=CHR$(28) AND I<4 THEN I=I+1
1780 IF I$<>CHR$(13) GOTO 1750
1790 RETURN
























コメント
コメント(0件)
コメントする
トラックバック
トラックバック(0件)
トラックバック先