1. 程式人生 > >x86平臺轉x64平臺關於內聯彙編不再支援的解決

x86平臺轉x64平臺關於內聯彙編不再支援的解決

2011/08/25   把自己碰到的問題以及解決方法給記錄下來,留著備用!

 

工具:VS2005  編譯器:cl.exe(X86 C/C++)  ml64.exe(X64 ASM64)

前提:X86下內聯彙編是嵌在函式當中實現的

 

在X86平臺下,可以輕鬆的在C/C++程式碼中嵌入彙編程式碼,稱其為“內聯彙編”,使用”__asm{}”語法即可,比較簡單,這裡不做介紹。當你在X86平臺下,由於效能和速度的要求,需要在C/C++程式碼中內聯彙編。而當你好不容易在X86平臺下實現了這些以後,發現要轉到X64平臺下面,怎麼辦(不是說在X64下執行X86的程式,因為這是肯定可以的,而是說從X86工程轉到X64工程)?可以相容的吧?先試試再說嘛。

 

試一試:


 

看到上圖的Debug和Win32字眼麼,就從這裡開始改。

 

 

下拉Win32右端的下三角,呈現出如上圖。由於我已經設定好了,會有x64字眼。如果以前沒有設定,那麼預設是沒有x64字樣的。要出現x64平臺,請設定:點選“配置管理器”,一系列操作見圖知意:

 
 

注意:一般情況下,是在X86平臺下程式設計,至少我是這樣的。那麼裝VS2005的時候預設是不支援在X86平臺下編譯連線生成X64平臺的EXE的。如果真的要在X86下編譯連線生成X64平臺的EXE,比如和我一樣。那麼找到您安裝VS2005時候的SETUP.EXE,雙擊它,選擇“新增或者刪除”選項(名字不確定,但是是第一項),然後勾選住有X64字眼的那一項(具體我也不記得了),然後等SETUP.EXE幫你裝上這一項就好了。接下來看圖~

 

 

 

 

 

 

 

 

 

 

 

注意:當你第一次“新建”的時候,在“新建平臺(P)”下會出現“X64”選項,這裡沒有出現,因為我之前已經都設定好了。

 

 


 

 

 

 

都說了試一試了,結果上面才弄好了環境設定。下面編譯連線(F7),啊哦!出錯了,而且一大堆錯誤提示!媽呀!!!

 

經典的一句報錯是:

error C4235:

 使用了非標準擴充套件: 不支援在此結構上使用“__asm”關鍵字

 

完蛋了!想辦法咯~

上網求解方案,說VS2005 X64平臺下不再支援內聯彙編了!但是考慮到時間,又不允許換編譯器,怎麼辦?繼續上網搜尋解決方法。。。有了。單獨寫彙編ASM檔案,編譯生成.OBJ檔案。也就是說不能在C/C++程式碼中直接內嵌(內聯)彙編了,而要把原先內聯的彙編全都放在一個獨立的彙編檔案中。換句話說,一部分彙編程式碼,一部分C/C++程式碼。然後將獨立彙編編譯生成的.OBJ檔案附加到C/C++主工程之中。。。好像好難哦,沒事,萬事開頭難嘛~

好的,不懂的話先往下看了!

下面還有一些頭大的操作那

記住,我是在X86平臺下編譯連線X64平臺下的程式哦!主工程是在X64平臺下執行的程式。上面說的兩部分:彙編和C/C++當然是X64平臺下的(肯定的嘛)。

64位彙編,傻眼了,32位都頭大,一下子跳到64位,有沒有搞錯??沒有,32位彙編程式碼應該是不用做太大的改動的。事實上證明,確實是這樣的哦~

首先,不是把原先的內聯彙編程式碼改成單獨的彙編檔案。問題是寫好了64位彙編,怎麼編譯單獨的彙編檔案?用VS2005整合環境去編譯單獨的彙編檔案,對,就是這樣,不要再回到DOS介面敲命令行了,這會死人的,而且不方便!!接下來跟著我做:

用VS2005建立一個常規的空專案。然後將自己改好的64位彙編(說白了,大部分還是32位的指令)加入該工程中,F7編譯連線好像有反應,但是是假象!預設的話IDE不認識彙編。怎麼辦?

 

 

  

  

