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:
完蛋了!想辦法咯~
上網求解方案,說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 bmpWidth, int bmpHeight, unsigned char *videoRef, unsigned char*YUVData);
extern "C" int __stdcall RGB2YUV_BLOCK(int bmpWidth, int bmpHeight, unsigned char *videoRef, unsigned char*YUVData, int 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;
}
這其中的過程,還有很多需要解決的問題和思考的地方,這需要你的基本功了,就不在這裡都說出來了,做一做就都知道了!相信自己!