【问题标题】:Assembly for dereferencing a pointer用于取消引用指针的程序集
【发布时间】:2014-03-23 19:16:10
【问题描述】:

刚刚启动了一个 Visual Studio 项目来查看程序集以取消引用指针。我有这个 C++:

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

asm(用于取消引用):

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

我对上述问题有几个问题:

  1. dword ptr[x] 究竟是什么意思?指向x的指针地址?
  2. 为什么上面的值被复制到ecx?我知道这是因为正在调用 resize() 的函数,但为什么要特别注册 ecx 呢?
  3. 是取消引用mov dword ptr [x],ecx 部件的唯一装配线吗?

我正在尝试了解取消引用指针的成本。

【问题讨论】:

  • 当前 CPU 交错(部分)执行指令,确切的交错取决于周围的指令。取消引用的确切存储位置也会影响指令。因此,“取消引用的成本”作为价值意义不大。此外,在当前的 CPU 中,访问 RAM 的成本与数百条指令相同。不要担心这样的时间安排,除非测量表明这是你的瓶颈。

标签: c++ pointers assembly x86


【解决方案1】:

C++ 指针和底层架构

mov ecx, dword ptr [x] 表示:将 dword(32 位)从内存位置 x 移动到 ecx 寄存器。这只是汇编语言的一个语法特性,表示有内存访问,并且它的大小是 32 位。

在考虑指针时,记住一些关于底层架构的要点是有帮助的:

  • 处理器有少量寄存器(大约 16-32 个,具体取决于架构),用于存储机器大小的整数(x86 为 32 位,x64 为 64 位)。
  • 所有其余数据都必须保存在内存中,始终通过指针访问(即使您没有在代码中声明显式指针)。

因此,当您在 C++ 中实际声明指向对象的指针时,大多数情况下它不会影响生成的代码。例如,以下两段代码在优化编译时会产生相同的汇编代码:

Obj a;
a.function();

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

与您的代码的唯一区别是您在堆上分配内存(通过new)。这是一个额外的函数调用,它还意味着您必须在最后注意delete(您的演示代码错过了!)。除此之外,优化编译器将为x 的所有实际使用生成同等性能的代码。我猜你的代码是在没有优化的情况下编译的,否则内存访问会被完全优化掉。

在一种情况下,指向对象的单个指针是一种特殊情况:内存中的所有对象都必须通过指针访问,即使它们没有在 C++ 中明确显示。因此,一旦启用优化,单指针情况就与无指针情况相同。

指针链/链接结构

关于指针链的一个词,那些变得更慢并且需要多次内存访问。这种情况经常发生在链接结构中:

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

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

在这种情况下,需要取消引用几个指针才能访问最终的value

为什么选择 ecx?

向量的地址被复制到ecx 寄存器,因为这是this 指针在Microsoft fastcall convention 中的位置。

【讨论】:

  • 你写的真好。你能说明堆栈分配指令和堆分配指令是如何相同的吗?我从来没有意识到指针间接没有成本?!
  • 你知道Q2的答案吗?
  • 也许你的意思是a.function();
  • 我扩展了我的答案并修复了a.function(); 问题。感谢您的关注。
猜你喜欢
  • 1970-01-01
  • 2017-11-03
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 2013-01-04
  • 2013-02-20
相关资源
最近更新 更多