點選“自定義生成規則”:

 

 
 

 

預設只有前兩項,最後一項是我自己新增的。第一項,我不知道什麼東西。第二項是32彙編的編譯器(ml.exe)。但是我們是要編譯64位彙編啊!不急,按著下面做:

找到這個路徑“…\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults”,OK,在這個目錄下,找到masm.rules。接下來,複製貼上masm.rules,改複製檔名字為“masm64.rules”。

回到IDE,上面就有了三項了。對最後一項進行修改,明顯的,不然後兩項是一樣的。勾選第三項,點選“修改規則檔案”:

 

 

 
 

 點選“修改生成規則”:

 

改成藍色選中的文字就行了,就是簡單的加了“64”在原先ml後面,你懂的~一路確定,萬事搞定!如果64位彙編檔案沒有語法錯誤,就會生成.OBJ檔案了,哈哈!沒有這麼簡單的啦。。。主要是編寫符合要求的64位彙編程式碼,而不是以前簡單的內聯在C/C++程式碼中。關於編寫單獨彙編程式碼檔案,靠你原先的彙編基礎了,這個我沒話說了,靠你們自己了!!

OK,“搞定了”,F7如下提示:

 

1>------ 已啟動生成: 專案: ASM64, 配置: Debug x64 ------

1>正在連結...

1>LINK : fatal error LNK1561: 必須定義入口點

1>生成日誌儲存在“file://f:\VC Projects\Visual Studio 2005 Projects\happyway\test\ASM64\ASM64\x64\Debug\BuildLog.htm”

1>ASM64 - 1 個錯誤,個警告

========== 生成: 0 已成功, 1 已失敗, 0 最新, 0 已跳過==========

 

 

 

我沒有去深究入口點,因為我不需要這個,入口點在C/C++主工程那,彙編搞定,語法上!得到了編譯生成的asm64.obj。

接下來,是另一部分,C/C++主工程程式碼了,停筆,和田大頭吃飯去~

……

我X,田大頭放我鴿子,一個人吃飯!

 

注意,X86下內聯彙編是嵌在函式當中實現的,所以上面的64位彙編的任務就是編寫函式過程(PROC)。

接下來,回到主工程。在主工程中要用到彙編中的函式,那麼彙編生成的.OBJ檔案就派上用場了。主工程可以呼叫.OBJ去使用匯編中的函式。過程如下:

“專案”->“屬性”,彈出:

然後“配置屬性”->”連結器”->“輸入”,,右側的“附加依賴項”中,填入彙編檔案生成的.OBJ,如下圖。


 

 

然後暴露出彙編中編寫好的函式的介面。

我是這樣暴露我的彙編函式的:

extern "C" int __stdcall  RGB2YUV_ALL(int bmpWidthint bmpHeightunsigned char *videoRefunsigned char*YUVData);

extern "C" int __stdcall  RGB2YUV_BLOCK(int bmpWidthint bmpHeightunsigned char *videoRefunsigned char*YUVDataint LargebmpWidth);

如果一切順利的話,主工程就可以使用上面的函式,編譯連線都沒有問題,但是萬惡的執行時有錯,那就得靠你的除錯了!至此,差不多,從X86到X64,從內聯彙編到單獨的彙編檔案,解決了X64下不支援內聯彙編的問題啦,嘻嘻。

但是,更加辛苦和耗時的是彙編程式碼的修改和編寫、C/C++調用匯編函式過程遇到的種種問題,但是隻要努力再加上有一定基礎的情況下是搞得定許多問題的!

如果你感興趣,或者就是和我一樣碰到這樣的問題,下面給出例項程式碼。

1. ASM檔案

.data

;資料段


.code
 FUNC proc 
 MOV EAX, 1234
 RET 
 FUNC endp
end

 

2.測試VS2005控制檯工程

#include <stdio.h>

extern "C" int __stdcall  FUNC();

 

int main(int argc, WCHAR* argv[])

{

 

    int nret = FUNC();

    printf(“%d\n”, nret);

    system("pause");  

    return 0;

}

 

這其中的過程,還有很多需要解決的問題和思考的地方,這需要你的基本功了,就不在這裡都說出來了,做一做就都知道了!相信自己!