这个电话是从哪里来的?

时间:2012-03-19 20:00:51

标签: c# il disassembly

我有一些非常类似于以下内容的代码:

class C {
    string s;
    static C a = new C();

    static void Main() {
        C b = a;
        b.s = "hello";
}

在发布模式下,Main方法的反汇编如下:

        C b = a;
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  push        eax 
00000004  cmp         dword ptr ds:[04581D9Ch],0 
0000000b  je          00000012 
0000000d  call        763B3BC3 
00000012  xor         edx,edx 
00000014  mov         dword ptr [ebp-4],edx 
00000017  mov         eax,dword ptr ds:[01B24E20h] ; Everything up to this point
0000001c  mov         dword ptr [ebp-4],eax        ; is fairly clear.
        b.s = "hello";
0000001f  mov         eax,dword ptr ds:[01B22088h] ; Loads the address of "hello"
00000025  mov         ecx,dword ptr [ebp-4]        ; Loads the address of b
00000028  lea         edx,[ecx+4]                  ; Loads the address of (the reference to?) b.s
0000002b  call        76100AE0                     ; ??
    }
00000030  nop 
00000031  mov         esp,ebp 
00000033  pop         ebp 
00000034  ret 

我不明白为什么nb的电话是必要的。似乎b.ss的地址作为参数传递,但由于这是一个简单的指针赋值,为什么这是必要的?

(对于指针的大量赋值似乎会出现这种情况。但是,分配null似乎并不遵循这种模式。)

2 个答案:

答案 0 :(得分:5)

猜猜:它正在设置GC卡表,因为您正在创建从堆字段到堆对象的新引用。

你说“这种行为似乎发生在指针的很多任务上”。这非常适合这种解释。

答案 1 :(得分:0)

如果示例中的stringstd::string,那么您看起来无辜的作业如下:

mov  eax, offset "hello"
mov  ecx, b
lea  edx, [ecx+4] ; edx = &b.s
call std::string::operator=(const char *)

(看来这个特定的编译期望edx中的“this”和eax中的参数 - 可能是整个程序优化的结果 - 传统的约定是ecx和其他参数中的this在堆栈上。)

C ++和STL为您提供了很好的,最简单的内存管理。但它不是免费的。无论它在源代码中看起来如何,它绝对不是“简单的指针赋值”。