バイナリかるたのコツ

バイナリかるたはパッと見ただけだと「こんなのできねーよ」と 思ってしまいがちです.

アーキテクチャかるたを例にして, ちょっとコツというか考えかたみたいなものを解説してみましょう. (ただし,裏付け無し推測多数のかなりテキトーな説明です. 間違い等あったらごめんなさい)

目次

※ エンディアンや命令長の理解のためには,まずは フィーリングで読むアセンブラ入門 の「本環境より調べた各アーキテクチャのスペック」を見よう!

■ 問題1

まず,以下のような問題が出たとします.

パッと見で,ビットマップデータの下半分に縦のラインが見えますね.

その直前の部分は色が濃くなっているので,機械語コードっぽいように思います. 縦線の部分は配列データっぽいのと機械語コードの後にあるということで,たぶん 再配置データかデバッグ情報のように思えますが,なんだか線が右側に寄っている ように見えます.また線の間隔は4ラインずつぐらいのように見えます. ということは32ビット・ビッグエンディアンのアーキテクチャのようです.

リトルエンディアンのアーキを除外できるので,この時点でかなり範囲をしぼれます. アーキテクチャかるたの取り札から考えると, MIPS,SH,68HC11,SPARC,680x0,H8,PowerPCあたりが候補になりますね. (8ビットアーキや16ビットアーキも含まれてるけど,ELFはそれらも32ビットとして 扱うようなので候補に入れちゃってます.あと厳密に言うとMIPSはリトルの場合も あるのだけど,まああまり気にしないで)

実はこのあたりの情報はELFヘッダを見てもわかります. 例えば以下の赤のところはELFヘッダで,32ビット・ビッグエンディアンという情報が あります.また青のところはその他の情報ですが,2バイト単位でビッグエンディアン で値が格納されているので,ここからもビッグエンディアンであることはわかります.

まあでもヘッダ見ただけで簡単に判断できるとそのうち隠されてしまったときに 対応できないので,ここではビットマップパターンから判断してみましょう. (そういうのがバイナリかるたの楽しみのひとつですし)

次に,機械語コードを見てみましょう.機械語コードは実行ファイルの頭のほうに あって,ビットマップ的にはいろんな色が出て濃くなっている部分です. たぶんこのへんでしょう.

後ろ3分の1は赤いのでテキストデータなので,文字列リテラルなどが置いてある .rodataのように思えます.その前3分の2の機械語コードの部分は,ちょっと 緑の線が縦に入っているように見えますね.

線の間隔は狭く,(4バイトでなく)2バイト単位に線が出ているように見えます. ということは偶数長命令か2バイト固定長命令のアーキテクチャに思えます. RISCマイコンっぽいです.

実際の機械語コードも見てみます. 頭のほうはゼロが多いのでおそらくヘッダ(たぶんELFのプログラムヘッダ)で, うしろのほうはASCIIに文字列が出てるので.rodataだろうから, たぶんこのへん.

機械語コードを見るときは,似たようなバイトパターンが出てないかをまず探します. すると0x5Eというバイトコードが連続で出ていることに気がつきます.

他に0x5Eが出ているところを探してみましょう.

4バイトアラインメントで考えたときに,0x5Eは1と3バイト目に出ていて, 2と4バイト目には出ていません.ということはやはり, 偶数長命令か2バイト固定長命令のアーキテクチャです.

これは,右端のASCII文字表示の部分を見てもわかります. 0x5Eの文字コードをASCII表示の位置に照らし合わせて見てみると, 0x5Eは「^」(べき乗記号)のようです.そしてASCII表示の部分では, 「^」が奇数位置に出ています.ASCII表示では,他にも「F」や「m」といった 文字が奇数位置に出て,縦のラインを作っていますね.うーん偶数長命令っぽい においがプンプンします.

あとは取り札から考えてみましょう. 取り札の候補から,まずは4バイト固定長命令のアーキを削除してみます. 残るのは,SH,68HC11,680x0,H8あたりです.

ただ68HC11は旧来のマイコンの命令セットで1バイト命令を持っているので, これも候補から外せそうです.残るのは,SH,680x0,H8の3つです.

うーん,あとはどこで判断しようか.ELFのアーキテクチャ番号でも見てみましょう.

