Анализ кода ассемблера C ++ (скомпилирован с помощью clang) - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь выяснить, как выглядит двоичный код C ++, особенно для вызовов виртуальных функций. Я придумал несколько любопытных вещей. У меня есть следующий код C ++:

#include <iostream>

using namespace std;

class Base {
 public:
  virtual void print() { cout << "from base" << endl; }
};

class Derived : public Base {
 public:
  virtual void print() { cout << "from derived" << endl; }
};

int main() {
  Base *b;
  Derived d;
  d.print();
  b = &d;
  b->print();
  return 0;
}

Я скомпилировал его с помощью clang ++, а затем использовал objdump:

00000000004008b0 <main>:
  4008b0:   55                      push   rbp
  4008b1:   48 89 e5                mov    rbp,rsp
  4008b4:   48 83 ec 20             sub    rsp,0x20
  4008b8:   48 8d 7d e8             lea    rdi,[rbp-0x18]
  4008bc:   c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  4008c3:   e8 28 00 00 00          call   4008f0 <Derived::Derived()>
  4008c8:   48 8d 7d e8             lea    rdi,[rbp-0x18]
  4008cc:   e8 5f 00 00 00          call   400930 <Derived::print()>
  4008d1:   48 8d 7d e8             lea    rdi,[rbp-0x18]
  4008d5:   48 89 7d f0             mov    QWORD PTR [rbp-0x10],rdi
  4008d9:   48 8b 7d f0             mov    rdi,QWORD PTR [rbp-0x10]
  4008dd:   48 8b 07                mov    rax,QWORD PTR [rdi]
  4008e0:   ff 10                   call   QWORD PTR [rax]
  4008e2:   31 c0                   xor    eax,eax
  4008e4:   48 83 c4 20             add    rsp,0x20
  4008e8:   5d                      pop    rbp
  4008e9:   c3                      ret    
  4008ea:   66 0f 1f 44 00 00       nop    WORD PTR [rax+rax*1+0x0]

У меня вопрос, почему в ассемблерном коде мы имеем следующий код:

  4008b8:   48 8d 7d e8             lea    rdi,[rbp-0x18]
  4008d1:   48 8d 7d e8             lea    rdi,[rbp-0x18]

1 Ответ

0 голосов
/ 15 мая 2018

Локальная переменная d в main() хранится в местоположении [rbp-0x18].Это в автоматическом хранилище, выделенном в стеке для main().

lea    rdi,[rbp-0x18]

Эта строка загружает адрес d в регистр rdi.По соглашению, функции-члены Derived обрабатывают rdi как указатель this.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...