初探 c/c++ 与 汇编 之间的交叉编译 命令行实现

也不知道怎么了,最近想搞搞这个东西,嘿嘿,,可能觉得某些方面对速度要求不高的用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++ 与 汇编 之间的交叉编译 命令行实现_第1张图片

 

汇编调用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,运行效果如下:

初探 c/c++ 与 汇编 之间的交叉编译 命令行实现_第2张图片

 

 

你可能感兴趣的:(初探 c/c++ 与 汇编 之间的交叉编译 命令行实现)