VS2005混合编译ARM汇编代码

在开发过程当中,发现简单的在Storage Memory区域拷贝或粘贴文件不能达到硬件量测的要求,须要直接经过编写ARM汇编指令让CPU直接对Memory进行读写数据。

之前没有用VS2005编写过汇编代码,因此走了点弯路,一直试图用内嵌汇编的方式来build,可恨的VS2005死活不认ARM指令,后来请出 google大神一搜,原来这条路已经有不少先行者试过了,结论是VS2005不能用内嵌汇编的方式build ARM汇编代码!windows

俗话说的好啊,机器是死的,人是活的!函数

google大神给我指出了一条通向光明的道路: VS2005中是能够对纯粹的arm汇编文件进行编译的,固然也能够将C编译生成的obj文件和asm汇编文件生成的obj文件进行link。ui

这种混合编译的方法,网上流传最广的一份代码出自一位叫Larry Bank的老外。this

具体方法:google

一. 建立编译规则code

<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile Name="Arm ASM" Version="8.00">
   <Rules>
      <CustomBuildRule
         Name="Arm asm" DisplayName="Arm asm"
         CommandLine="armasm -o &quot;$(IntDir)\$(InputName).obj&quot; [$Inputs] "
         Outputs="$(IntDir)\$(InputName).obj"
         FileExtensions="*.asm"
         ExecutionDescription="Executing tool..."
      >
      <Properties></Properties>
      </CustomBuildRule>
   </Rules>
</VisualStudioToolFile>orm

将上面的代码复制到记事本中,并将其保存到vs2005安装目录的Microsoft Visual Studio 8\VC\VCProjectDefaults文件夹下,命名为armcc.rulesxml

二. 在VS2005中添加编译规则ip

选择须要和ARM汇编代码作混合编译的Project,右键弹出的菜单中选择"Custom Build Rules...”,在弹出的对话框中点"Find Existing..."按钮,选择armcc.rules文件utf-8

三. 编写ARM汇编代码,并将其加入VS2005的Project中(以Larry Bank的code为例)

ARM汇编代码,文件命名为armtest.asm:

;      TITLE("Sample App")
;++
        AREA sample, CODE, READONLY ; name this block of code
       
   EXPORT TEST
IMPORT iGlobal
;
; Called from C as int ARMTEST1(int, int, int, int);
; The first 4 parameters are passed in r0-r3, more parameters would be passed on the stack
;
TEST proc
    add r0,r0,r1     ; add all of the inputs together
    add r0,r0,r2
    add r0,r0,r3
    ldr r1,=iGlobal ; get the value of our global variable
    ldr r1,[r1]   ; dereference the pointer (I know there's a pipe stall here)
    add r0,r0,r1 ; we're not concerned with performance in this example
    mov pc,lr     ; return to C with the value in R0   
    endp

    LTORG      ; allow room for the address constant of our global (loaded relative to PC)
    END

将armtest.asm加入VS2005的Project中,编写调用代码:

// Windows CE Sample Application

// File Name: MAIN.C
// Demonstrations how to use ARM assembly language within a C program
// Written by Larry Bank 3/25/2007

#include <windows.h>

int iGlobal;

int TEST(int, int, int , int);

/****************************************************************************
*                                                                          *
* FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
*                                                                          *
* PURPOSE    : Program entrypoint                                         *
*                                                                          *
****************************************************************************/
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
int iResult;
TCHAR szTemp[256];

   iGlobal = 5;
   iResult = TEST(1,2,3,4);
   wsprintf(szTemp, L"Result = %d", iResult);
   MessageBox(HWND_DESKTOP, szTemp, L"ASM Result", MB_OK);
      
   return 0;

} /* WinMain() */

四. Build VS2005的Project,当你看到以下信息时,恭喜你~~~你成功了!

========= Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

到这里,可能你们以为结束了,呵呵,其实才是作了一半!

仔细的朋友可能也发现了,Larry Bank调用armtest.asm中函数的文件MAIN.C在VS2005编译时调用的是C编译器,可是如今不少项目工程会以C++代码编写(*.cpp),在VS2005中会用C++编译器Compile。

若是不注意这点的话,就会出现下面的结果:

error LNK2001: unresolved external symbol iGlobal
error LNK2019: unresolved external symbol "int __cdecl TEST1(int,int,int,int)" (?TEST1@@YAHHHHH@Z) referenced in function wmain
fatal error LNK1120: 2 unresolved externals

出现这个问题缘由是:

汇编源文件再编译之后,函数名称以及变量名称没有作任何的更改,而C++源码在通过C++编译器编译之后,函数名称和变量名称都已经有过变化(可查看编译后的object文件),因此链接的时候会报错。

解决的办法有下列几种:

方法一

将汇编中的函数名称和变量名称都更改成C++编译器编译过的函数名称和变量名称,即?TEST1@@YAHHHHH@Z?iGlobal@@3HA。注意这种方式在名称前面要加上“|”符号。

;      TITLE("Sample App")
;++
        AREA armtest, CODE, READONLY ; name this block of code

    IMPORT |?iGlobal@@3HA|
    EXPORT |?TEST1@@YAHHHHH@Z|
;
; Called from C as int ARMTEST1(int, int, int, int);
; The first 4 parameters are passed in r0-r3, more parameters would be passed on the stack
;
|?TEST1@@YAHHHHH@Z| proc
    add r0,r0,r1     ; add all of the inputs together
    add r0,r0,r2
    add r0,r0,r3
    ldr r1,=iGlobal;|?iGlobal@@3HA| ; get the value of our global variable
    ldr r1,[r1]   ; dereference the pointer (I know there's a pipe stall here)
    add r0,r0,r1 ; we're not concerned with performance in this example
    mov pc,lr     ; return to C with the value in R0   
    endp

    LTORG      ; allow room for the address constant of our global (loaded relative to PC)
    END

方法二

在C++源程序中声明变量和函数的时候用extern "C"修饰,直接告诉编译器这是C函数。

extern "C"
{

     int iGlobal;      int TEST1(int, int, int , int); }

相关文章
相关标签/搜索