How do objects work in x86 at assembly level?

I am trying to understand how objects work at the assembly level. How exactly are objects stored in memory and how do member members access them?

(Editor's Note: The original version was too wide and had some confusion about how assembly and structure work in the first place.)

+3
source share
2 answers

Classes are stored in exactly the same way as structures, except when they have virtual elements. In this case, there is an implicit vtable pointer as the first element (see below).

( ). , . (: http://en.cppreference.com/w/c/language/struct). C, ++ struct class ( public: private:).

struct class , , , "". ; - , double . 3 1 int . A struct - C , .

( static), (malloc new) ( : C/++ ). ( struct, . , .)

, . C ++ int : http://en.cppreference.com/w/c/language/object. , memcpy ( -POD- ++).

ABI , , , , - struct { char a; int b; }; (, x86-64 System V ABI, Linux , Windows, , int - 32- , 4- . ABI - , , C ++ " ", ABI , .)

, offsetof(struct_name, member), ( C11 ++ 11). . alignof ++ 11 _Alignof C11.

, , C . (, char, 4, . - , , 64 32- .)

ABI .. fooobar.com/tags/x86/.... Agner Fog ABI, .


( -)

class foo {
  int m_a;
  int m_b;
  void inc_a(void){ m_a++; }
  int inc_b(void);
};

int foo::inc_b(void) { return m_b++; }

( http://gcc.godbolt.org/):

foo::inc_b():
    mov eax, DWORD PTR [rdi+4]
    lea edx, [rax+1]
    mov DWORD PTR [rdi+4], edx
    ret

, this ( rdi, SysV AMD64 ABI). m_b 4 /. lea post-increment, eax.

inc_a, . , inline non-member. , .


++ C-, . ( ).

class foo {
  public:
  int m_a;
  int m_b;
  void inc_a(void){ m_a++; }
  void inc_b(void);
  virtual void inc_v(void);
};

void foo::inc_b(void) { m_b++; }

class bar: public foo {
  virtual void inc_v(void);  // overrides foo::inc_v even for users that access it through a pointer to class foo
};

void foo::inc_v(void) { m_b++; }
void bar::inc_v(void) { m_a++; }

  ; This time I made the functions return void, so the asm is simpler
  ; The in-memory layout of the class is now:
  ;   vtable ptr (8B)
  ;   m_a (4B)
  ;   m_b (4B)
foo::inc_v():
    add DWORD PTR [rdi+12], 1   # this_2(D)->m_b,
    ret
bar::inc_v():
    add DWORD PTR [rdi+8], 1    # this_2(D)->D.2657.m_a,
    ret

    # if you uncheck the hide-directives box, you'll see
    .globl  foo::inc_b()
    .set    foo::inc_b(),foo::inc_v()
    # since inc_b has the same definition as foo inc_v, so gcc saves space by making one an alias for the other.

    # you can also see the directives that define the data that goes in the vtables

: add m32, imm8 , inc m32 Intel (- + ALU uops); , Pentium4 inc. gcc inc, - :/ INC ADD 1: ?


struct , , . , , struct , .

as-if : , asm, ( , , ++ "" ).

struct pair {
  int m_a;
  int m_b;
};

pair addsub(int a, int b) {
  return {a+b, a-b};
}

int foo(int a, int b) {
  pair ab = addsub(a,b);
  return ab.m_a * ab.m_b;
}

( g++ 5.4) :

# The non-inline definition which actually returns a struct
addsub(int, int):
    lea     edx, [rdi+rsi]  # add result
    mov     eax, edi
    sub     eax, esi        # sub result
                            # then pack both struct members into a 64-bit register, as required by the x86-64 SysV ABI
    sal     rax, 32
    or      rax, rdx
    ret

# But when inlining, it optimizes away
foo(int, int):
    lea     eax, [rdi+rsi]    # a+b
    sub     edi, esi          # a-b
    imul    eax, edi          # (a+b) * (a-b)
    ret

, . X86-64 SysV ABI , . ABI .

+9

(, "" - , "".)

Old ++ C . :

class foo {
  int m_a;
  void inc_a(void);
  ...
};

... C:

struct _t_foo_functions {
  void (*inc_a)(struct _class_foo *_this);
  ...
};
struct _class_foo {
  struct _t_foo_functions *functions;
  int m_a;
  ...
};

"" "", "" . C ( ++): "this". "struct" - .

, ++:

m_x=1; // implicit this->m_x
thisMethod(); // implicit this->thisMethod()
myObject.m_a=5;
myObject.inc_a();
myObjectp->some_other_method(1,2,3);

... C:

_this->m_x=1;
_this->functions->thisMethod(_this);
myObject.m_a=5;
myObject.functions->inc_a(&myObject);
myObjectp->some_other_method(myObjectp,1,2,3);

, C . , ...

++ C, - , ++-to-C.

"new" "delete" ( "malloc" "free" ), .

+3

Source: https://habr.com/ru/post/1694930/


All Articles