<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C#嵌入x86匯編——一個GPIO接口的實現

      開始進入工業自動化,買的工控機帶有GPIO接口,可用于直接控制繼電器。

      從廠家拿到接口手冊一看,居然是匯編直接操作端口,基本上是IN/OUT指令了。接口很簡單,計算位移,讀取;計算位移,寫入。

      這種接口,常見有四種辦法,分別是四種語言實現,一是直接寫ASM,不過要公開給C#做的應用程序調用,很不容易,另外三種是C/C++/Delphi嵌入匯編,倒是問題不大。

      接口實在是小,不想大動干戈,所以想了別的辦法。

      第五種,用C++/CLI,這也是一個不錯的主意。但是我甚至想省掉這個接口DLL,于是有了第六種辦法:C#嵌入x86匯編。

       

      C#是沒辦法像C/C++/Delphi那樣直接嵌入x86匯編的,所以需要做點手腳。

      在匯編里面,我們為了修改一個軟件經常找一塊空白區域來寫匯編代碼,然后Jmp過去執行。(不明白這一句話的可以跳過,或者去看雪論壇)

      但是顯然要在C#代碼里面這么做很不現實,即使用C/C++編譯得到obj,C#也沒辦法鏈接這個obj。(這個涉及編譯的也可以跳過)

      回頭一想(其實不是現在想,07年就做過C#嵌入匯編),其實C#也跑在x86上,IL指令最終還是要編譯成x86匯編指令的,我們應該可以這些寫匯編指令,所需要的只是一塊空間而已。

      我們可以申請一塊非托管空間嘛,于是有:

      // 分配內存
      var ptr = Marshal.AllocHGlobal(code.Length);

      有了空間,我們就可以把二進制的匯編指令給寫進去啦:

      // 寫入匯編指令
      Marshal.Copy(code, 0, ptr, code.Length);

      然后呢?.Net提供一個途徑,讓我們可以把一個內存指針轉為一個委托(一直都說.Net的委托其實就是C/C++的函數指針哈):

      // 轉為委托
      return (T)(Object)Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));

       

      那么,剩下的問題,就是如何把匯編轉為二進制了!

      這個我們是不能像C/C++/Delphi那樣直接寫匯編指令的,所以得走點彎路。

      我的做法是用OD隨便打開一個程序,在上面直接寫匯編代碼,然后把匯編的十六進制復制出來,放到C#代碼中。

      剩下的就不多說了,直接上代碼吧!

       

      GPIO接口實現
      using System;
      using System.Collections.Generic;
      using System.Text;
      using System.Runtime.InteropServices;
      using System.Diagnostics;
      using System.IO;
       
      namespace ConsoleApplication19
      {
          class GPIO
          {
              #region 屬性
              private Int32 _Offset;
              /// <summary>選擇位移</summary>
              public Int32 Offset { get { return _Offset; } set { _Offset = value; } }
       
              private Int32 _Bit;
              /// <summary>選擇位</summary>
              public Int32 Bit { get { return _Bit; } set { _Bit = value; } }
              #endregion
       
              #region 構造
              private GPIO(Int32 offset, Int32 bit)
              {
                  Offset = offset;
                  Bit = bit;
              }
       
              private GPIO(Int32 gpio)
              {
                  Offset = gpio / 16;
                  Bit = gpio % 16;
              }
              #endregion
       
              #region 預定義針腳
              public static GPIO Pin2 = new GPIO(0, 6);
              public static GPIO Pin3 = new GPIO(0, 7);
              public static GPIO Pin4 = new GPIO(2, 1);
              public static GPIO Pin5 = new GPIO(2, 4);
              public static GPIO Pin6 = new GPIO(1, 0);
              public static GPIO Pin7 = new GPIO(1, 4);
              public static GPIO Pin8 = new GPIO(3, 3);
              public static GPIO Pin9 = new GPIO(3, 4);
       
              public static GPIO IO6 = new GPIO(6);
              public static GPIO IO7 = new GPIO(7);
              public static GPIO IO17 = new GPIO(17);
              public static GPIO IO20 = new GPIO(20);
              public static GPIO IO8 = new GPIO(8);
              public static GPIO IO12 = new GPIO(12);
              public static GPIO IO27 = new GPIO(27);
              public static GPIO IO28 = new GPIO(28);
              #endregion
       
              #region 業務
              /// <summary>是否啟用</summary>
              public Boolean Enable { get { return Read(Offset, Bit); } set { WriteBit(Offset, Bit, value); } }
       
              /// <summary>是否輸出</summary>
              public Boolean Output { get { return Read(Offset + 4, Bit); } set { WriteBit(Offset + 4, Bit, value); } }
       
              /// <summary>是否設置數據位</summary>
              public Boolean Data { get { return Read(Offset + 12, Bit); } set { WriteBit(Offset + 12, Bit, value); } }
              #endregion
       
              #region 讀取端口
              const Int16 BASEADDRESS = 0x500;
       
              Boolean Read(Int32 offset, Int32 bit)
              {
                  var d = ReadHandler((Int16)(BASEADDRESS + offset));
                  var c = (Byte)~(1 << bit);
                  d &= c;
                  return d == c;
              }
       
              private static ReadFunc _ReadHandler;
              /// <summary>屬性說明</summary>
              public static ReadFunc ReadHandler { get { return _ReadHandler ?? (_ReadHandler = GetReadHandler()); } }
       
              //static IntPtr ptr;
              static ReadFunc GetReadHandler()
              {
                  // 匯編指令
                  var code = new Byte[] {
                      0x66, 0x8B, 0x55, 0x08, //mov dx, word ptr [ebp+8]
                      0xEC, //in al, dx
                  };
       
                  return (ReadFunc)InjectASM<ReadFunc>(code);
              }
       
              public delegate Byte ReadFunc(Int16 address);
              #endregion
       
              #region 寫入端口
              void Write(Int32 offset, Int32 value)
              {
                  WriteHandler((Int16)(BASEADDRESS + offset), (Byte)value);
              }
       
              private static WriteFunc _WriteHandler;
              /// <summary>屬性說明</summary>
              public static WriteFunc WriteHandler { get { return _WriteHandler ?? (_WriteHandler = GetWriteHandler()); } }
       
              static WriteFunc GetWriteHandler()
              {
                  // 匯編指令
                  var code = new Byte[] {
                      0x66, 0x8B, 0x55, 0x08, //mov dx, word ptr [ebp+8]
                      0x8A, 0x45, 0x0C, //mov al, byte ptr [ebp+C]
                      0xEE  //out dx, al
                  };
       
                  return InjectASM<WriteFunc>(code);
              }
       
              public delegate void WriteFunc(Int16 address, Byte bit);
              #endregion
       
              #region 寫入端口位
              void WriteBit(Int32 offset, Int32 bit, Boolean value)
              {
                  if (value)
                      SetBitHandler((Int16)(BASEADDRESS + offset), (Byte)bit);
                  else
                      ClearBitHandler((Int16)(BASEADDRESS + offset), (Byte)bit);
              }
       
              private static WriteBitFunc _SetBitHandler;
              /// <summary>設置位</summary>
              public static WriteBitFunc SetBitHandler { get { return _SetBitHandler ?? (_SetBitHandler = GetSetBitHandler()); } }
       
              private static WriteBitFunc _ClearBitHandler;
              /// <summary>清除位</summary>
              public static WriteBitFunc ClearBitHandler { get { return _ClearBitHandler ?? (_ClearBitHandler = GetClearBitHandler()); } }
       
              static WriteBitFunc GetSetBitHandler()
              {
                  // 匯編指令
                  var code = new Byte[] {
                      0x53, //push ebx
                      0x51, //push ecx
                      0x66, 0x8B, 0x55, 0x08, //mov dx, word ptr [ebp+8]
                      0x8A, 0x45, 0x0C, //mov al, byte ptr [ebp+C]
                      0xB3, 0x01, //mov bl, 1
                      0xD2, 0xE3, //shl bl, cl
                      0xEC, //in al, dx
                      0x08, 0xD8, //or al, bl
                      0xEE, //out dx, al
                      0x59, //pop ecx
                      0x5B  //pop ebx
                  };
       
                  return InjectASM<WriteBitFunc>(code);
              }
       
              static WriteBitFunc GetClearBitHandler()
              {
                  // 讀出字節,取消指定位后重新寫回去
                  var code = new Byte[] {
                      0x53, //push ebx
                      0x51, //push ecx
                      0x66, 0x8B, 0x55, 0x08, //mov dx, word ptr [ebp+8]
                      0x8A, 0x45, 0x0C, //mov al, byte ptr [ebp+C]
                      0xB3, 0x01, //mov bl, 1
                      0xD2, 0xE3, //shl bl, cl
                      0xF6, 0xD3, //not bl
                      0xEC, //in al, dx
                      0x20, 0xD8, //and al, bl
                      0xEE, //out dx, al
                      0x59, //pop ecx
                      0x5B, //pop ebx
                  };
       
                  return InjectASM<WriteBitFunc>(code);
              }
       
              public delegate void WriteBitFunc(Int16 address, Byte bit);
              #endregion
       
              #region 注入匯編
              static T InjectASM<T>(Byte[] code)
              {
                  // 匯編指令
                  var code1 = new Byte[] {
                      0x55, //push ebp
                      0x8B, 0xEC, //mov ebp, esp
                      0x52, //push edx
                  };
                  var code2 = new Byte[] {
                      0x5A, //pop edx
                      0x8B, 0xE5, //mov esp, ebp
                      0x5D, //pop ebp
                      0xC3  //ret
                  };
       
                  //var cbs = new Byte[code1.Length + code.Length + code2.Length];
                  var ms = new MemoryStream();
                  ms.Write(code1, 0, code1.Length);
                  ms.Write(code, 0, code.Length);
                  ms.Write(code2, 0, code2.Length);
                  code = ms.ToArray();
       
                  // 分配內存
                  var ptr = Marshal.AllocHGlobal(code.Length);
                  // 寫入匯編指令
                  Marshal.Copy(code, 0, ptr, code.Length);
                  // 設為可執行
                  VirtualProtectExecute(ptr, code.Length);
       
                  Console.WriteLine("0x{0:X8}", ptr.ToInt32());
                  Console.ReadKey(true);
                   
                  // 轉為委托
                  return (T)(Object)Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
              }
              #endregion
       
              #region 輔助
              //[DllImport("kernel32.dll", SetLastError = true)]
              //static extern int VirtualQueryEx(int hProcess, ref object lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
              [DllImport("kernel32.dll", SetLastError = true)]
              static extern int VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, int flNewProtect, ref int lpflOldProtect);
              static Boolean VirtualProtectExecute(IntPtr address, Int32 size)
              {
                  const Int32 PAGE_EXECUTE_READWRITE = 0x40;
                  Int32 old = 0;
                  return VirtualProtectEx(Process.GetCurrentProcess().Handle, address, size, PAGE_EXECUTE_READWRITE, ref old) == 0;
              }
              #endregion
          }
      }

       

      image

      這里有個舊版本:http://bbs.53wb.com/forum.php?mod=viewthread&tid=137

      posted @ 2012-05-10 09:36  大石頭  閱讀(17995)  評論(64)    收藏  舉報
      主站蜘蛛池模板: 最新国内精品自在自线视频| 欧美人与动人物牲交免费观看| 92国产精品午夜福利免费| 亚洲高清国产拍精品5G| 蜜桃臀av一区二区三区| 亚洲精品国产精品国在线| 欧美人与动牲猛交A欧美精品| 国产成人综合网在线观看| 国产真实乱对白精彩久久| 丰满老熟妇好大bbbbb| 国产精品日韩专区第一页| 1精品啪国产在线观看免费牛牛| 蜜臀98精品国产免费观看| 欧美影院成年免费版| 大尺度国产一区二区视频| 国产97人人超碰caoprom| 国产成人综合在线观看不卡| 大渡口区| 九九热精品免费在线视频| 国产成人精品日本亚洲网站| 色综合久久精品亚洲国产| 天堂中文在线资源| 免费午夜无码片在线观看影院 | 久久国产热这里只有精品| 不卡一区二区三区四区视频| 性做久久久久久久久| 成人免费视频一区二区三区| 亚洲国产v高清在线观看| 亚洲精品一区二区二三区| 国产精品久久久久aaaa| 中文字幕第一页国产| 国产精品乱子乱xxxx| 国产精品黄色大片在线看| 本溪市| 亚洲精品成人片在线观看精品字幕| 麻豆国产va免费精品高清在线| 日韩乱码人妻无码中文字幕视频| 久久久无码精品亚洲日韩蜜臀浪潮| 最近最好的2019中文| 无码专区 人妻系列 在线| 亚洲AV日韩AV激情亚洲|