天天看點

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彙編指令的,我們應該可以這些寫彙編指令,所需要的隻是一塊空間而已。

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

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

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

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

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

我的做法是用OD随便打開一個程式,在上面直接寫彙編代碼,然後把彙編的十六進制複制出來,放到C#代碼中。

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

C#嵌入x86彙編——一個GPIO接口的實作
C#嵌入x86彙編——一個GPIO接口的實作

GPIO接口實作

C#嵌入x86彙編——一個GPIO接口的實作

我不相信神話,我隻相信汗水!我不相信命運,我隻相信雙手!