この番号をすべて暗記している必要は無いですが(暗記してれば最強なのですが), 値をみることでだいたい推測ができます. 番号の採番がどのようなポリシーで行われているのかはよく知りませんが, 若い番号から順に割りふるのだと考えると,若い番号は古いアーキテクチャと 考えられます. 実際,〜0x20くらいまでの若い番号は,多く知られているような有名どころか, 歴史的に古めの(〜80年代あたりが起源の)アーキテクチャです. 逆に0x50以上くらいになるとそこそこ新しいアーキテクチャだったりします. 0x80を越えたらもう今どき流行りのアーキテクチャの可能性が高いです. あくまでおおまかに,ですが.

そうすると,680x0は除外できそうです(SHやH8に比べるとかなり古めなので). 残るはSHとH8ですが,SHの特徴は2バイト固定長命令,4バイト即値を扱うのが苦手 なため機械語コード中にデータとそれを飛び越すジャンプ命令が頻発するということ, H8の特徴は偶数長の可変長命令,16ビットCPUというところです. そんな目で機械語コードを見ると…あまり2バイト固定長のような感じはしません. ということで答えはH8,と判断できるでしょうか…まあ最後のほうは無理矢理感が ありますが,実際のかるた競技では,消去法とかで判断できるかなーと思います. あとはいちかばちかの賭けとか駆け引きとかですかねえ.

ちなみにH8は16ビットアーキテクチャ(32ビット拡張もあり)ですが, ELFは16ビットというものが無いので,デバッグ情報などは32ビットで 格納されるのでしょう,おそらく.

■ 問題2

さて,別の問題も見てみましょう.次はこんなのです.

あーこりゃ簡単だあれしかないわ,と思えたら良い感じです. 実際これは,ひとつのアーキにしぼり込めます.見かたを解説しましょう.

さっきと同じように,ビットマップの後ろのほうの縦線が出ている配列っぽいところ (再配置情報か,デバッグ情報)あたりを見てみます.

赤い部分はテキストデータで,たぶんいろんな文字列データだから無視します. 縦線部分を見てみると,なんだか左に寄っているように見えます. リトルエンディアンっぽいです.あと線の間隔がドット幅に対して広いので, 64ビットアーキテクチャのように思えます.

64ビット・リトルエンディアンということで,これはこれでだいぶしぼれます. アーキテクチャかるたの取り札から考えると, IA-64,x86-64,Alphaが候補です.一気にしぼれました. MIPSやPowerPCも64ビットアーキがあるけど主流じゃないし, そもそもこれらは今となってはビッグエンディアンの方が主流のように思うので 気にしない.(このへんはかるた競技としての確率での判断になりますね)

次に機械語コードを見てみましょう.

機械語コードのほうは, 明らかに4バイト単位で縦にそろっている感じがあります. ビットマップにも等間隔の縦線が出ていて, 固定長命令のRISCアーキテクチャっぽいです. RISCマイコンとかじゃなく,ワークステーション向きのコテコテのRISCって感じです.

ということは可変長命令の(しかも奇数長命令多数の)x86-64は除外できます. 残るのはIA-64かAlphaですが, IA-64はVLIWというアーキテクチャ(IA-64的にはEPICと言うのかな?)で, 1命令がなんと16バイト長でその中に3命令入っているという命令構造で, 16バイト単位に似たパターンが見られるという特徴があります. 対して上記の機械語コードは「01 80 FA 6B」というパターンが 各所に見られ,16バイト単位ということはなさそうです. なので答えはAlphaで決まり.これは割と簡単.

Alphaっぽさは,実は以下にも出ています.

似たような機械語コードが縦に4つ並んでいますが,右側のバイトは「1F 20」で 一致していますが,左側が異なる値になっています. 機械語のオペコードは上位桁の位置にあることが多いですから, これはまさに4バイト固定長のリトルエンディアンっぽい機械語コードです (下位桁は即値指定で,値がバラついているのだと思われる). そしてこれは,ASCII表示で空白の縦線が右側に出ていることにも現れています (ビットマップ画像では赤の縦線に見えるはず). ちなみにH8では0x5Eが2バイトアラインメントの左側に出てましたので, そっちはオペコードが左側にあるっぽく,ビッグエンディアンっぽい機械語コードと いえます.

■ 問題3

Alphaがあっさり解けて,なんだかノッてきました.どんどんいきましょう. 次はこんなのです.

うーん縦線部分を見ても,ビッグかリトルかよくわからない…. しかたがない,ELFヘッダを見てみましょうか.

