-6

C ++クラスのデータ構造は何ですか?アセンブリレベルでどのように機能しますか?

IFステートメントは、コード行の比較+条件付きジャンプです。

配列と文字列はデータのチェーンリンクです。

4

1 に答える 1

3

コンパイラーはすべてのメンバーにオフセットを割り当て、メンバーに対するすべてのロード/ストア操作にこれらを含めます。

struct foo {
    uint32_t bar;
    uint32_t baz;

    uint32_t get_baz() { return baz; }
};

uint32_t get_baz_from_foo(foo *f) { return f->baz; }

になる(簡単にするために使用されるARMアセンブラコード):

foo__get_baz:
    ; calling convention: this pointer in r3
    ; load 32 bit value from r3 + 4 bytes into r0
    ldr r0, [r3, #4];
    ; calling convention: return value in r0
    ; return from subroutine
    b lr

get_baz_from_foo:
    ; calling convention: first parameter in r0
    ; load 32 bit value from r0 + 4 bytes into r0
    ldr r0, [r0, #4]
    ; calling convention: return value in r0
    ; return from subroutine
    b lr

structそれぞれclassのレイアウトはコンパイル後に変更されないため、ここでは4が命令ストリームにハードコードされています。

インスタンスの作成は、メモリを割り当て、割り当て関数から構造体へのポインタを期待するすべての人にポインタを渡すことで機能します。

new__foo:
    ; two 32 bit integers need 8 bytes
    ; calling convention: first parameter in r0
    mov r0, #8
    ; call allocator, which will then return to the function invoking new
    bra malloc

コンストラクターがある場合

struct foo2 {
    foo2() : bar(5), baz(7) { }
    uint32_t bar;
    uint32_t baz;
    uint32_t get_baz() { return baz; }
};

最終的に、オブジェクトを作成するためのもう少し複雑な方法になります(コメントなしで理解できるはずです)。

new__foo2:
    strdb lr, ![sp]
    mov r0, #8
    bl malloc
    mov r1, #5
    str r1, [r0]
    mov r1, #7
    str r1, [r0, #4]
    ldaia lr, ![sp]
    b lr

実装はクラスのget_baz場合と同じです。foo

ここで、そのようなオブジェクトを作成してbaz値を取得すると、次のようになります。

    bl new__foo2
    ; remember: the this pointer goes to r3
    mov r3, r0
    bl foo2__get_baz

値がr0含まれることになります7

メソッドの場合virtual、関数のテーブルへのポインターである非表示のデータメンバーが作成されます。

struct base {
    virtual uint32_t get_baz() = 0;
};

struct derived : base {
    derived() : baz(5) { }
    virtual uint32_t get_baz();
    uint32_t bar;
    uint32_t baz;
};

になります

new__derived:
    strdb lr, ![sp]
    mov r0, #12
    bl malloc
    mov r1, #5
    str r1, [r0, #8]
    ; get the address of the vtable
    ldr r1, =vtable__derived
    ; vtable typically goes to the end of the class defining it
    ; as this is the base class, it goes before derived's data members
    str r1, [r0]
    ldria lr, ![sp]
    b lr

vtable__derived:
    ; pointer to function
    dw derived__get_baz

derived__get_baz:
    ldr r0, [r3, #8]
    b lr

この関数の呼び出しは間接的に行われます。

    ; construct normally
    bl new__derived
    ; here, we forget that this is a "derived" object
    ; this pointer to r3
    mov r3, r0
    ; get vtable ptr
    ldr r0, [r3]
    ; get function ptr from vtable
    ldr r0, [r0]
    ; call function
    bl r0

これが、コンストラクターr05そこに格納したものであるためです。

于 2012-10-11T17:37:32.413 に答える