池袋バイナリ勉強会(8)に参加しました

11月25日(日)に開催された池袋バイナリ勉強会(8)に参加しました。PDP-11のバイナリ解析に取り組んでいます。a.outを逆アセンブルする自作スクリプトを作成しながら、平行してそれを実行するインタプリタを作ろうとしている段階です。

アセンブラの作成

以下のhello.cを逆アセンブルするプログラムの作成に取り組んでいます。

$ cat hello.c
main() {
  write(0, "hello\n", 6);
}

たったこれだけのコードですが、hello.cから生成されるa.outをpdp11-aout-objdumpで逆アセンブルしてみると、いろんな処理が行われているのが分かります。逆アセンブル結果が以下になります。

$ v6cc hello.c                # コンパイル
$ v6strip a.out               # シンボルテーブル削除
$ pdp11-aout-objdump -d a.out # 逆アセンブル

a.out:     ファイル形式 a.out-pdp11


セクション .text の逆アセンブル:

00000000 <.text>:
   0:	f009           	setd
   2:	1180           	mov	sp, r0
   4:	1226           	mov	(r0), -(sp)
   6:	0bd0           	tst	(r0)+
   8:	1036 0002      	mov	r0, 2(sp)
   c:	09f7 0008      	jsr	pc, 0x18
  10:	100e           	mov	r0, (sp)
  12:	09df 0052      	jsr	pc, *$122
  16:	8901           	sys	1
  18:	0977 0040      	jsr	r5, 0x5c
  1c:	15ce 0006      	mov	$6, (sp)
  20:	15e6 0086      	mov	$206, -(sp)
  24:	0a26           	clr	-(sp)
  26:	09df 0030      	jsr	pc, *$60
  2a:	2596           	cmp	(sp)+, (sp)+
  2c:	0077 003a      	jmp	0x6a
  30:	1166           	mov	r5, -(sp)
  32:	1185           	mov	sp, r5
  34:	1d40 0004      	mov	4(r5), r0
  38:	1d77 0006 0052 	mov	6(r5), $0x90
  3e:	1d77 0008 004e 	mov	10(r5), $0x92
  44:	8900           	sys	0
  46:	008e           	.word	216
  48:	8602           	bcc	0x4e
  4a:	0077 002a      	jmp	0x78
  4e:	1585           	mov	(sp)+, r5
  50:	0087           	rts	pc
  52:	1166           	mov	r5, -(sp)
  54:	1185           	mov	sp, r5
  56:	1d40 0004      	mov	4(r5), r0
  5a:	8901           	sys	1
  5c:	1140           	mov	r5, r0
  5e:	1185           	mov	sp, r5
  60:	1126           	mov	r4, -(sp)
  62:	10e6           	mov	r3, -(sp)
  64:	10a6           	mov	r2, -(sp)
  66:	0be6           	tst	-(sp)
  68:	0048           	jmp	(r0)
  6a:	1141           	mov	r5, r1
  6c:	1844           	mov	-(r1), r4
  6e:	1843           	mov	-(r1), r3
  70:	1842           	mov	-(r1), r2
  72:	1146           	mov	r5, sp
  74:	1585           	mov	(sp)+, r5
  76:	0087           	rts	pc
  78:	1037 0018      	mov	r0, $0x94
  7c:	15c0 ffff      	mov	$-1, r0
  80:	1146           	mov	r5, sp
  82:	1585           	mov	(sp)+, r5
  84:	0087           	rts	pc

自作の逆アセンブラによる出力は以下になります。Pythonで作成しています。

