在针对ARM体系结构的编程中,一般很难直接使用C语言产生操作协处理器的相关代码,因此使用汇编语言来实现就成为了唯一的选择。但如果完全通过汇编代码实现,又会过于复杂、难以调试。因此,C语言内嵌汇编的方式倒是一个不错的选择。然而,使用内联汇编的一个主要问题是,内联汇编的语法格式与使用的编译器直接相关,也就是说,使用不同的C编译器内联汇编代码时,它们的写法是各不相同的。下面介绍在ARM体系结构下GCC的内联汇编。GCC内联汇编的一般格式:

asm(

代码列表
: 输出运算符列表
: 输入运算符列表
: 被更改资源列表
);

在C代码中嵌入汇编需要使用asm关键字,在asm的修饰下,代码列表、输出运算符列表、输入运算符列表和被更改的资源列表这4个部分被3个“:”分隔。下面,我们看一个例子:

void test(void)
{
……
asm(
"mov r1,#1\n"
:
:
:"r1"
);
……
}

注:换行符和制表符的使用可以使得指令列表看起来变得美观。你第一次看起来可能有点怪异,但是当C编译器编译C语句的是候,它就是按照上面(换行和制表)生成汇编的。

函数test中内嵌了一条汇编指令实现将立即数1赋值给寄存器R1的操作。由于没有任何形式的输出和输入,因此输出和输入列表的位置上什么都没有填写。但是,在汇编代码执行过程中R1寄存器会被修改,因此为了通知编译器,在被更改资源列表中,需要写上寄存器R1。

寄存器被修改这种现象发生的频率还是比较高的。例如,在调用某段汇编程序之前,寄存器R1可能已经保存了某个重要数据,当汇编指令被调用之后,R1寄存器被赋予了新的值,原来的值就会被修改,所以,需要将会被修改的寄存器放入到被更改资源列表中,这样编译器会自动帮助我们解决这个问题。也可以说,出现在被更改资源列表中的资源会在调用汇编代码一开始就首先保存起来,然后在汇编代码结束时释放出去。所以,上面的代码与如下代码从语义上来说是等价的。

void test(void)
{
……
asm(
"stmfd sp!,{r1}\n"
"mov r1,#1\n"
"ldmfd sp!,{r1}\n"
);
……
}

这段代码中的内联汇编既无输出又无输入,也没有资源被更改,只留下了汇编代码的部分。由于程序在修改R1之前已经将寄存器R1的值压入了堆栈,在使用完之后,又将R1的值从堆栈中弹出,所以,通过被更改资源列表来临时保存R1的值就没什么必要了。

在以上两段代码中,汇编指令都是独立运行的。但更多的时候,C和内联汇编之间会存在一种交互。C程序需要把某些值传递给内联汇编运算,内联汇编也会把运算结果输出给C代码。此时就可以通过将适当的值列在输入运算符列表和输出运算符列表中来实现这一要求。请看下面的例子:

void test(void)
{
int tmp=5;
asm(
"mov r4,%0\n"
:
:"r"(tmp)
:"r4"
);
}

上面的代码中有一条mov指令,该指令将%0赋值给R4。这里,符号%0代表出现在输入运算符列表和输出运算符列表中的第一个值。如果%1存在的话,那么它就代表出现在列表中的第二个值,依此类推。所以,在该段代码中,%0代表的就是“r”(tmp)这个表达式的值了。

那么这个新的表达式又该怎样解释呢?原来,在“r”(tmp)这个表达式中,tmp代表的正是C语言向内联汇编输入的变量,操作符“r”则代表tmp的值会通过某一个寄存器来传递。在GCC4中与之相类似的操作符还包括“m”、“I”,等等,其含义见下表:

ARM嵌入式开发中的GCC内联汇编简介

与输入运算符列表的应用方法一致,当C语言需要利用内联汇编输出结果时,可以使用输出运算符列表来实现,其格式应该是下面这样的。

void test(void)
{
int tmp;
asm(
"mov %0,#1\n"
:"=r"(tmp)
:
);
}

在上面的代码中,原本应出现在输入运算符列表中的运算符,现在出现在了输出运算符列表中,同时变量tmp将会存储内联汇编的输出结果。这里有一点可能已经引起大家的注意了,上面的代码中操作符r的前面多了一个“=”。这个等号被称为约束修饰符,其作用是对内联汇编的操作符进行修饰。几种修饰符的含义如下表所示:

ARM嵌入式开发中的GCC内联汇编简介

