c++ - 取消引用指针的程序集

标签 c++ pointers assembly x86

刚刚启动了一个 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 部分的汇编代码吗?

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

最佳答案

C++指针和底层架构

mov ecx, dword ptr [x] 表示:将双字(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;

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

为什么选择 ecx?

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

关于c++ - 取消引用指针的程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22595749/

相关文章:

c++ - 在 SWIG 中将结构从 C++ 函数返回到 Python

C++ 参数是指向常量对象的指针,但未返回更新的对象?

c - 函数只返回字符串的字母

c++ - 如何在 VisualDsp++ 5 中为 Blackfin BF537 使用 *.cpp 文件中的 asm 实现的函数?

c - 当堆栈增长时,谁负责向操作系统请求页面?

c++ - 从程序集调用 C/C++ 函数 (OSX Mavericks x64)

c++ - 使用循环使相同的线程在没有 sleep 的情况下一次又一次地获得相同的互斥锁

c++ - 如何将 Delphi Stream 传递给 c/c++ DLL

c++ - 这个条件是如何被解析的?

c - 在 Linux 中从应用程序调用函数到动态加载库时无法将 void ponter 作为函数参数