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 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;
}
這其中的過程,還有很多需要解決的問題和思考的地方,這需要你的基本功了,就不在這里都說出來了,做一做就都知道了!相信自己!
jpg改rar