当一个操作符没有修饰符对其进行修饰时,代表这个操作符是只读的。当我们需要将内联汇编的结果输出出来,那么至少要保证该操作符是可写的。因此,“=”或者“+”也就必不可少了。

本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2012-11/74645.htm

ARM嵌入式开发中的GCC内联汇编__asm__的更多相关文章

  1. 推荐一篇讲arm架构gcc内联汇编的文章

    这是来自ethernut网站的一篇文章,原文链接: http://www.ethernut.de/en/documents/arm-inline-asm.html 另外,据说nut/os是个不错的开源 ...

  2. ARM体系下的GCC内联汇编

    转:http://andyhuzhill.github.io/arm/gcc/asm/2012/09/25/gcc-inline-assemly/ 在操作系统级的编程中,有时候,C语言并不能完全的使用 ...

  3. 最牛X的GCC 内联汇编

    导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 ...

  4. GCC内联汇编入门

    原文为GCC-Inline-Assembly-HOWTO,在google上可以找到原文,欢迎指出翻译错误. 中文版说明 由于译者水平有限,故译文出错之处,还请见谅.C语言的关键字不译,一些单词或词组( ...

  5. [翻译] GCC 内联汇编 HOWTO

    目录 GCC 内联汇编 HOWTO 原文链接与说明 1. 简介 1.1 版权许可 1.2 反馈校正 1.3 致谢 2. 概览 3. GCC 汇编语法 4. 基本内联 5. 扩展汇编 5.1 汇编程序模 ...

  6. 汇编语言---GCC内联汇编

    转:http://www.cnblogs.com/taek/archive/2012/02/05/2338838.html GCC支持在C/C++代码中嵌入汇编代码,这些代码被称作是"GCC ...

  7. GCC 内联汇编(GCC内嵌ARM汇编规则)

    转:http://smileleeboo.howbbs.com/posts/list/3127/81062.html 更多文档参见:http://pan.baidu.com/s/1eQ7nd8Q 有时 ...

  8. Linux 中 x86 的内联汇编

    工程中需要用到内联汇编,找到一篇不错的文章,趁机学习下. 原文地址:http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/ 如果 ...

  9. VC内联汇编和GCC内联汇编的语法区别

    VC: #include <stdio.h> main(){ int a = 1; int b = 2; int c; __asm{ mov eax,a mov ebx,b mov ecx ...

随机推荐

  1. JZOJ 5906. 传送门

    Description             8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normalgod扔进了一间实验室.这间实 ...

  2. python之获取微信好友列表并保存文档中

    代码如下 from wxpy import * from pprint import pprint #登录微信 bot = Bot() my_friend = bot.friends() f = op ...

  3. 笔记-scrapy-pipeline

    笔记-scrapy-pipeline 1.简介 scrapy抓取数据后,使用yield发送item对象至pipeline,pipeline顺序对item进行处理. 一般用于: 清洗,验证,检查数据: ...

  4. Spark&Hive结合起来

    1.spark与Hive结合起来 前提:当你spark的版本是1.6.1的时候,你的Hive版本要1.2.1,用别的版本会有问题 我们在做的时候,Hive的版本很简单,我们只需要解压缩,告诉他Hive ...

  5. Git-Git协同与工作协同

    Git支持的协议 首先来看看数据交换需要使用的协议. Git提供了丰富的协议支持,包括:SSH.GIT.HTTP.HTTPS.FTP.FTPS.RSYNC及前面已经看到的本地协议等.各种不同协议的UR ...

  6. 11,flask之--WTForms

    WTForms是什么? 相当于django的ModelForm. 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据 ...

  7. Spring核心技术(十五)——BeanFactory

    BeanFactory是Spring IoC功能的潜在基础,但是现在BeanFactory一般仅仅用于直接集成第三方的框架,对于大多数的Spring用户来说,BeanFactory已经算是一个历史了. ...

  8. Android onConfigurationChanged 收不到回调

    我返现,90度横屏 旋转到270度横屏onConfigurationChanged 是收不到回掉的.尽管清单里面声明了什么: android:configChanges="orientati ...

  9. 内部类inner class

    1.什么是内部类,为什么要用内部类? 可以将一个类定义在另一个类的定义内部,这就是内部类. 当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容. 如: class ...

  10. 页面引入外部字体ttf,如何提取所需要的ttf字体或者加载过慢的解决方法-1127更新

    最近几天编写手机端的页面之后,文中需要华文行楷字体,在网上下载后,引入到了自己的前端页面,以为没有什么事了,继续码代码 @font-face { font-family:huawen; src: ur ...