Capture The Frog

かえるぴょこぴょこw

MENU

アセンブリ言語入門 その6

 

今回は、関数について書いていきたいと思います。

 

関数に触れる前に

関数が呼び出されると、制御は別のメモリアドレスに移動します。

CPUはそのメモリアドレスで処理を実行し、処理が終わると元のメモリアドレスに戻ってきます。関数のパラメータ、ローカル変数、フロー制御はすべてスタックと呼ばれる

メモリの重要な領域に保存されます。

まずスタックについて軽く説明していきます。

スタック

スタックとはスレッド作成時にOSによって作られるデータ構造です。

そして、LIFOを採用しています。(後入れ先出し、Last In First Outの略ね。

つまり、PUSH・POP命令でスタックのデータをやりとりするということです。

 

PUSH命令・POP命令

 PUSH命令は、4バイト値をスタックにプッシュ(格納し、

POP命令は、4バイト値をスタックからポップ(取りだします。


push source        ;sourceをスタックの最上部にプッシュします。
pop des            ;スタックの最上部の値をdesにコピーします。

スタックは、上位アドレスから下位アドレス方向へデータを積み上げていきます。

つまり、スタックが作成されるとESPレジスタ(スタックポインタ)がスタックの上位アドレス(先頭)を指しています。

スタックにデータをプッシュするとESPレジスタの値が4バイトずつ減少し、

スタックからデータをポップするとESPレジスタの値が4バイトずつ増加します。

 

 

関数

アセンブリ言語のCALL命令を利用して、関数を呼び出すことができます。


call fanction     ;関数の呼び出し

関数を大きなメモリアドレスだと考えるとわかりやすいです。

関数が終了されるとリターンアドレスがスタックから取り出され、メモリアドレス

から実行が継続されます。

 

関数の終了には、RET命令を使います。

この命令はスタックの最上部にあるリターンアドレスをポップします。

そして、制御はポップされたアドレスに移行します。

 

関数パラメータと戻り値

x86において、関数が受け取るパラメータはスタックにプッシュされ

戻り値がEAXレジスタに格納されます。

C言語アセンブラでおなじ処理を書いていきます。


int test(int a,int b)
{
   int x,y;
   x=a;
   y=b;
   return 0;
}
int main(){
test(2,3)
return 0;
}

これをアセンブリで表すと、


test:
push ebp ;フレームポインタ(EBPをスタックに保存する
mov ebp, esp ;EBP=ESP
上の2行の処理を関数プロローグという。
sub esp, 8 ;ESPレジスタを減らしている
mov eax, [ebp+8] ;関数の実際の処理
mov [ebp-4], eax |
mov ecx, [ebp+0ch] |
mov [ebp-8], ecx ↓  
xor eax, eax ;eaxの値を0にする。return 0;を示す
mov esp, ebp ;ESPはEBPに格納されているメモリアドレスを指す。
上の2行を関数エピローグという。
pop ebp          ;スタックから古いEBPを復元する
ret             ;スタックの先頭の戻りアドレスがポップ。制御が戻る

main: push 3 ;3をスタックにプッシュ
push 2 ;2をスタックにプッシュ
call test ;test関数を呼び出す
add esp, 8 ;test関数が実行された後、制御がここに戻ってくる
xor eax, eax        ;レジスタ値をクリアにする。return 0;を示す。

 

 という感じです。スタックが登場して少しややこしくなりました。

関数プロローグとは、関数が利用できる環境のセットアップをしています。

そして、関数エピローグとはプロローグとは逆のことをして元の環境を復元します。

また、main関数はtest関数を呼び出しているので"呼び出し元関数"。

test関数は呼び出されているので"呼び出し先関数"といいます。

main関数の


add esp, 8

 は、test関数で使用したスタックにプッシュされたパラメータを削除する役割があり、

関数を呼び出す前のスタックポインタに戻しています。

 

 

今回は、関数についてやってきましたが少し難しかったです。

ここは、自分でも少しわからないところがあるので、後で見返してみようと思いました。

みなさんも、おつかれさまでした。

次回は、配列と文字列をやっていきます。これでアセンブラ言語入門は一区切りつけたいと思います。

qwertytan.hatenablog.jp