16bitのx86コードに触れたくなりました。そこでMINIX 2に目を付けました。
MINIX 2は16bitと32bitの両方に対応しています。16bitの方は80286のプロテクトモードを使用しているためリアルモードではありません。カーネルではなくユーザープログラムの動きを追いたいので、ユーザーだけを見ている限りはリアルモードとの違いは少ないのではないかと予想しています。詳しいことは触りながら調べてみる予定です。
入手
ダウンロードからリンクされているPrevious Versionsから入手できます。
展開すると、中には更にアーカイブが入っています。そこからバイナリやソースが入手できます。16bitに関連するファイルを挙げます。
i86/USR.TAZ | /usr以下に展開されるバイナリ |
src/SYS.TAZ | カーネルやlibcなどのソース |
src/CMD.TAZ | コマンドのソース |
src/FIX.TAZ | カーネルのNICに関する差し替え(→パッチ化したもの) |
今回はOSのインストールではなくバイナリ調査が目的ですが、USR.TAZを展開するだけで簡単に入手できました。
MINIX 1
もしかするとMINIX 1の方が単純で調べやすいのかもしれません。
1.7.5と2.0.4のファイルサイズを比較すると、バイナリとソースのファイルサイズは大差ありません。配布物のサイズが倍近く違うのはドキュメント量の差のようです。
ファイル | 1.7.5 | 2.0.4 |
---|---|---|
Intel-*.tar.bz2 | 14,677,079 | 29,407,996 |
USR.TAZ | 3,691,424 | 4,041,076 |
SYS.TAZ | 2,191,217 | 2,397,026 |
CMD.TAZ | 3,287,049 | 3,414,449 |
とりあえず2で始めて、複雑過ぎるようであれば1を検討しようかと思います。
シェルスクリプト
usr/binにはシェルスクリプトが混ざっています。
$ file * | grep script DESCRIBE: POSIX shell script text executable M: POSIX shell script text executable MAKEDEV: POSIX shell script text executable (略) srccrc: POSIX shell script text executable svclog: POSIX shell script text executable whatis: POSIX shell script text executable
これらを除外して小さい順に並べます。
$ ls -lrS | cut -d ' ' -f 5- 332 Aug 24 2003 sync 462 Aug 24 2003 yes 1472 Aug 24 2003 sleep 1518 Aug 24 2003 update 1926 Aug 24 2003 tr 1982 Aug 24 2003 rmdir 2318 Aug 24 2003 tee 2538 Nov 10 2003 uname 2538 Nov 10 2003 arch 2546 Aug 24 2003 loadkeys (略)
yesが取っ付きやすそうです。
fileコマンドでは以下のように識別されます。ヘッダにOSを識別する情報が入っていないようです。
$ file yes yes: Linux-8086 executable
逆アセンブラ
コマンドを眺めると、dis88という逆アセンブラを見付けました。ソースから再コンパイルすれば手元の環境(MSYS)でも動きました。
Makefileを修正します。
--- Makefile.orig +++ Makefile @@ -24,14 +24,14 @@ # the initialization data in the lookup tables. It should not # be necessary to alter the formats of the tables. -CFLAGS =-O -wo +CFLAGS =-O -I. #-wo OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o all: dis88 dis88: $(OBJ) - cc -i -o dis88 $(OBJ) - install -S 5kw dis88 + cc -o dis88 $(OBJ) + #install -S 5kw dis88 install: /usr/bin/dis88
usr/includeからa.out.hとansi.hをコピーします。
POSIXに準拠したソースらしく、修正なしですんなりmakeが通りました。
.textの抽出
先ほどコピーしたa.out.hを見ると、ヘッダ情報が分かります。
struct exec { /* a.out header */ unsigned char a_magic[2]; /* magic number */ unsigned char a_flags; /* flags, see below */ unsigned char a_cpu; /* cpu id */ unsigned char a_hdrlen; /* length of header */ unsigned char a_unused; /* reserved for future use */ unsigned short a_version; /* version stamp (not used at present) */ long a_text; /* size of text segement in bytes */ long a_data; /* size of data segment in bytes */ long a_bss; /* size of bss segment in bytes */ long a_entry; /* entry point */ long a_total; /* total memory allocated */ long a_syms; /* size of symbol table */ /* SHORT FORM ENDS HERE */ long a_trsize; /* text relocation size */ long a_drsize; /* data relocation size */ long a_tbase; /* text relocation base */ long a_dbase; /* data relocation base */ };
a_hdrlenとa_textを見れば.textだけを抽出できそうです。Pythonで抽出スクリプトを書きました。
extract-text.py
import sys, struct if len(sys.argv) != 3: print "usage: %s input output" % sys.argv[0] sys.exit(1) with open(sys.argv[1], "rb") as f: assert f.read(2) == "\x01\x03", "not a.out" f.seek(4) a_hdrlen = ord(f.read(1)) f.seek(8) a_text = struct.unpack("<L", f.read(4))[0] f.seek(a_hdrlen) text = f.read(a_text) with open(sys.argv[2], "wb") as f: f.write(text)
yesから.textを抽出して、objdumpで逆アセンブルします。-bで生バイナリ、-mで16bit、-MでIntel形式、-Dでファイル全体の逆アセンブルを指定します。
$ python extract-text.py yes yes-text $ objdump -b binary -m i8086 -M intel -D yes-text (略) 0: 31 ed xor bp,bp 2: 89 e3 mov bx,sp 4: 8b 07 mov ax,WORD PTR [bx] 6: 8d 57 02 lea dx,[bx+0x2] 9: 8d 4f 04 lea cx,[bx+0x4] c: 01 c1 add cx,ax e: 01 c1 add cx,ax 10: bb 0a 00 mov bx,0xa 13: 81 fb 0e 00 cmp bx,0xe (略)
NASMに含まれるndisasmでも逆アセンブルしてみます。オプションが必要ないため簡単です。
$ ndisasm yes-text 00000000 31ED xor bp,bp 00000002 89E3 mov bx,sp 00000004 8B07 mov ax,[bx] 00000006 8D5702 lea dx,[bx+0x2] 00000009 8D4F04 lea cx,[bx+0x4] 0000000C 01C1 add cx,ax 0000000E 01C1 add cx,ax 00000010 BB0A00 mov bx,0xa 00000013 81FB0E00 cmp bx,0xe (略)
先ほどのdis88とフォーマットがやや異なりますが、内容は一致しています。バイナリが併記されているので便利です。objdumpを使うかndisasmを使うかは好みです。