zoukankan      html  css  js  c++  java
  • VS2005混合编译ARM汇编代码-转

    原文地址:http://blog.csdn.net/annelcf/article/details/5468093

    公司HW team有人希望可以给他们写一个在WinCE上,单独读写DDR的工具,以方便他们量测Memory读写时的硬件信号。

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

     

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

     

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

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

     

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

     

    具体方法:

    一. 创建编译规则

    <?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>

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

     

    二. 在VS2005中添加编译规则

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

     

    三. 编写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);
    }

  • 相关阅读:
    TCP系列24—重传—14、F-RTO虚假重传探测
    TCP系列23—重传—13、RACK重传
    TCP系列22—重传—12、Forward Retransmit
    TCP系列21—重传—11、TLP
    TCP系列20—重传—10、早期重传(ER)
    TCP系列19—重传—9、thin stream下的重传
    TCP系列18—重传—8、FACK及SACK reneging下的重传
    TCP系列17—重传—7、SACK下的重传
    TCP系列16—重传—6、基础快速重传(Fast Retransmit)
    Centos 6.2 安装mysql5.5
  • 原文地址:https://www.cnblogs.com/xunbu7/p/3866405.html
Copyright © 2011-2022 走看看