• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#使用汇编

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文告诉大家如何在 C# 里面使用汇编代码

请看

C#嵌入x86汇编——一个GPIO接口的实现 - 云+社区 - 腾讯云

C# inline-asm / 嵌入x86汇编 - 苏璃 - CSDN博客

通过这个方法在 dotnet core 获取 CPU 信息

[StructLayout(LayoutKind.Sequential)]
internal ref struct CpuIdInfo
{
    public uint Eax;
    public uint Ebx;
    public uint Ecx;
    public uint Edx;


    public static void AppendAsString(StringBuilder builder,uint value)
    {
        var val = value;

        while (val != 0)
        {
            builder.Append((char) (val & 0xFF));
            val >>= 8;
        }

    }

    public string GetString()
    {
        StringBuilder ret = new StringBuilder(16);
        AppendAsString(ret,Ebx);
        AppendAsString(ret,Edx);
        AppendAsString(ret,Ecx);

        return ret.ToString();
    }
}
internal sealed class CpuIdAssemblyCode
    : IDisposable
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void CpuIDDelegate(int level, ref CpuIdInfo cpuId);

    private IntPtr _codePointer;
    private uint _size;
    private CpuIDDelegate _delegate;

    public CpuIdAssemblyCode()
    {
        byte[] codeBytes = (IntPtr.Size == 4) ? x86CodeBytes : x64CodeBytes;

        _size = (uint) codeBytes.Length;
        _codePointer = NativeMethods.Kernel32.VirtualAlloc(
                IntPtr.Zero,
                new UIntPtr(_size),
                AllocationType.COMMIT | AllocationType.RESERVE,
                MemoryProtection.EXECUTE_READWRITE
            );

        Marshal.Copy(codeBytes, 0, _codePointer, codeBytes.Length);
#if NET40
        _delegate = (CpuIDDelegate) Marshal.GetDelegateForFunctionPointer(_codePointer, typeof(CpuIDDelegate));
#else
        _delegate = Marshal.GetDelegateForFunctionPointer<CpuIDDelegate>(_codePointer);
#endif

    }

    ~CpuIdAssemblyCode()
    {
        Dispose(false);
    }

    public void Call(int level, ref CpuIdInfo cpuInfo)
    {
        _delegate(level, ref cpuInfo);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        NativeMethods.Kernel32.VirtualFree(_codePointer, _size, 0x8000);
    }

    // Basic ASM strategy --
    // void x86CpuId(int level, byte* buffer) 
    // {
    //    eax = level
    //    cpuid
    //    buffer[0] = eax
    //    buffer[4] = ebx
    //    buffer[8] = ecx
    //    buffer[12] = edx
    // }

    private readonly static byte[] x86CodeBytes = 
    {
    0x55,                   // push        ebp  
    0x8B, 0xEC,             // mov         ebp,esp
    0x53,                   // push        ebx  
    0x57,                   // push        edi

    0x8B, 0x45, 0x08,       // mov         eax, dword ptr [ebp+8] (move level into eax)
    0x0F, 0xA2,              // cpuid

    0x8B, 0x7D, 0x0C,       // mov         edi, dword ptr [ebp+12] (move address of buffer into edi)
    0x89, 0x07,             // mov         dword ptr [edi+0], eax  (write eax, ... to buffer)
    0x89, 0x5F, 0x04,       // mov         dword ptr [edi+4], ebx 
    0x89, 0x4F, 0x08,       // mov         dword ptr [edi+8], ecx 
    0x89, 0x57, 0x0C,       // mov         dword ptr [edi+12],edx 

    0x5F,                   // pop         edi  
    0x5B,                   // pop         ebx  
    0x8B, 0xE5,             // mov         esp,ebp  
    0x5D,                   // pop         ebp 
    0xc3                    // ret
    };

    private readonly static byte[] x64CodeBytes = 
    {
    0x53,                       // push rbx    this gets clobbered by cpuid

    // rcx is level
    // rdx is buffer.
    // Need to save buffer elsewhere, cpuid overwrites rdx
    // Put buffer in r8, use r8 to reference buffer later.

    // Save rdx (buffer addy) to r8
    0x49, 0x89, 0xd0,           // mov r8,  rdx

    // Move ecx (level) to eax to call cpuid, call cpuid
    0x89, 0xc8,                 // mov eax, ecx
    0x0F, 0xA2,                 // cpuid

    // Write eax et al to buffer
    0x41, 0x89, 0x40, 0x00,     // mov    dword ptr [r8+0],  eax
    0x41, 0x89, 0x58, 0x04,     // mov    dword ptr [r8+4],  ebx
    0x41, 0x89, 0x48, 0x08,     // mov    dword ptr [r8+8],  ecx
    0x41, 0x89, 0x50, 0x0c,     // mov    dword ptr [r8+12], edx

    0x5b,                       // pop rbx
    0xc3                        // ret
    };


}

使用方法

var asmCode = new CpuIdAssemblyCode();
CpuIdInfo info = new CpuIdInfo();
asmCode.Call(0, ref info);
asmCode.Dispose();
string ret= info.GetString();

c# - How can I get CPU name in .NET Core? - Stack Overflow

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#windows服务:C#windows服务中的Timer控件的使用发布时间:2022-07-10
下一篇:
C#ASP.NET里的@妙用,字符串换行发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap