linux汇编mips,GCC内嵌汇编(mips)

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

以MIPS架构的汇编为主进行说明1

2

3

4

5

6

7

8__asm__ __volatile__(

"1: ll %1, %2 # arch_read_lock n"

" bltz %1, 1b n"

" addu %1, 1 n"

"2: sc %1, %0 n"

: "=m" (rw->lock), "=&r" (tmp)

: "m" (rw->lock)

: "memory");基本形式: __asm__ __volatile__("ssnopnt");ssnop: 空指令

汇编扩展以__asm__开头表示后面部分为汇编,__volatile__严禁将此处的汇编语句和其他语句进行重组优化,就是希望gcc不要修改我们这个部分。

构成

主要由四部分构成,之间以:分隔:instruction指令:每条指令之后最好使用"nt"结尾,这样在gcc产生汇编格式比较好.

output operand输出:每个输出部分使用,分隔.”=”作为修饰符,”m”表示存放位置/约束符,()里面表示对应C程序值.

input operand输入:这个部分和输出是一样的.

clobber(装备):这个部分是告诉gcc在这条指令里面我们会修改什么值.

约束符

束符影响的内容包括:whether an operand may be in a register

which kinds of register

whether the operand can be a memory reference

which kinds of address

whether the operand may be an immediate constant

which possible values it may have

约束符包括:p 内存地址

m 内存变量

o 内存变量,但是寻址方式必须是偏移量的,就是基址寻址或者是基址变址寻址.

V 内存变量,但是寻址方式是非偏移量的.

r general寄存器操作数

i 立即操作数,内容在编译器可以确定.

n 立即操作数.有些系统不支持字(双字节)以外的立即操作数,这些操作数以n非i来表示.

E/F 浮点常数

g 内存操作数,整数常数,非genernal寄存器操作数

X 任何操作数

0,1,2…9 和编号指定操作数匹配的操作数束符影响的内容包括

修饰符

修饰符包括:= 操作数是write only的

+ 操作数是可读可写的

& 常用于输出限定符,表示某个寄存器不会被输入所使用.1

2

3

4

5

6

7

8__asm__ __volatile__(

" .set mips3 n"

" ll %0, %1 # atomic_sub n"

" subu %0, %2 n"

" sc %0, %1 n"

" .set mips0 n"

: "=&r" (temp), "+m" (v->counter)

: "Ir" (i));

实例

读取CP0 25号硬件计数寄存器的值1

2

3

4

5

6

7

8

9

10

11int get_counter()

{

int rst;

__asm__ __volatile__(/* mfc0 为取cp0 寄存器值的指令 */

"mfc0%0, $25nt"/* %0 表示列表开始的第一个寄存器 */

: "=r" (rst)/* 告诉gcc 让rst对应一个通用寄存器 */

);

return rst;

}“=r” 中,’=’ 为修饰符,表示该操作对象只写,一般用于修饰输出参数列表中。’r’ 表示任意一个通用寄存器

设置CP0 24号硬件计数寄存器的值1

2

3

4

5

6

7unsigned int op = 0x80f;

__asm__ __volatile__(

"mtc0 %0, $24nt"

:/* 没有输出,列表为空 */

:"r"(op)/* 输入参数,告诉gcc 让op对应一个通用寄存器 */

);

重设后,读取CP0 24号寄存器的值1

2

3

4

5

6

7

8

9unsigned int rst;

unsigned int op = 0x80f;

__asm__ __volatile__(

"mtc0%1, $24nt"/* %1 表示 op 对应的寄存器 */

"mfc0%0, $25nt"/* %0 表示 rst 对应的寄存器 */

: "=r" (rst)

: "r" (op)

);输入输出参数列表,按先后顺序,从0开始编号, %0, %1。

解读开头汇编代码

读写锁中读锁上锁的汇编实现:1

2

3

4

5

6

7

8__asm__ __volatile__(

"1: ll %1, %2 # arch_read_lock n"

" bltz %1, 1b n"

" addu %1, 1 n"

"2: sc %1, %0 n"

: "=m" (rw->lock), "=&r" (tmp)

: "m" (rw->lock)

: "memory");"=m" (rw->lock): 只写内存操作

"=&r" (tmp) : 只写的输出变量,使用一个通用寄存器

"memory": 告诉gcc编译,该指令会修改内存中的值通过原子操作ll,将rw->lock读到tmp

加一:tmp = tmp + 1

通过原子操作sc,将tmp写入rw->lock

barrier

内存屏障:保证前后指令的执行顺序1file: include/linux/compiler-gcc.h

"memory"作为clobber部分另外一个作用是可以让在这条指令之后的指令,告诉gcc应该刷新内存状态.内存的状态可能发生修改,如果需要操作的话,需要重新把内存内容载入寄存器

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值