初探 c/c++ 與 彙編 之間的交叉編譯 命令列實現

來源:互聯網
上載者:User

也不知道怎麼了,最近想搞搞這個東西,嘿嘿,,可能覺得某些方面對速度要求不高的用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,運行效果如下:

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.