$ python ./script/dump.py a.out
text size: 134
data size: 14
   0: f009           setd                 170011
   2: 1180           mov sp, r0           010600
   4: 1226           mov (r0), -(sp)      011046
   6: 0bd0           tst (r0)+            005720
   8: 1036 0002      mov r0, 0o2(sp)      010066 000002
   c: 09f7 0008      jsr pc, 0o10(pc) => $0x18 004767 000010
  10: 100e           mov r0, (sp)         010016
  12: 09df 0052      jsr pc, @(pc)+ => 82(0o122 0x52) 004737 000122
  16: 8901           sys 1                104401
  18: 0977 0040      jsr r5, 0o100(pc) => $0x5c 004567 000100
  1c: 15ce 0006      mov $6, (sp)         012716 000006
  20: 15e6 0086      mov $206, -(sp)      012746 000206
  24: 0a26           clr -(sp)            005046
  26: 09df 0030      jsr pc, @(pc)+ => 48(0o60 0x30) 004737 000060
  2a: 2596           cmp (sp)+, (sp)+     022626
  2c: 0077 003a      jmp 0o72(pc) => $0x6a 000167 000072
  30: 1166           mov r5, -(sp)        010546
  32: 1185           mov sp, r5           010605
  34: 1d40 0004      mov 0o4(r5), r0      016500 000004
  38: 1d77 0006 0052 mov 0o6(r5), 0o122(pc) => $0x90 016567 000006 000122
  3e: 1d77 0008 004e mov 0o10(r5), 0o116(pc) => $0x92 016567 000010 000116
  44: 8900           sys 0                104400
  46: 008e           .word 0o216          000216
  48: 8602           bcc 0x4e             103002
  4a: 0077 002a      jmp 0o52(pc) => $0x78 000167 000052
  4e: 1585           mov (sp)+, r5        012605
  50: 0087           rts pc               000207
  52: 1166           mov r5, -(sp)        010546
  54: 1185           mov sp, r5           010605
  56: 1d40 0004      mov 0o4(r5), r0      016500 000004
  5a: 8901           sys 1                104401
  5c: 1140           mov r5, r0           010500
  5e: 1185           mov sp, r5           010605
  60: 1126           mov r4, -(sp)        010446
  62: 10e6           mov r3, -(sp)        010346
  64: 10a6           mov r2, -(sp)        010246
  66: 0be6           tst -(sp)            005746
  68: 0048           jmp (r0)             000110
  6a: 1141           mov r5, r1           010501
  6c: 1844           mov -(r1), r4        014104
  6e: 1843           mov -(r1), r3        014103
  70: 1842           mov -(r1), r2        014102
  72: 1146           mov r5, sp           010506
  74: 1585           mov (sp)+, r5        012605
  76: 0087           rts pc               000207
  78: 1037 0018      mov r0, 0o30(pc) => $0x94 010067 000030
  7c: 15c0 ffff      mov $177777, r0      012700 177777
  80: 1146           mov r5, sp           010506
  82: 1585           mov (sp)+, r5        012605
  84: 0087           rts pc               000207

mov の引数のパターン

Mode Name Symbolic Description
0 register R Rの値
1 register deferred (R) Rの値をアドレスと見なし、そのアドレスの値
2 auto-increment (R)+ Rの値をアドレスと見なし、そのアドレスの値; R+=2
3 auto-incr deferred @(R)+ Rの値をアドレスと見なし、そのアドレスの値をさらにアドレスとみなし、そのアドレスの値; R+=2
4 auto-decrement -(R) R-=2; Rの値をアドレスと見なし、そのアドレスの値
5 auto-decr deferred @-(R) R-=2; Rの値をアドレスと見なし、そのアドレスの値をさらにアドレスと見なし、そのアドレスの値
6 index X(R) R+Xの値をアドレスと見なし、そのアドレスの値
7 index deferred @X(R) R+Xの値をアドレスと見なし、そのアドレスの値をさらにアドレスと見なし、そのアドレスの値

表のSymbolicの括弧の意味は、C言語のポインタのデリファレンスと同じと捉えて良いようです。また、@ も同様でポインタのデリファレンスと同じ意味になります。ですから、@ ( R )+ は、( ( R ) )+ のように括弧が2重になったものと解釈すると良いと教えていただきました。C言語のポインタのポインタですね。

(今後の課題)条件式と符号なし整数

Lions’ Commentary on UNIX (Ascii books)』の278ページには以下の記述があります。

Cでは条件式を使うことができる。aとbが整数変数ならば、

 (a > b ? a : b)
はaとbの大きなほうを値として持つ式である。

ただし、これはaとbが符号なし整数とみなされる場合には機能しない。したがって、次の手続きを使用する。

 6326 max (a, b)
      char *a, *b;
      {
        if (a > b)
          return (a);
        return (b);
      }
ここでのトリックは、文字へのポインタとして宣言されたaとbが比較のために符号なし整数として扱われるということである。

aとbが符号なしの場合、条件式がなぜ機能しないのか疑問に思いました。その理由を勉強会で教えていただいたのですが、よく理解出来ませんでした……。まだまだ学ぶべきことが沢山あるので、今後の課題となります。理解できたら改めてブログに書くつもりです。