您的位置:首页 > 编程语言

转:VS2005混合编译ARM汇编代码

2012-03-08 13:19 274 查看
转:VS2005混合编译ARM汇编代码

在开发过程中,发现简单的在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 "$(IntDir)\$(InputName).obj" [$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);

}

转载地址:http://my.oschina.net/tonyyang/blog/15031s
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: