13

私は、アセンブリ言語を介して c++ が適切なメンバー関数を呼び出す方法を研究しています。私が付属している簡単なプログラムは次のとおりです。

class A                        
{                              
    public:                    
        virtual void show() {} 
};                             

class B : public A             
{                              
    public:                    
        void show() {}         
};                             


int main()                     
{                              
    A* pA = new B;             
    pA->show();                

    return 0;                  
}                              

そのアセンブリは次のとおりです。

main:
.LFB2:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    pushq   %rbx
    subq    $24, %rsp
    movl    $8, %edi
    .cfi_offset 3, -24
    call    _Znwm            <<<================ 1
    movq    %rax, %rbx
    movq    %rbx, %rax
    movq    %rax, %rdi
    call    _ZN1BC1Ev
.L11:
    movq    %rbx, %rax
    movq    %rax, -24(%rbp)
    movq    -24(%rbp), %rax
    movq    (%rax), %rax
    movq    (%rax), %rdx
    movq    -24(%rbp), %rax
    movq    %rax, %rdi
    call    *%rdx             <<<=== 2
    movl    $0, %eax
    addq    $24, %rsp
    popq    %rbx
    leave
    ret
    .cfi_endproc

私の質問は次のとおりです。

  1. Googleでnwmを検索しましたが、c ++がそれを使用してメモリを割り当てていることだけがわかりました。誰かがそれについてもっと教えてくれませんか? それは1つのlibにありますか?可能であれば、そのソース コードを入手できますか? どうやって?
  2. 私はこの構文にあまり慣れていません。何をしたいのですか?
4

1 に答える 1

19

*、呼び出しまたはジャンプ命令の AT&T アセンブリ構文で絶対アドレスの前に使用されます。これは、レジスタに含まれるアドレスにジャンプすることを意味します。もう 1 つの方法は、現在の命令に相対的な相対ジャンプです。

GNUasマニュアルから:

AT&T 絶対 (PC 相対ではなく) ジャンプ/呼び出しオペランドには、接頭辞 `*' が付きます。これらは Intel 構文では区切られていません。

あなたのコードでは、レジスタ内のアドレスへの呼び出しがあることは理にかなっています。呼び出すpA->show()には、呼び出される正しい関数が何であるかを確認するためにルックアップが必要です。これは、クラス A の仮想関数であるためです。

于 2013-09-30T06:59:35.823 に答える