在linux源代码中会有一部分c语言与汇编语言相交融的部分。
其中linux中汇编语言采用的不是我们通用的intel的汇编语言,而是采用的是AT&T格式的汇
编语言,它们之间有一些差别:
1 目标与源的方向不大一样
mov ax, bx mov %bx, %ax
2 AT&T寄存器前要加入%
ax %ax
3 AT&T立即数前面要加上$
add ax, 4 add %ax,$4
4 对于访问指令的操作数大小
intel的格式是在操作数前加上BYTE PTR、DWORD PTR等等
AT&T格式:在操作数后面加上b、l、w等
MOV AL, BYTE PTR FOO(intel)
movb FOO, %al (AT&T)
5 间接寻址:
SECTION:[BASE+INDEX*SCALE+DISP]
Section:disp(base, index, scale)
C语言中插入汇编代码比纯粹的汇编要难,因为要设计到“如何分配使用寄存器、怎样与C语
言中变量相结合”
下面“=”代表只读,“+”代表读写
每个输出部分均以=开始
比如我想定义一个char型的变量,放入ax中
register char _temp asm ("ax");
register char _temp __asm__ ("ax");
以上两种方式均正确
在这里我们通常看到普通的寄存器前面有两个%,代表下面的意思:第一寄存器前要有一个%
第二对于一个模板前要加入一个%
下面以一个在内核中常见的目的为了实现原子操作的一个函数为例子atomic_add来介绍
static __inline__ void atomic_add(int i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "addl %1, %0"
:"=m"(v->counter)
:"ir"(i), "m"(v->counter)
);
}
ir代表一个寄存器中的直接操作数
首先一个头部:__asm__ __volatile__(); asm(); __asm__();告诉编译器里面是汇编语言
:第一个冒号是输出部分:第二个冒号是输入部分
其实还有第三个冒号:代表着损坏部分
asm("汇编语句" :输出部分 :输入部分 :损坏部分)
%0、%1 等等代表着一种模板操作数,其中数字到几取决于cpu寄存器数量
"m", "v", "o" --内存单元 "r" 任意寄存器
"q" 表示eax、ebx、ecx、edx之一
"i", "h" 表示立即数
"a", "b", "c", "d"表示eax、ebx、ecx、edx
关键字LOCK表示在执行的时候把系统总线锁住,不让其他 cpu干扰。
温馨提示:答案为网友推荐,仅供参考