這是一個老生常談的問題,但是我昨天又遇到了。敝人不才,實在想象不出C#裡怎麼能在直接寫彙編,直接操作寄存器,直接調用系統中斷。。。。。。我回答:由於。net是虛擬了沒有CPU的虛擬機器,所以不能直接操作寄存器,所以也就不能直接nested彙編。我理解的嵌入就應該是C裡的asm(C++裡的_asm)
首先看看什麼樣才是嵌入,查了一下詞典,是鑲入,好了,不picky了,直接進入正題。
查了一下園子,有如下一些可參考的文章:
《C#內嵌彙編代碼的討論》
《在.net程式中嵌入asm彙編代碼》
《C#調用彙編dll (載)》
《一個C#內聯彙編的類 》
諸如此類的,他們的方案大概分為兩類:
1.將彙編寫在native code的 dll裡,然後通過DllImport來調用
2.利用DllImport Windows API,再將彙編碼注入調用。
上面的方法看似不同,其實實質相同,都是Managed 程式碼對非託管的調用。而且這兩種方法都不能叫做嵌入,只能叫做調用而已。第二種方法有些“奇技淫巧”的意味。而且兩種方法有個巨大的弊端:均不能實現連調。還有離直接書寫彙編相聚深遠。
在上面的《在.net程式中嵌入asm彙編代碼》 文中的後面的評論中,敝人已經給這個問題發表了評論。
可是不幸的是,大家沒有看到,而且本人昨天還被人恥笑了一番。遂有了此文
寫個簡單的:實現從一個數begin到end的累加,只是demo。
建立一個C++的CLR類庫 |
inline int SumASM(int begin, int end) { _asm { xor eax, eax //eax清零 mov ecx, end //迴圈計數放入ecx,不解釋 } lable: _asm { cmp ecx,begin //查看ecx是否到達下限begin jl exit //如果小於begin則跳出 add eax,ecx //開始累加 loop lable //ecx迴圈,每次會自減1 } exit:; } |
然後建立一個class,用作C++/CLI的wrapper |
.h
using namespace System; namespace CPPWrapper { public ref class Class1 { // TODO: Add your methods for this class here. public: static int Sum(int begin,int end); }; } .cpp int CPPWrapper::Class1::Sum(int begin, int end) { return SumASM(begin, end); } PS: SumASM 如果放在同一個cpp裡,要放在Sum方法的前面,這個也不解釋。 |
下面各建一個C++/CLI和C# 的Console application,用作caller。 記得同樣得添加引用using namespace System; using namespace CPPWrapper; int main(array<System::String ^> ^args) { int a=Class1::Sum(1,100); return 0; } C#的我不寫了。 用C++/CLI,這樣就可以實現連調了。從Managed 程式碼到非託管調試。 |