我一直在研究针对某些典型C#构造执行的汇编代码的一些细节。调试简单的C#代码时,我在Visual Studio拆卸窗口中遵循其执行(这是具有完整调试信息的应用程序构建的版本)。
我们有以下代码片段:
return Interlocked.Increment(ref _boxedInt);
00007FFD6CFB5522 sub esp,30h
00007FFD6CFB5525 lea rbp,[rsp+30h]
00007FFD6CFB552A mov qword ptr [rbp+10h],rcx
00007FFD6CFB552E cmp dword ptr [7FFD6C166370h],0
00007FFD6CFB5535 je 00007FFD6CFB553C
00007FFD6CFB5537 call 00007FFDCBCFFCC0
00007FFD6CFB553C mov rcx,qword ptr [rbp+10h]
00007FFD6CFB5540 cmp dword ptr [rcx],ecx
00007FFD6CFB5542 mov rcx,qword ptr [rbp+10h]
00007FFD6CFB5546 add rcx,8
00007FFD6CFB554A call 00007FFDCA6624B0
00007FFD6CFB554F mov dword ptr [rbp-4],eax
00007FFD6CFB5552 mov eax,dword ptr [rbp-4]
00007FFD6CFB5555 lea rsp,[rbp]
00007FFD6CFB5559 pop rbp
00007FFD6CFB555A ret
call 指令在> 00007FFD6CFB554A 地址(实际上是对互锁的呼叫)不会遵循执行到子例程。
我打算查看互锁时执行什么代码。执行插入。
为什么调试器不遵循执行,将执行到称为子例程?
如何强迫它进入该呼叫(C#项目启用了混合调试)?
谢谢汉斯的工作...某种程度上;)
没有JIT优化,它看起来像:
00007FFDCA6624B0 nop dword ptr [rax+rax]
00007FFDCA6624B5 mov eax,1
00007FFDCA6624BA lock xadd dword ptr [rcx],eax
00007FFDCA6624BE inc eax
00007FFDCA6624C0 ret
随着JIT优化,一切都更加复杂。它只是一个很难包含的结构的代码,但它在那里:
00007FFD6CD7219F lea rax,[rsi+8]
00007FFD6CD721A3 mov edx,1
00007FFD6CD721A8 lock xadd dword ptr [rax],edx
00007FFD6CD721AC lea eax,[rdx+1]
看来它返回eax中的增量值。
尽管我设法实现了自己的目标,但我遇到了一些困难。
关闭"抑制在模块加载上的JIT优化"时,并在代码中放置了一个断点,我无法在汇编窗口中跟踪执行。当逐步进入第一次通话指令时,过程已终止(违反访问)。我必须采用其他方法,然后切换到debugger.break()互锁之前。
- 启动我的应用而无需调试
- 附加调试器,好像我的应用是本地的
- 触发互锁的执行(在此之前的调试器中断)。
我能够跟踪自己的需求。但是,如果我的应用程序直接从VS中进行调试,为什么会崩溃?我想该调试器并未将其附加到应用程序上。但是,为什么我们关心的只是汇编窗口中的指令流?
考虑到我们启用了"抑制JIT在模块负载上的抑制JIT优化",为什么调试器不逐渐介入呼叫并在Interlocked中揭示代码。再一次 - 这些只是CPU说明。没有托管和本机说明,对
在评论中提到的是互锁。信息是不受管理的代码。以哪种方式无法管理,因为所有这些都归结为少数CPU说明?是什么使它不受管理,为什么?它不是系统调用,也不是任何取决于未管理资源的东西。实际上,它指的是所指和使用的所有内容。那为什么?