逆アセンブラとVMとアセンブラ

1. 命令表(一部拡張)

斜線で示した命令は、前回までのものに加えた命令である。実装せよ。

命令

引数1

引数2

引数3

ニモニック

内容

32

n

 

 

inc mem_n

mem_n = mem_n+1

34

n

 

 

print mem_n

mem_nの内容を表示

 

 

 

 

 

 

36

n1

n2

 

add mem_n1 mem_n2

mem_n1 = mem_n1+mem_n2

38

n1

n2

 

mult mem_n1 mem_n2

mem_n1 = mem_n1*mem_n2

 

 

 

 

 

 

64

n

x

 

setI mem_n x

mem_n = x (整数リテラルxmem_nに格納)

96

n

x

 

mov mem_n1, mem_n2

mem_n1 = mem_n2転送

 

 

 

 

 

 

255

 

 

 

end

プログラムの終了

 

 

 

 

 

 

1

 

 

 

printSP

 

2

 

 

 

printPeri

 

3

 

 

 

printQuestion

 

5

 

 

 

printA

 

6

 

 

 

println

改行

10

 

 

 

printIs

 

11

 

 

 

printAre

 

20

 

 

 

printThis

 

21

 

 

 

printThese

 

25

 

 

 

printTotal

 

30

 

 

 

printPen

 

31

 

 

 

printPens

 

 

2. (前回と同じ)算術式を計算するプログラムを作成中のアセンブラ言語で記述し、VM上で動作を確認せよ。例えば次のようなプログラムに対応するアセンブラプログラムを考えて見よ。

 x = 2;

 y = x * x + 2 * x * 1;

 print(y)

 

ヒント:かけ算命令はまだ作っていないので、addと同じやり方でmult命令を命令セットに加えて良い。また、今のアセンブラには転送命令(レジスタの値をコピーする命令)がない。Move命令を加えてもよい。(上の命令表では、mult命令、転送命令を増やした。)

 

Move命令が無くとも、一応コピーは可能である。例えばmem3の値をmem5にコピーしたいときは、

setI mem3 20

setI mem5 0

add mem5 mem3

のようにすると、

Mem3 20 ;

Mem5  0 :

Mem5 mem5 + mem3 = 20 + 0 = 20

となる。

 

考え方: 各変数をメモリに割り当てる。下記ではxmem0, ymem1とする。

途中で出てくる中間結果は他のメモリmem2tmp2,  mem3 tmp3 ... に割り当てる。

 

プログラム例:(一通りではない。もっと効率の良い方法もあると思われる。)

命令(ニモニックで)

コメント

結果

setI mem0 2  

(x 2)

x = 2

move mem2 mem0;

(tmp2 x)

 

mult mem2, mem0;

(tmp2 tmp2 * x)

tmp2 = x*x = 2 * 2 = 4

setI mem3 2     

(tmp3← 2)

 

mult mem3 mem0

 tmp3 tmp3 *x

tmp3 = 2 * x = 2 * 2 = 4

setI mem4 1

tmp4 1

 

mult mem3 mem4

tmp3 tmp3 * 1

tmp 3= 4 * 1 = 4

add mem2 mem3

tmp2 tmp2 + tmp3

tmp2 = tmp2  + tmp3
= 4 + 4 = 8

move mem1 mem2

y tmp2

y = 8

print mem1

display(y)

 

 

3. 2の挙動を調べる。紙の上でメモリ状態をトレースする。(エクセルを用いると良い)

 

トレースの考え方:一命令終わったごとに、何が出力されたか、メモリに入っているデータは何か、を書き取る。

 

 

 

最後まで続けてみよ。最後の部分は次のようになるはずである。(間違ってなければ。。)

 

 

4. 上の命令をVMで動かす際に、Eclipseのデバッガを用いて上記にトレースした動きと同じになるか試してみよ。

ブレイクポイントの設定(実行を中断するポイント)。Javaエディタで、止めたい行の左でダブルクリックすると○がつく。

 

エディタの中で右クリックで、デバッグ→javaアプリケーションを選択。

命令の入力。以下の例では、単純な命令列で実行。(setI mem0 20,  setI mem1 20,  ret)

ブレイクポイントで中断。(73行目を実行する手前でとまっている)1行進めるときはF6か、メニューでステップオーバーを選ぶ。

 

Switchは実行され、最初の命令64番の部分を実行する手前でストップしている。

 

何度かステップオーバーする。下記では、95行目の実行する寸前でとまっている。変数というタブ(皆さんの環境では同じポジションにはないかもしれない)の中を観察すると、直前の命令で変数pcに3が書き込まれた、という情報が観察できる。

 

95行目を実行すると、メモリに値が書き込まれる。メモリは、変数のタブのなかのmemoryの部分をひらけばよい。

 

さらにステップオーバーすると、次の命令(64 1 2)を実行する。書き込みの直後のmemoryの内容は、次のように観察できる。

もとの画面(javaの編集画面(javaパースペクティブ))に戻すときは、@の部分が赤いときは、プログラム(デバッガ上での)が実行されているので、押して止める。

次にAを押してでてくるプルダウンメニューから、Javaを選ぶ。

@

 

A

 

 

 

 

逆アセンブラとVMとアセンブラの関係(再掲)