2011-07-26 10 views
2

私は現在、「アセンブリ言語のガイド」のx86アセンブリを学習しています.241ページには、16ビットワードまたは32ビットワードのみがスタックに保存されると書かれています。これは本当ですか? C言語では、char配列は1バイトで構成されており、Cはコールスタックを使用する関数で構成されているため、スタックに保存されます。では何が間違っているのですか?x86の呼び出しスタックで1バイトを節約する

+1

[なぜPentium IA-32のスタックにバイトをプッシュできないのですか?](http://stackoverflow.com/questions/2586591/why-is-it-not-possible-to -push-a-byte-on-a-stack-on-pentium-ia-32)あなたのコンパイルがコンパイルするものを逆アセンブルし、それについて議論しましょう。 –

答えて

5

偶数バイトはゼロで埋められ、プッシュされる前に16ビットまたは32ビットワードに変換されます。

スタックを特定のサイズ(16または32)のプレートの積み重ねとして考えます。あなたがサイズプレートの半分を押すことができる方法はありますか?いいえ?サイズの半分を押したい場合でも、フルサイズのプレートを作って押します。

+0

私は、他の投稿でコメントしたいと思っていましたが、誰かまたは作者がそれを削除しました。これは私の他の質問です。つまり基本的にCはchar配列の最初の要素を初期化するようにします:movb $ 65、(%esp)forインデックス0?それ以前は、sub sizeofarray、%espのようなことをするでしょうか? – rob

+0

@rob:私はこれを元に戻しました。これはもう間違っていません:-)基本的にはそうですが、あなたの実装が何をするかを正確に見るために逆アセンブリを見てください。配列の先頭が 'esp'かどうかは、あなたが持っている他の自動変数に依存します。 –

2

これはpush命令に当てはまりますが、スタックを使用する唯一の方法ではありません。 x86には、現在のスタック位置へのポインタを格納するespレジスタもあります。

関数の引数はスタック上にあります。逆アセンブリのいくつかをチェックすると、コンパイラがそれらを取得する方法がわかります。通常の呼び出し規約では、charの引数はそれぞれ4バイトを占めます。配列は値で渡すことはできません。そのため、可能であればchar配列をどのように保存するかは問題になりません。

自動変数もスタックを占有しますが、配列要素は「プッシュ」を使用してスタックに個別に保存されません。一般に、関数は開始時にすべての自動変数のためのスペースを作成します - "esp"を含む "sub"命令を探します。次に、配列の開始点はespの既知のオフセットになります。自動変数と同じように、コンパイラはこのオフセットを使用して配列へのアクセスを生成します。スタックポインタを正しく整列させるために、配列の最後の後にはいくつかの部分があるかもしれませんが、要素間のパディングは必要ありません。

関連する問題