Binary2.0勉強会 3

レジスタとスタックの説明が前回いい加減な感じで終わったので、今回はいい加減逆アセ結果見ながら命令の解説とかしますが、勿論ボクはあんまり分かってない。
とりあえずその前に、命令のリファレンスを「IA-32 インテル(R) アーキテクチャ・ソフトウェア・デベロッパーズ・マニュアル 命令セット」とかでぐぐって手に入れておきましょう。ちなみにふざけんなよってくらい多いです。これがCISCか…!

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    

一行目から順に説明していきます。

lea    0x4(%esp),%ecx

LEA Load Effective Address。第二オペランドの実行アドレスを計算し、第一オペランドにストアする。らしいです。何故か第二、第一の順に並んでるらしい。
基本的に値の代入というかコピーというか、は後でも出てくる mov という命令を使うのですが、こちらはアドレス限定でちょっと便利です。よく知りませんが、多分作った人はアドレス操作は頻繁に行われるから、それ専用の命令があった方がコードサイズ小さくなっていいよね、とか考えたんじゃないかなあ…
ちなみに「実行アドレスを計算し」とか、さもアドレス限定みたいなこといいながら、全然そんなこと無い気がするんですけどそういうものなんですかね。後で試そう。
第二オペランドは「0x4(%esp)」ですが、これは「esp + 4」という意味になります。esp はスタックポインタなので、この命令によって ecx はスタックポインタの4つ先のアドレスを指すことになります。
次二行目。

and    $0xfffffff0,%esp

AND Logical AND。第一オペランドと第二オペランドとの間のビット単位のAND(論理積)演算を実行し、結果を第一オペランドにストアする。らしいです。
「$0xfffffff0」は整数リテラルみたいなものですね。$0xから始まる場合は16進数、$0bから始まる場合は2進数だった気がします。まあマクロですね。esp の下4bitを0にしてます。よく分かりませんが、アラインメントか何かかな?まだなんとも分かりません。
三行目。

pushl  -0x4(%ecx)

PUSH Push Word or Doublewode onto the Stack。スタックポインタをデクリメントし、次にオペランドをスタックトップにストアする。らしいです。
お尻の「l」は多分「long」つまり32ビットで扱うということなんだと思います。ということはもしかして他のって32ビットで扱ってないのかなあ?32ビットCPUだしどう考えても32ビットで扱ってると思いますが…
先ほど一行目で ecx は esp + 4 を指しているので、-0x4(%ecx) は元の esp のアドレスを指しています。スタックにスタックポインタがつまれました。ついでに esp の値がデクリメントされます。
4行目。

push   %ebp

ベースポインタがスタックにつまれました。今度はlがないけど気にしないで行きましょう。
5行目。

mov    %esp,%ebp

MOV Move。第二オペランドを第一オペランドにコピーする。そのまんまですね。
ベースポインタが現在のスタックポインタに書き換えらました。
とりあえず mov まで来たので一旦おしまい。