内嵌汇编

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
    unsigned long tmp;

    __asm__ __volatile__(
"1: ldrex   %0, [%1]\n"          
"   teq %0, #0\n"                    
    WFE("ne")
"   strexeq %0, %2, [%1]\n"
"   teqeq   %0, #0\n"
"   bne 1b"
    : "=&r" (tmp)
    : "r" (&lock->lock), "r" (1)
    : "cc");

    smp_mb();
}   
 
内嵌汇编的通用形式:
 __asm__ __volatile__ (
   代码
   : 输出操作数列表
   : 输入操作数列表
   : registers-modified
 );
 
在一个asm语句中可以写一条或者多条汇编代码,一条汇编代码结束采用\n进行换行,有时候,也采用\n\t进行换行。
C语言通过变量的形式访问数据,而汇编语言是通过内存地址或者直接访问寄存器的方式访问数据,如果要在内嵌汇编中访问C语言中的变量,并且修改它的值的话,那么就需要用一种方式用于相互转换C语言的变量与内嵌汇编能访问的寄存器或内存地址形式。这种方式就是通过输入操作数列表和输出操作数列表实现的。
输入和输出操作数列表的格式是一样的,都是由一个或者多个操作数组成,中间采用逗号进行分开,单个操作的格式如下:
 [C变量在汇编中的访问名称] "限制性字符“ (C传递进来的变量名称)
 
常用限制符:
     m          Any valid memory address,有效内存地址
     r            General register r0 .. r15,通用寄存器r0~r15
     I             Immediate value in data processing instructions
上面这些限制性字符如果不带修饰符的话,表示是只读操作数,只能用于输入操作数列表中。对于输出操作数列表中的操作数我们需要加上相应的写权限。常用修饰符包括如下:
     =              Write-only operand, usually used for all output operands  只写操作数,通常用于所有的输出操作数。
     +              Read-write operand, must be listed as an output operand 读写操作。
     &              A register that should be used for output only        只用作输出的寄存器。(表示不能与输入寄存器用同样一个寄存器)
 
asm __volatile__(
    "mcr p15, 0, %[domain], c3, c0, 0\n\t"  //domain
    "mcr p15, 0, %[ttb], c2, c0, 0\n\t" //ttb_base
    "mrc p15, 0, r0, c1, c0, 0\n\t"     //mmu enable
    "orr r0, r0, #1\n\t"
    "orr r0, r0, #(1<<13)\n\t"
    "mcr p15, 0, r0, c1, c0, 0\n\t"
    : 
    : [ttb] "r" (ttb), [domain] "r" (0xffffffff)          //%0--->ttb, %1--->domain
    : "memory", "r0"
);
 
通常在内嵌汇编中我们使用%0,%1之类的访问输入或输出操作数,但我们也可以自定义变量来访问,且内嵌汇编中的变量名与C中的变量名相同也不会有问题。
 
“cc”:你使用的指令会改变CPU的条件寄存器cc;
“memory”:你使用的指令会修改内存;
posted @ 2015-12-07 22:17  suonikeyinsu  Views(981)  Comments(0Edit  收藏  举报