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    

すっきりしました!