Aquí hay una clase simple de C#:
public class C { public object O { get; set; } public int N { get; set; } }
Aquí hay una declaración de C# que inicializa una instancia de C
:
var c = new C { O = new object(), N = 0x11223344 };
Y aquí está su desensamblado x86, con optimizaciones habilitadas (recuperado a través de la ventana "Desensamblado" de Visual Studio):
01A70851 mov ecx,1654E00h 01A70856 call CORINFO_HELP_NEWSFAST (016430F4h) 01A7085B mov esi,eax 01A7085D mov ecx,73042734h 01A70862 call CORINFO_HELP_NEWSFAST (016430F4h) 01A70867 lea edx,[esi+4] => 01A7086A call 7485EC00 01A7086F mov dword ptr [esi+8],11223344h
Aquí está el código en la dirección 7485EC00:
7485EC00 mov dword ptr [edx],eax 7485EC02 cmp eax,371100Ch 7485EC08 jb 7485EC17 7485EC0A shr edx,0Ah 7485EC0D nop 7485EC0E cmp byte ptr [edx+33223E0h],0FFh 7485EC15 jne 7485EC1A 7485EC17 ret 7485EC18 nop 7485EC19 nop 7485EC1A mov byte ptr [edx+33223E0h],0FFh 7485EC21 ret
Este es el estado de los registros justo antes de llamar al 7485EC00:
EAX = 037123D4 EBX = 0137F570 ECX = 73042734 EDX = 037123C8 ESI = 037123C4 EDI = 0137F4E0 EIP = 01A7086A ESP = 0137F4C4 EBP = 0137F4C8 EFL = 00000216
Según tengo entendido, la función en la dirección 7485EC00 comienza asignando la referencia al object
recién creado (almacenado en eax
) al campo de respaldo de CO
( esi+4
). Eso es de esperar. Lo que me sorprendió son todas las operaciones adicionales posteriores.
En mi caso, eax
era 037123D4h, que no es inferior a 371100Ch, por lo que el código no toma el salto 7485EC08 jb 7485EC17
y, por lo tanto, continúa verificando/estableciendo la dirección en (edx >> 0Ah) + 33223E0h
a 0FFh.
Aquí están mis preguntas:
CO
? ¿Cuál es su significado?mov dword ptr [esi+4], eax
, similar a asignar a CN
(un campo de tipo de valor)?(edx >> 0Ah) + 33223E0h
?Por cierto, esto sucede tanto para .NET Framework como para .NET Core, tanto para x86 como para x64 (como se comprobó a través de https://sharplab.io/ ).
Para que quede claro: no tengo ningún problema. Es solo por curiosidad.