user997112
user997112

Reputation: 30605

Assembly for dereferencing a pointer

Have just started a visual studio project to look at the assembly for de-referencing a pointer. I had this C++:

int main(){
    std::vector<int>* x = new std::vector<int>();
    x->resize(10);
    return 1;
}

asm (for the de-referencing):

mov         dword ptr [x],ecx 
    x->resize(10);
push        0Ah  
mov         ecx,dword ptr [x]  
call        std::vector<int,std::allocator<int> >::resize (0BC124Eh) 

I have a few questions about the above:

  1. What does dword ptr[x] actually mean? The pointer address which refers to x?
  2. Why is the above value copied in to ecx? I understand this is because a function call to resize() is being made, but why ecx register in particular?
  3. Is the only line of assembly for the dereferencing the mov dword ptr [x],ecx part?

I am trying to understand the cost of a pointer being de-referenced.

Upvotes: 4

Views: 5353

Answers (1)

Christian Aichinger
Christian Aichinger

Reputation: 7227

C++ pointers and the underlying architecture

mov ecx, dword ptr [x] means: move the dword (32 bits) from memory location x to the ecx register. It is just a syntax feature of the assembly language to signify that there's a memory access and that it's size is 32 bits.

When thinking about pointers, it helps to keep a few points about the underlying architectures in mind:

  • The processor has a small number of registers (about 16-32, depending on the architecture), which store machine sized integers (32 bits for x86, 64 bits for x64).
  • All the rest of the data has to be kept in memory, which is always accessed via pointers (even if you don't declare an explicit pointer in your code).

So when you actually declare a pointer to an object in C++, for the most part it doesn't influence the generated code. For example, the following two pieces of code will produce the same assembly code when compiled with optimization:

Obj a;
a.function();

Obj a;
Obj *b = &a;
b->function();

The only difference with your code is that you allocate memory on the heap (via new). That's one extra function call, and it also implies that you have to take care to delete it at the end (which your demo code misses!). Apart from that, an optimizing compiler will generate equally performant code for all actual usage of x. I guess your code is compiled without optimization, because otherwise the memory access would have been optimized away completely.

In a case a single pointer to an object is a special case: all objects in memory must be accessed via pointers, even if they do not explicitly show up in C++. So the single pointer case becomes identical with the no-pointer case, once optimization is enabled.

Pointer chains / linked structures

One word about pointer chains, those become slower and require multiple memory accesses. This happens often with linked structures:

struct C { int value; };
struct B { C* c; };
struct A { B* b; };

A a = initialize_A();
a->b->c->value = 7;

In this case, several pointers need to be dereferenced to access the final value.

Why ecx?

The address of the vector is copied to the ecx register, because that's where the this pointer goes in the Microsoft fastcall convention.

Upvotes: 6

Related Questions