加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转载]__asm__ volatile 之 C语言嵌入式汇编

(2012-10-10 22:58:33)
标签:

c语言

杂谈

分类: 软件编程

原文地址:__asm__ volatile 之 C语言嵌入式汇编

 

在linux/include/unistd.h中定义的系统调用嵌入汇编宏函数_syscall0。

其实展开不难发现就是一个函数,只不过用宏定义了。其中关键的是怎么理解 __asm__ volatile这个语法。对于__asm__ volatile这个固定形式,我们暂且不理会它(可参考http://blog.csdn.net/robbie1314/archive/2011/04/17/6329880.aspx),关键看懂()里面的含义。

以下面这个为例子先简要介绍一下这个用法。

插入C语言的一个汇编语言代码片段可以分成4部分,以“:”号加以分隔,其一般形式为:

指令部:输出部:输入部:损坏部

static __inline__ void atomic_add(int i, atomic_t *v)

{

__asm_volatile__(

LOCK "addl %1, %0"

: "=m" (v->counter)

: "ir" (i), "m" (v->counter));

}

当汇编语言代码嵌入到C代码时,解决操作数和C代码中的变量结合是一个问题。我们无法确切知道gcc在嵌入点的前后会把哪个寄存器分配给哪个变量等,所以gcc采用一种方法:程序员只提供具体的指令,而对寄存器的使用则一般只提供一个“样板”和一些约束条件,而到底如何把变量和操作数结合的问题留给gcc和gas去处理。

指令部

数字加上前缀%,如%1、%0等,表示需要使用寄存器的样板操作数。可以使用的此类操作数的总数取决于具体CPU中通用寄存器的数量。

输出部

规定对输出变量,即目标操作数如何结合的约束条件。每个这样的条件称为一个“约束条件”。必要时输出部可以有多个约束条件,互相以逗号分隔。每个输出约束以“=”号开头,然后是一个字母表示对操作数类型的说明,然后是关于变量结合的约束。例子中:

: “=m” (v->counter)

这里只有一个约束条件,“=m”表示相应的目标操作数(指令中的%0)是一个内存单元v->counter。

输入部

输入部约束的格式和输出约束相似,但不带“=”号。例子中:

第1个为"ir" (i),表示指令中的%1可以是一个在寄存器中的“直接操作数”(i表示immediate),并且该操作数来自于C代码中的变量名(这里是调用参数)i。

第2个约束条件“m” (v->counter)意义与输入约束相同。

损坏部

有些操作中,除了用于输入操作数和输出操作数的寄存器外,还要将若干个寄存器用于计算或者操作的中间结果。这样,这些寄存器原有的内容就损坏了,所以要在损坏部对操作的副作用加以说明,让gcc采取相应的措施。不过,有的时候就直接把这些说明放在输出部了,那也并无不可。

操作数的编号从输出部的第一个约束(序号为0)开始,顺序数下来,每个约束计数加1次。在指令部中引用这些操作数或分配用于这些操作数的寄存器时,就在序号前面加上%号。

表示约束条件的字母有很多,主要有:

"m"、"v"和"o" ---- 表示内存单元

"r" ---- 表示任何寄存器

"q" ---- 表示寄存器eax,ebx,ecx,edx之一

"i"和"h" ---- 表示直接操作数

"E"和"F" ---- 表示浮点数

"g" ---- 表示任意

"a","b", "c" "d" ---- 分别表示要使用寄存器eax ebx ecx和edx

"S"和"D" ---- 分别表示要使用寄存器esi和edi

"I" ---- 表示常数(0至31)

回到上面的例子,这段代码的作用是将参数i的值加到v->counter上。代码的关键字LOCK表示在执行addl指令时要把系统总线锁住,不让别的CPU打扰,以保证原子性操作。

下面就可以照着上面的说明把下面代码看懂吧。

代码:


#define _syscall0(type, name)/
type name(void)/
{/
long __res;/
__asm__ volatile ("int $0x80" /
: "=a" (__res) /
: "" (__NR_##name));/
if (__res >= 0)/
{/
return (type)__res;/
}/
errno = -__res;/
return -1;/
}


#define _syscall1(type, name, atype, a) /
type name(atype a)/
{/
long __res;/
__asm__ volatile ("int $0x80"/
: "=a" (_res)/
: "" (__NR_#name), "b" ((long)(a)));/
if (__res >= 0)/
{/
return (type)__res;/
}/
errno = -__res;/
return -1;/
}


#define _syscall2(type, name, atype, a, btype, b)/
type name(atype a, btype b)/
{/
long __res;/
__asm__ volatile ("int $0x80"/
: "=a" (__res)/
: "" (__NR_##name), "b" ((long)(a)), "c" ((long)(b)));/
if (__res >= 0)/
{/
return (type)__res;/
}/
errno = -__res;/
return -1/
}


#define _syscall3(type, name, atype, a, btype, b, ctype, c) /
type name(atype a, btype b, ctype c)/
{/
long __res;/
__asm__ volatile ("int $0x80"/
: "=a" (__res) /
: "" (__NR_##name), "b" ((long)(a)), /
"c" ((long)(b)), "d" ((long)(c)));/
if (__res >= 0)/
{/
return (type)__res;/
}/
errno = -__res;/
return -1;/
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有