Well you cant see the actual memory location even if you mark this code as unsafe. That is because object is a managed data type, and you cant get address of an managed data type. If it would be an int or something then after putting this code in an unsafe{ } block you can take address of a variable same as you do it in C ie. by using & operator.
No, when an regular object is assigned to another object, it always points to the second objects memory address. This is evident from these lines:
Code:
object oVal1 = iNum; // oVal1 @ location YY ->value 16
object oVal2; // oVal2 @ location ZZ ->value null
oVal2 = oVal1; // oVal2 @ location YY ->value 16
First oVal2 was at ZZ, then after doing oVal2=oVal1, oVal2 is at YY, the location of oVal1. This is normal behavior of objects.
But any statement that causes boxing, a new memory is given to object. So when oVal2=32 was executed, a value type (int) is assigned to a reference type (object) so oVal2 is given a new memory.
Hope this clear things up for you