私はジョナサン・バートレットの「基礎からプログラミング」の本からGNUアセンブリを学んでいます。Linuxでのx86 32ビットアセンブリでの関数呼び出しはどのように機能しますか?
関数呼び出しとスタックのトピックを調べているうちに、その動作を理解できません。以下は
は本に書かれているものです:
機能を実行する前に、プログラムは、彼らが文書化されていることを逆の順序でスタックに関数のパラメータのすべてをプッシュ。次に、プログラムは、どの機能を開始したいかを示す呼び出し命令を発行する。コール命令は2つのことを行います。まず、戻りアドレスである次の命令のアドレスをスタックにプッシュします。次に、関数の開始点を指すように命令ポインタ(%eip)を変更します。ですから、関数が起動する時に、スタックは、この(スタックの「トップ」は、この例の一番下にある)のようになります。
Parameter #N ... Parameter 2 Parameter 1 Return Address <--- (%esp)
関数のパラメータは、それぞれにプッシュされています最後に戻りアドレスがそこにあります。今、関数自体にはいくつかの作業があります。
まず、pushl%ebpを実行して、現在のベースポインタレジスタ%ebpを保存します。基本ポインタは、関数のパラメータとローカル変数にアクセスするために使用される特別なレジスタです。次に、movl%esp、%ebpを実行して、スタックポインタを%ebpにコピーします。これにより、基本ポインタから固定インデックスとして関数パラメータにアクセスできるようになります。このためにスタックポインタを使用できると思うかもしれません。しかし、あなたのプログラムの中では、引数を他の関数にプッシュするなど、スタックで他のことを行うことができます。スタックポインタを関数の先頭でベースポインタにコピーすることで、スタック上で物事を押したり押したりしている間でも、パラメータがどこにあるかを知ることができます。 %ebpは常にスタックポインタが関数の先頭にあった場所になるので、多かれ少なかれスタックフレームへの定数参照です(スタックフレームは関数内で使用されるすべてのスタック変数で構成されます。変数、およびリターンアドレス)。
Parameter #N <--- N*4+4(%ebp) ... Parameter 2 <--- 12(%ebp) Parameter 1 <--- 8(%ebp) Return Address <--- 4(%ebp) Old %ebp <--- (%esp) and (%ebp)
あなたが見ることができるように、各パラメータは%EBPレジスタを使用してアドレッシングモードをベースポインタを使用してアクセスすることができます。この時点で
、スタックは次のようになります。
著者が第2段落の後に伝えたいことについて簡潔なイントロを得ることができますか? ここでは、%esp、%ebpレジスタと%ebpが混乱しています。 ご協力いただきまして誠にありがとうございます。第2の図で
[正確に基本ポインタとスタックポインタは何ですか?彼らが何を指しているのですか?](https://stackoverflow.com/q/1395591/995714)、[ESPとEBPのレジスタは何ですか](https://stackoverflow.com/q/21718397/995714)、 [ESPとEBPの間には何か?](https://stackoverflow.com/q/15020621/995714)、[EBPフレームポインタレジスタの目的は何ですか?](https://stackoverflow.com/q/579262/995714) –
これは32ビットx86で、あなたが尋ねているLinux上で使用されている呼び出し規約を使用しています。そのため、あなたの質問タイトルを編集して、アセンブリを知っている人に見えるようにします。 "GNUアセンブリ"は構文です。他の呼び出し規約を使用してコードを記述することができます。 (あなたが読んでいる本は良いです、それを読んでください) –
@Yatendra:あなたが何を理解するかについて何か言いたいことはありますか?あなたが引用したブロック(特に "ダイアグラム")は、あなたがそれについて何かを理解していないと言うことを除いて、この質問に優れた答えを出すでしょう。 'push 'は'%esp - = 4'を実行してから '(%esp)'に保存されます。 –