あ,32ビット・リトルエンディアンみたいですね.

いやいやこれではちと説明不足ですね.詳しく見ると,

そのほかにも,0x0020〜0x004Fあたりに配置されているデータが左に詰まっていて, リトルエンディアンっぽく見えます.このあたりは0x00が多くしかも0x00が縦に 並んでいる感じが強いので,たぶんなんらかの(配列っぽい)データ構造でしょう. ということは位置的に,ELFのプログラムヘッダだと思われる.

ということはおそらくその直後にいっぱい出てくるバイトコードが, 機械語コードだと思われる.

うーん雑然としています.ビットマップ画像も機械語コードも, なんか縦にそろってるようなものは見えません. 奇数長命令や1バイト命令を持つ,旧来のマイコンっぽい感じがしますね. 68HC11とかかなあと思ってしまいますが,エンディアン違いますね….

瀕出するバイトコードを探してみましょう. 「0xEB」「0xEF」というのが各所に見られますが, ここでは「0xEB」を探してみます.

場所は全然そろっていません.奇数位置にも偶数位置にも現れています. ということは奇数長命令を持つ可変長命令セットか…しかもリトルエンディアン… しかも旧来のマイコンっぽい… ということでx86を取ってしまいたくなりますが,はい,お手つきです. もっと注意深く見てみましょう.

機械語コードには,x86で瀕出するはずの「0xC3」(ret)や, これも瀕出するはずの「C9 C3」(leave; ret)というパターンが見られません. またx86は,機械語コード部分がもっと白っぽくなります.理由は後述.

実はこれ,ひっかけ問題です.アーキテクチャ番号を見てみましょう.

0xADというやたら大きな値になっています.ということは,かなり最近の アーキテクチャくさいです.

最近のアーキで奇数長命令を持っているとすれば, ルネサスの新型マイコンRXかRL78です. 新型アーキなのに1バイト命令を持つということで話題になりました. RL78は取り札に無いので,これはRXしかありません. RXとRL78はアセンブラ短歌が できる貴重なアーキテクチャであることもわかっているので,(短歌的に)注目ですね!

■ 問題4

最後にもうひとつ解説です.以下の問題です.

もう詳しい解説は不要かと思いますが,今までと同じように見てみると… まず縦線的に,リトルエンディアンということがわかります. また機械語コードを見る限り,0xC3という値が瀕出していてしかも 場所はばらけています(奇数位置にも偶数位置にもある).

やっと来たか…という感じがしますね.そう,x86です.しかしちょっとひねって, 64ビットのx86-64です.ビットマップイメージ中に出ている縦線の間隔がビット幅に 対して広いので,64ビットであることがわかります.

x86のその他の特徴としては,相対アドレス指定が多いため 機械語コード中に 0xFF という値が横に連続で出ることが多いというのがあります. (コンパイラにもよるかとは思いますが)

これはビットマップ中で見ると,短い白い線が各所に入っているように見えて まるで高級な肉にサシが入っているようで,一般に「霜降り肉」と呼ばれています. 肥え太った命令セットを言い表わしているようで,言い得て妙です. (インテルなので国産肉じゃないのではというツッコミは無し)

■ まとめ

ほかにも命令コードの特徴として, MIPSやPowerPCなどのコテコテのRISC系は縦に黒い線が出る (3バイト目.16ビット即値指定の上位バイトがゼロであることが多いため), PowerPCは表示可能文字にマッピングされている命令が多いため赤っぽくなる (x86の霜降りに対して,一般に赤身肉と言われます.さすがPOWERアーキテクチャ, 力がつきそうです),V850もそれと同様の特徴がある(PowerPCよりも強く出やすい ようです),ARMは条件コードのため縦に水色の線が出る(有名ですね), といったところがあります.エンディアンやビット数である程度条件をしぼったら, あとはそういった個別知識で判断する,ということになるでしょうか.

とはいっても,バイナリかるたはまあ試験問題とかではなく遊びです. なのでこうすれば確実にわかるというような解法手順とか, 模範的な解きかたとか解きかたの答えとかがあるわけではなく, 漠然と推測したあとでいかにしぼりこむかとか,一発賭けに出るとか, 状況や相手の目を見て駆け引きするとかいったところが面白さになると思います.


メールは kozos(アットマーク)kozos.jp まで