Binary2.0勉強会 1
アセンブラを勉強しよー。
その前に簡単に計算機について。計算機というのは基本的にはCPUさんが色々頑張る物体なのですが、計算機さんは機械語という言語を喋る子で、その機械語であれしろこれしろと命令されないと自分からこっちの意志を汲み取って何かしてくれたりはしません。
じゃあ機械語喋ろうか、となるのですが、これがまた人間に優しくない言語でとても困る。仕方ないので機械語を人間がそこそこ喋れるような感じにしたものを作りました。それがアセンブリ言語で、これから勉強するアセンブラというのはそのアセンブリ言語を機械語に翻訳してくれる物のことです。それはつまりアセンブリ言語を勉強するんじゃないの?とか言わない。
さて今回は、機械語の塊みたいなオブジェクトファイルさんを逆アセンブル(機械語からアセンブリ言語に翻訳)してひとまず表示するとこまでいきます。
ということでおもむろに教科書とかに乗ってそうな何もしないCのコードを書いてコンパイルしてみます。
niha@hoge:~/src/c$ cat bin01.c int main(){ return 0; } niha@hoge:~/src/c$ gcc -o bin01 bin01.c
これで bin01 という実行形式のファイルができました。こいつの中には基本的に機械語がたくさんつまっているわけですね。
さてこういうファイルを覗きたいときはどうするかというと objdump とかいうコマンドを使うといいらしい。オプションには -d を指定してやります。これで逆アセンブル(機械語からアセンブリ言語に翻訳)したものを出力してくれます。
niha@hoge:~/src/c$ objdump -d bin01 bin01: file format elf32-i386 Disassembly of section .init: 08048254 <_init>: 8048254: 55 push %ebp 8048255: 89 e5 mov %esp,%ebp 8048257: 53 push %ebx 8048258: 83 ec 04 sub $0x4,%esp 804825b: e8 00 00 00 00 call 8048260 <_init+0xc> 8048260: 5b pop %ebx 8048261: 81 c3 ac 12 00 00 add $0x12ac,%ebx 8048267: 8b 93 fc ff ff ff mov -0x4(%ebx),%edx 804826d: 85 d2 test %edx,%edx (中略) 080483fc <_fini>: 80483fc: 55 push %ebp 80483fd: 89 e5 mov %esp,%ebp 80483ff: 53 push %ebx 8048400: 83 ec 04 sub $0x4,%esp 8048403: e8 00 00 00 00 call 8048408 <_fini+0xc> 8048408: 5b pop %ebx 8048409: 81 c3 04 11 00 00 add $0x1104,%ebx 804840f: e8 dc fe ff ff call 80482f0 <__do_global_dtors_aux> 8048414: 59 pop %ecx 8048415: 5b pop %ebx 8048416: c9 leave 8048417: c3 ret
はい意味が分かりませんね。何で何もしないコードのはずなのに、こんなに大きな物体ができてしまったのでしょうか。ちなみに、
niha@hoge:~/src/c$ objdump -d bin01 | wc -l 207
207行だそうです。つけあがるなよ。
何が悪かったかというと(悪くはないけど)、何もしないようなコードでも、実は裏でこそこそとgcc君が色々とくっつけてくれているのです。
知ったことか、ボクが欲しいのは自分の書いたコードの部分だけなんだよ!pltとかなんだようざいよ!
いやいやキミ、gcc君も色々大変なんだよモダンなオブジェクトファイルは何か色々ややこしくってごにょごにょ…そうだ -c オプションを使いなさい。
gcc -c bin01.c
ということで -c オプションをつけると bin01.o とかいう怪しげな物ができます。これは何かというと、コンパイルとアセンブルだけをさせるオプションらしくて、リンカさんとかはすっこんでしまう。その結果オブジェクトファイルが出力されます。オブジェクトファイルは実行形式のように機械語がつまってる物体なのですが、実行するには実は色々と足りない(実行できたらリンカさんいりませんね)。
ちなみに cat bin01.o とかすると端末が狂うからやめとけよな!(やった)
よいこは素直に objdump -d しましょう。
niha@hoge:~/src/c$ objdump -d bin01.o bin01.o: file format elf32-i386 Disassembly of section .text: 00000000 <main>: 0: 8d 4c 24 04 lea 0x4(%esp),%ecx 4: 83 e4 f0 and $0xfffffff0,%esp 7: ff 71 fc pushl -0x4(%ecx) a: 55 push %ebp b: 89 e5 mov %esp,%ebp d: 51 push %ecx e: b8 00 00 00 00 mov $0x0,%eax 13: 59 pop %ecx 14: 5d pop %ebp 15: 8d 61 fc lea -0x4(%ecx),%esp 18: c3 ret
すっきりしました!