jtalesを解析してみる その3
前回の続き。アセンブリコードを解析するとは言っても英単語を覚えたてで長文読解をするようなもんで、イディオムのように単語の組み合わせで意味が初めて分かるようにコードの組み合わせを理解しておくべきではないかなーと思ってよく遭遇しそうな組み合わせをまとめてみました。
If 文のコンパイル
if 文は je 命令を使って実現される。C言語などでif文を表現すると下記の通り。
if (i > 0)i = 1;
else
i = 2;
return i;
このプログラムをコンパイルすると下記のようなアセンブリコードが吐き出される。
cmpl $0, %edxje L1
jmp L2
L1:
文 i = 2 (else 部分) のコンパイル結果
L2:
return i (if の次の文) のコンパイル結果
比較演算子の計算結果もレジスタ %edx に書き込まれる。そこで %edx と 0 を比較して同じなら else に分岐し、そうでなければ then 部を実行する。C 言語では 0 が false で、0 以外が true である。
配列変数のコンパイル
局所変数として int a[10]; と宣言した場合、a[i] の内容をレジスタ %edx に読み出すためのコードは、下記の通り。
movl 変数 i の値, %edx
shll $2, %edx # 左へ 2bit シフトで 4 倍
movl %ebp, %ecx
subl $44, %ecx
addl %ecx, %edx
movl 0(%edx), %edx
上のコードははじめの2行で、配列の添字 (offset) の値を4倍して、a[0]用に割り当てられたメモリのアドレスから、何bytes離れたところに a[i] 用のメモリが割り当てられているか計算する。3-5 行目は、a[i]用に割り当てられているメモリのアドレスを求めている。例では a[0] はスタック・フレームの末尾から 12 番目なので、 $ebp - 44 の値が a[0] のアドレスである。a[i] はこれに i の 4 倍を足し合わせたものである。
ループのコンパイル
while 文のコンパイルは if 文のコンパイルとそれほど違いはなく、分岐がわずかに複雑になるだけである。
while (i < n) {
i = i + 1;
}
return i;
このプログラムは例えば次のようにコンパイルすればよい。
L1:
式 i < n のコンパイル結果 (%edx に結果が保存される)
cmpl $0, %edx
je L2
文 { i = i + 1; } のコンパイル結果
jmp L1
L2:
文 return i のコンパイル結果
L1, L2 はラベルである。while 文の制御構造をそのまま分岐命令に置きかえているので分かりやすそう。
もうひとつのwhile文のコンパイル方法
jmp L2
L1:
文 { i = i + 1; } のコンパイル結果
L2:
式 i < n のコンパイル結果 (%edx に結果が保存される)
cmpl $0, %edx
jne L1
文 return i のコンパイル結果
分岐命令 jne は jump on not equal の意味で、0 (zero) と %edx のが等しくなければ L1 に分岐する。
for文のコンパイル
for (i = 0; i < n; i = i + 1) {
j = j + 1;
}
return i;
このプログラムは例えば次のようにコンパイルすればよい。
文 i = 0; のコンパイル結果
L1:
式 i < n のコンパイル結果 (%edx に結果が保存される)
cmpl $0, %edx
je L2
文 { j = j + 1; } のコンパイル結果
文 i = i + 1 のコンパイル結果
jmp L1
L2:
文 return i のコンパイル結果
基本は while 文のコンパイルと同様である。また while 文でしたような工夫をすれば、for 文もループ一回あたりの分岐命令の数を減らすことができる・・・らしい
(OS/Programmingより引用)
う~ん・・・ここまで載せた情報を踏まえて適当にjtales流し読みしてみると、レジスタ計算して値を比較して条件にあったらジャンプ命令を実行する・・・みたいな箇所が多いですね。dateコマンドを使わないと数秒で蔵落ちしてしまう問題はおそらくtickの値を入れてる変数が扱える値(ビット数?)が小さいのが原因だと考えてるので検索を掛けてみたのですが・・・tickで調べると該当箇所が多すぎ(笑) む~・・・これは骨が折れそうだ。
ひとまずtickのことは置いておいて・・・2chスレでちらっと話題に出てたLevelManagerにでも手を出してみようかとおもいます。
もしよろしければ私のモチベーションアップの為にチャンネル登録お願いします!
コメント