如何在Visual Studio项目中正确添加汇编代码 .
引用注明>>?【作者:張佩】【鏡像:www.yiiyee.cn/blog】
?
1.??????問題描述
?
在以往的編程經(jīng)歷中,本人最常使用的匯編代碼是__asm {int 3}。它可以在我的代碼中插入一個(gè)軟件斷點(diǎn)。如果沒有一個(gè)連接到當(dāng)前程序的調(diào)試器,則程序?qū)⑼V乖谶@行語句處無法繼續(xù)執(zhí)行。
上面的這種方式稱為高級(jí)語言和匯編語言混編。當(dāng)我用得正爽的時(shí)候,迎頭碰到了64位平臺(tái)這員猛將。它大手一張,挑出一張禁令通知單:在64位編程中,高級(jí)語言和匯編混編將再也不被支持!兄弟我不禁暗暗垂淚,因?yàn)楫?dāng)我固執(zhí)而行的時(shí)候,若干惡心的編譯錯(cuò)誤赫然出現(xiàn)在我的面前:
[html]?view plaincopy
1>test.cpp(98):error C4235: nonstandard extension used : '__asm' keyword not supported on thisarchitecture
1>test.cpp(98):warning C4091: '' : ignored on left of 'int' when no variable is declared
1>test.cpp(98):error C2143: syntax error : missing ';' before 'constant'
?上面的幾行所示的并非什么驚天動(dòng)地的大錯(cuò)誤,意思非常簡單:當(dāng)前架構(gòu)不支持__asm關(guān)鍵字。
既然被踢出了體制外,我們要想生存,就必須得另謀出路。
?
?2. ? ? ?使用.asm文件
?
在64位平臺(tái)上,我們遇到了翩然而至的.asm文件。在和她共舞的過程中,下面幾個(gè)步驟必須遵守:
?
?
?
?
[cpp]?view plaincopy
FunName PROC
// 此處包含匯編指令
FunName ENDP
這里面有兩個(gè)關(guān)鍵字分別表示函數(shù)的開始和結(jié)束:PROC和ENDP。我們看一個(gè)簡單的包含中斷指令的函數(shù)應(yīng)當(dāng)怎么寫。我們假設(shè)一個(gè).asm文件中僅有一個(gè)函數(shù)實(shí)現(xiàn),下面是一個(gè).asm匯編源文件的全部內(nèi)容:
[cpp]?view plaincopy
//
// FILE: test.asm
// Description: 匯編源文件。當(dāng)前文件僅在x64平臺(tái)上編譯,并不包含于x86平臺(tái),可通過設(shè)置源文件的屬性實(shí)現(xiàn)。
//
.CODE // 文件開始
// 函數(shù)原型: void Int_3()
// 函數(shù)描述:函數(shù)實(shí)現(xiàn)中斷指令,沒有輸入/輸出參數(shù),也沒有返回值
Int_3 PROC
int 3 // 中斷指令
ret // 函數(shù)返回指令
Int_3 ENDP
END // 文件結(jié)束
這個(gè)文件名為test.asm,文件包含名為Int_3的匯編函數(shù),函數(shù)本身僅有兩行代碼:中斷指令,返回指令。
?
?3.??????X86與X64的兼容
?
現(xiàn)在澄清一下狀況:
?
?
?
?
為了讓一段包含匯編指令的代碼能夠同時(shí)在X86和X64平臺(tái)上編譯通過,我們要有辦法讓編譯器自己判斷硬件平臺(tái)。編譯器提供了名為_M_AMD64的宏,只有在X64平臺(tái)上,這個(gè)宏才是被定義的。所以我們可以用類似下面的語法進(jìn)行編程:
[cpp]?view plaincopy
#ifdef _M_AMD64
// 這是x64平臺(tái)
#else
// 這是x86平臺(tái)
#endif
實(shí)際上,大多數(shù)軟件都不使用_M_AMD64宏,而是使用在windows.h中定義的另一個(gè)表達(dá)同一含義的名為_AMD64_的宏。所以上文的另一種寫法如下:
?
[cpp]?view plaincopy
#include <windows.h>
#ifdef _AMD64_
// 這是x64平臺(tái)
#else
// 這是x86平臺(tái)
#endif
如果我們只想在程序中添加一個(gè)軟中斷指令,則完整的實(shí)現(xiàn)示例如下:
?
[cpp]?view plaincopy
#include <windows.h>
extern "C" void Int_3();
int _tmain()
{
#ifdef _AMD64_
printf("這是x64平臺(tái),使用.asm匯編文件中定義的中斷函數(shù)\n");
Int_3();
#else
printf("這是x86平臺(tái),使用__asm混編方式插入中斷指令\n");
__asm int 3;
#endif
return 0;
}
?
4.??????Visual Studio編譯
?
將.asm文件添加到項(xiàng)目中后,如果不做任何操作即直接編譯,我們會(huì)驚奇地發(fā)現(xiàn).asm文件被編譯器無視了(未被編譯)。為弄清個(gè)中緣由,請(qǐng)?jiān)?asm文件上右擊并選擇屬性,在彈出的屬性對(duì)話框中,你是否看到如下設(shè)置?
?
由于這個(gè)文件的"項(xiàng)類型"被默認(rèn)設(shè)置為“不參與生成”,所以在編譯的時(shí)候,編譯器就不會(huì)帶上它。不曉得這一點(diǎn)在新的Visual Studio里面會(huì)不會(huì)有改正。這時(shí)候各位也不要慌了手腳,Visual Studio看上去對(duì).asm這個(gè)灰頭土臉的家伙有點(diǎn)不客氣,覺得它好面生,所以有什么活動(dòng)都不愿意帶上它。沒有關(guān)系,讓我們想辦法來讓它們熟悉起來吧。
?
?
?
?
第一個(gè)選項(xiàng)“C/C++編譯器”,是用來編譯.C/.cpp文件的,如果點(diǎn)擊一個(gè).cpp文件看到的就會(huì)是它被默認(rèn)選中。但匯編文件不能使用C/C++編譯器,讀者不信可以試一試,一定有亂七八糟的編譯錯(cuò)誤秀出來。正確的做法是選擇“自定義生成工具”項(xiàng),點(diǎn)擊“應(yīng)用”后左列將出現(xiàn)名為“自定義生成工具”的子項(xiàng),如下圖所示:
在右列面板中,我們有一些設(shè)置需要添加進(jìn)去,上圖中已由紅色方框標(biāo)出。
?
?
?
?
確定并退出屬性對(duì)話框后,再次嘗試,會(huì)發(fā)現(xiàn)x86和x64平臺(tái)下的編譯都能夠成功了。我們通過上述方法,成功地在C/C++項(xiàng)目中添加匯編指令,并能夠在32/64位平臺(tái)上順利編譯通過。雖然我還沒有親自試驗(yàn),但相信相同的方法也能夠使用于.net等其他編程語言。
總結(jié)
以上是生活随笔為你收集整理的如何在Visual Studio项目中正确添加汇编代码 .的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。