也不知道怎麼了,最近想搞搞這個東西,嘿嘿,,可能覺得某些方面對速度要求不高的用c/c++就可以了且很方便,可對速度要求高的用彙編來實現也是個不錯的選擇。。而通常情況下,這兩條都希望有,所以想到了交叉編譯,當然寫成DLL形式再介面調用也未嘗不可,只是有時希望整合一下,嘿嘿。。。。羅嗦了吧,哈哈,下面開始吧。
說明:
1.呼叫慣例
統一採用_stdcall方式壓棧,通常用於Win32 Api中,函數採用從右至左的壓棧方式,
自己在退出時清空堆棧。VC將函數編譯後會在函數名前面加上底線首碼,在函數名後加上"@"和參數的位元組數。
比如:int f(void *p) 編譯後為 _f@4(在外部組合語言裡可以用這個名字引用這個函數)
2.名字修飾約定
C或者C++函數在內部(編譯和連結)通過修飾名識別。修飾名是編譯器在編譯函數定義或者原型時產生的字串。
修飾名由函數名、類名、呼叫慣例、傳回型別、參數等共同決定。
a、C編譯時間函數名修飾約定規則:
__stdcall呼叫慣例決定了在輸出函數名前加上一個底線首碼,後面加上一個“@”符號和其參數的位元組數,
格式為_functionname@number。
b、C++編譯時間函數名修飾約定規則:
通過extern "C"強制採用C編譯時間的函數名修飾約定規則a。
3. 以下程式均以上面兩條約定方式、windows vc6.0包 環境實現,其他方式也未嘗不可,只是這種方式用的多一點吧。。
C/C++調用彙編函數
也不想多說什麼,給個具體的例子吧
我們要通過C/C++來調用下面的彙編函數GetArgument PROC a:DWORD
.386
.model flat,stdcall
option casemap :none
.code
GetArgument PROC a:DWORD
mov eax, a
ret
GetArgument ENDP
end
將其儲存為myasm.asm檔案。寫個批處理將其編譯成目標檔案:
@echo off
set include=e:/masm32/include
set lib=e:/masm32/lib
set path=e:/masm32/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
ml /c /coff myasm.asm
pause
儲存為myasm.bat雙擊得到myasm.obj檔案。
接下來,通過C或C++來調用這個彙編函數。下面是C或C++的統一寫法:
#include <stdio.h>
#ifdef __cplusplus
#include <windows.h>
extern "C" {
#endif
int _stdcall GetArgument(int);
#ifdef __cplusplus
}
#endif
int main()
{
printf("Good luck!! C_Call_Asm Succeed return %d/n",GetArgument(10));
system("PAUSE");
return 0;
}
儲存為myc.c或myc.cpp即可
再寫個批處理交叉編譯myc.c和myasm.obj得到可執行檔:
@echo off
set include=D:/vcPack/include;D:/vcPack/MFC/Include
set lib=D:/vcPack/lib;D:/vcPack/MFC/lib
set path=D:/vcPack/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
cl /c myc.c
link /subsystem:console myc.obj myasm.obj
pause
myc.exe
pause
儲存bat檔案雙擊即可,運行效果如下:
彙編調用C/C++函數
我們要通過彙編來調用C/C++函數int GetArgument(int a) 採用前面的兩條約定方式,下面是C/C++的統一寫法:
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
int __stdcall GetArgument(int a)
{
printf("Good luck!! Asm_Call_C Succeed return %d/n",a);
return 0;
}
#ifdef __cplusplus
}
#endif
儲存為myc.c或myc.cpp即可
下面寫個批處理來編譯這個myc.cpp檔案
@echo off
set include=D:/vcPack/include;D:/vcPack/MFC/Include
set lib=D:/vcPack/lib;D:/vcPack/MFC/lib
set path=D:/vcPack/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
cl /c myc.cpp
pause
儲存為myc.bat 雙擊執行得到myc.obj檔案。
接著寫彙編啦,嘿嘿
.386
.model flat,stdcall
option casemap:none
GetArgument proto :dword ;函數申明
.code
start:
invoke GetArgument,10 ;函數調用
xor eax,eax
ret
end start
儲存為myasm.asm檔案
再寫個批處理來編譯上面的myc.obj和myasm.asm,產生可執行檔:
@echo off
set include=e:/masm32/include
set lib=e:/masm32/lib
set path=e:/masm32/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
ml /c /coff myasm.asm
link /subsystem:console myasm.obj myc.obj msvcrt.lib
pause
myasm.exe
pause
儲存bat檔案雙擊即可,需要說一下的是,由於原c中用到了printf函數,所以在連結時要包含庫檔案msvcrt.lib,運行效果如下: