Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1262591
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类: LINUX

2011-02-20 19:36:23

arm gcc内嵌汇编

=============================

高级语言可以实现大部分编程功能,但是当我们需要对特定代码进行优化,写启动代码,或者操作特定硬件,或需要直接用CPU指令等等操作的时候我们需要用到汇编。但是我们只想在高级语言(比如C语言)中的某些特定部分插入某些汇编指令,这时候,我们就需要用高级语言提供的内嵌汇编功能。我们以arm gcc为例,用arm gcc进行c语言和汇编语言混合编程。

最简单的内嵌汇编:

	#include 

	int main( int argc, char ** argv )
	{
	        asm("nop");
	}

上面就一条内嵌汇编指令:asm("nop");nop指令在汇编上表示执行空操作,消耗一个CPU指令周期。(实际上nop是一条伪指令,会被编译起翻译成: mov r0, r0这条真实cpu指令)


内嵌汇编的通用形式:

	asm (
			代码
			: 输出操作数列表
			: 输入操作数列表
			: 破坏列表
	);

在一个asm语句中可以写一条或者多条汇编代码,一条汇编代码结束采用\n进行换行,有时候,为了美观也采用\n\t进行换行。C语言通过变量的形式访问数据,而汇编语言是通过内存地址或者直接访问寄存器的方式访问数据,如果要在内嵌汇编中访问C语言中的变量,并且修改它的值的话,那么就需要用一种方式用于相互转换C语言的变量与内嵌汇编能访问的寄存器或内存地址形式。这种方式就是通过输入操作数列表和输出操作数列表实现的。

输入和输出操作数列表的格式是一样的,都是由一个或者多个操作数组成,中间采用逗号进行分开,单个操作的格式如下:

	[C变量在汇编中的访问名称] "限制性字符“ (C传递进来的变量名称)


例如,下面程序是实现从C语言中传递2个变量a,b进入汇编中,然后在汇编中实现a+b,把结果存回变量C中:

#include 

int main( int argc, char ** argv )
{
        int a = 20, b = 30;
        int c;

        asm (
                "add %[cc], %[aa], %[bb]"
                : [cc] "=r" (c)
                : [aa] "r" (a), [bb] "r" (b)
					: "memory"
		   );

        printf("c = %d\n", c );
        return 0;
}
~       
上面代码没有破坏列表,可以省略不写。上面汇编中,输入了C语言中的变量a和b,执行结果输出到变量c中,在汇编中访问C语言中的变量a,b,c通过%[aa],%[bb],%[cc]进行访问的。当传递常量,指针,或者变量到内嵌汇编中,内嵌汇编必须知道如何在汇编代码中表示他们,这个就是由中间“限制性字符”来指定。

常用限制性字符:

	I: 立即数			例如: [changliang] "I" (120), 表示把120作为立即数的方式传递进去。
	m: 任何有效内存	例如: [nc] "m" (a) , 表示把变量a的地址传递到内嵌汇编中,str r0, %[nc], 就表示把r0的值存入变量a。
	r: 通常的寄存器(r0-r15)。最常用。

上面这些限制性字符如果不带修饰符的话,表示是只读操作数,只能用于输入操作数列表中。对于输出操作数列表中的操作数我们需要加上相应的写权限。常用修饰符包括如下:

	= 只写操作数,通常用于所有的输出操作数。
	+ 读写操作。
	& 只用作输出的寄存器。(表示不能与输入寄存器用同样一个寄存器)


破坏列表:

	一般就是一个“memory",或者寄存器列表。如果在汇编代码中修改了内存中的值,我们就需要在破坏列表中加上"memory"字段,表示告诉编译器,要把缓存中的值写入内存,并且在执行之后重新加载内存。如果在汇编代码中修改了某些寄存器,那么我们就需要把在代码中所修改过的寄存器列在破坏列表中。

	
防止编译器优化:

	为了不让编译器优化我们的代码,比如,本来我们想在汇编中采用nop指令进行延时,然后,通常情况下编译起会把nop当成一条无用指令而优化掉它,为了防止编译器优化,我们需要在asm语句符号后面加上__volatile__,这样就可以防止编译器优化我们的汇编代码。

	asm __volatile__ ();













~                                                                                                                                           
~         
阅读(760) | 评论(0) | 转发(0) |
0

上一篇:ATPCS

下一篇:各种情况下的编译

给主人留下些什么吧!~~