x86 アセンブリのオブジェクト ストレージとメンバー関数アクセスについて
オブジェクト ストレージ
x86アセンブリでは、構造体とクラスの両方を含むオブジェクトは、連続したメモリ ブロックとして格納されます。これらのブロック内では、メンバー変数が宣言された順序で順番に配置されます。各メンバー変数のアドレスは、ブロックがトラバースされるにつれて増加します。
メンバー関数アクセス
メンバー関数は、this ポインターを介してオブジェクトにアクセスできます。非メンバー関数では、オブジェクトのアドレスが最初の引数として暗黙的に渡されます。ただし、暗黙的な this ポインターがあるため、これはメンバー関数には当てはまりません。
this ポインターは、オブジェクトが格納されているメモリ ブロックの先頭を指します。このポインタを使用すると、メンバー関数はオブジェクトのデータ メンバーに直接アクセスして変更できます。
たとえば、メンバー変数 m_a と m_b を持つ foo という名前のクラスと、m_a をインクリメントするメンバー関数 inc_a がある場合、アセンブリinc_a のコードは次のようになります。
foo::inc_a(): mov eax, DWORD PTR [rdi+4] # eax = this->m_a lea edx, [rax+1] # edx = eax + 1 mov DWORD PTR [rdi+4], edx # this->m_a = edx ret
仮想メンバー関数
仮想メンバー関数を持つクラスの場合、追加レベルの間接参照が導入されます。クラスの各インスタンスは、仮想関数テーブル (vtable) へのポインターを格納します。 vtable には、仮想メンバー関数の実際の実装へのポインターが含まれています。
仮想メンバー関数が呼び出されると、プログラムはまずその関数の vtable エントリにジャンプします。ジャンプ ターゲットは実際の関数実装であり、その後実行されます。
オブジェクト ストレージの最適化
オブジェクトは通常メモリに格納されますが、レジスタに格納される場合もあります。 。コンパイラーは、使用中ずっとオブジェクトをレジスターに保持できる場合、メモリー内にオブジェクトを配置することを回避するようにコードを最適化できます。この最適化は、オブジェクトがレジスタに収まるほど小さく、そのメンバーが積極的に使用されている場合に可能です。
たとえば、値によって小さな構造体を返す関数は、それにメモリを割り当てられない可能性があります。代わりに、コンパイラは構造体のメンバーをレジスタにパックし、それらを直接返す場合があります。
以上がメンバー関数はどのようにして x86 アセンブリ内のオブジェクト データにアクセスし、変更しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。