Вы задаете вопросы о деталях реализации , поэтому ответ будет зависеть от конкретной реализации. Давайте рассмотрим версию вашей программы, которая на самом деле компилируется:
class A { public int VarA; }
class X
{
static void Main(string[] args)
{
A a1 = new A();
a1.VarA = 5;
A a2 = a1;
a2.VarA = 10;
}
}
вот что происходит на Microsoft CLR 4.0 с C # 4.0 в режиме отладки.
На данный момент указатель кадра стека скопирован в регистр ebp:
Здесь мы выделяем кучу памяти для нового объекта.
A a1 = new A();
mov ecx,382518h
call FFE6FD30
Возвращает ссылку на объект кучи в eax. Мы храним ссылку в слоте стека ebp-48, который является временным слотом, не связанным ни с одним именем. Помните, a1 еще не был инициализирован.
mov dword ptr [ebp-48h],eax
Теперь мы берем ту ссылку, которую мы только что сохранили в стеке, и копируем ее в ecx, которая будет использоваться для указателя «this» на вызов ctor.
mov ecx,dword ptr [ebp-48h]
Теперь мы называем ctor.
call FFE8A518
Теперь мы снова копируем ссылку, хранящуюся в слоте временного стека, в регистр eax.
mov eax,dword ptr [ebp-48h]
И теперь мы копируем ссылку в eax в слот стека ebp-40, который равен a1.
mov dword ptr [ebp-40h],eax
Теперь мы должны извлечь a1 в eax:
a1.VarA = 5;
mov eax,dword ptr [ebp-40h]
Помните, eax теперь является адресом выделенных в куче данных для объекта, на который ссылается a1. Поле VarA этой вещи составляет четыре байта в объекте, поэтому мы сохраняем 5 в это:
mov dword ptr [eax+4],5
Теперь мы делаем копию ссылки в слоте стека для a1 в eax, а затем копируем ее в слот стека для a2, то есть ebp-44.
A a2 = a1;
mov eax,dword ptr [ebp-40h]
mov dword ptr [ebp-44h],eax
И теперь, как и следовало ожидать, мы снова получаем a2 в eax, а затем добавляем четыре байта ссылки для записи 0x0A в VarA:
a2.VarA = 10;
mov eax,dword ptr [ebp-44h]
mov dword ptr [eax+4],0Ah
Таким образом, ответ на ваш вопрос заключается в том, что ссылки на объект хранятся в стеке в трех местах: ebp-44, ebp-48 и ebp-40. Они хранятся в регистрах в eax и ecx. Память объекта, включая его поле, хранится в управляемой куче. Это все на x86 в отладочной сборке Microsoft CLR v4.0. Если вы хотите узнать, как содержимое хранится в стеке, куче и записывается в какой-то другой конфигурации, это может быть совершенно иначе. Все ссылки могут храниться в куче или все в регистрах; может не быть стека вообще. Это полностью зависит от того, как авторы jit-компилятора решили реализовать семантику IL.