RISC-V架构学习——C语言内嵌汇编总结

news/2024/11/26 23:47:21/

1、C语言内嵌汇编的作用

(1)优化:对于特别重要代码进行优化,出于性能的考虑;
(2)C语言需要借助汇编指令来实现特殊功能。比如:C语言中访问系统寄存器就需要借助CSR指令;

2、基础内嵌汇编

2.1、基础内嵌汇编格式

asm asm-qualifiers(AssemblerInstructions)
关键字含义
asm这是内嵌汇编的关键字,表明这是一个GNU扩展
asm-qualifiers修饰词,比如:volatile、inline
AssemblerInstructions要内嵌的汇编语句,如果是多条汇编语句指令,需要使用"\n\t"来换行

(1)基础内嵌汇编指令支持带参数;
(2)gcc编译器不会去解析内嵌汇编指令,当做一个字符串处理;

2.2、基础内嵌汇编举例

#同时内嵌多条汇编指令
asm( "pushl %eax\n\t""movl $0,%eax\n\t"
"popl %eax");# 也可以将多条的内嵌汇编语句拆开写,效果一样
asm("movl %eax,%ebx");
asm("xorl %ebx,%edx");
asm("movl $0,_booga);

3、扩展内嵌汇编

3.1、扩展内嵌汇编的格式

3.1.1、格式说明

asm关键字 修饰词(指令部:输出部:输入部:损坏部:GotoLables(goto修饰时才有该部))
关键字含义
asm关键字扩展汇编指令的关键字:__asm__
指令部要内嵌的汇编指令,可以是一条或者多条
输出部用于描述在指令部中可以被修改的C语言变量以及约束条件
输入部用于描述在指令部中只能被读取访问的C语言变量以及约束条件
损坏部告诉编译器内嵌汇编可能带来的影响

3.1.2、修饰词

修饰词含义
volatile用于关闭gcc优化,可参考博客:《C语言中volatile关键字详解以及常见的面试问题》
inline用于内联,gcc会把汇编代码编译成尽可能短的代码
goto用于在汇编代码里跳转到C语言的标签处

3.1.3、内嵌汇编操作符号/修饰符

操作符/修饰符含义
=被修饰的操作数是只写属性
+被修饰的操作数具有可读可写属性
&被修饰的操作数只能作为输出,这个操作数在输入参数的指令执行完成之后才能写入

输出部通常用“=”或者“+”修饰符;输入部分则不能用“=”或者“+”约束条件,否则编译器会报错,因为输入部是用来描述只能读取的C语言变量,不能具有写属性;

3.1.4、操作数约束符

操作符/修饰符含义
p内存地址
m内存变量
r通用寄存器
o内存地址,基地址寻址
i立即数
V内存变量,不允许偏移的内存操作数
n立即数

3.1.5、损坏部介绍

关键字含义
memory告诉编译器,内嵌汇编代码改变了内存中的值,执行完汇编代码后重新加载该值
cc告诉编译器,内嵌汇编代码修改了状态寄存器的相关标志位

3.1.6、指令部的参数表示

3.1.6.1 、用"前缀% + 数字"表示变量

asm volatile(
"add %0, %1, %2" 
: "=r"(res)
: "r"(i), "r"(j)
);

(1)%0对于"=r"(res),%1对应"r"(i),%2对应"r"(j),内嵌汇编的功能:把i+j的结果写到res中;
(2)"r"修饰词,表示该变量需要使用一个通用寄存器;
总结:用%+数字来引用后面输入部和输出部的参数;

3.1.6.2 、用汇编符号来表示变量

asm volatile(
"add %[result], %[input_i], %[input_j]" 
: [result] "=r"(res)
: [input_i] "r"(i), [input_j] "r"(j)
);

在输出部和输入部定义变量时就绑定符号,然后在指令部就可以通过符号来引用变量,提高代码的可读性;

3.1.7、goto修饰词介绍

asm goto("addi %0, %0, -1\n""beqz %0, %1[label]\n":: "r"(a): "memory": label);return 0;label:printf("11111\n");

(1)输出部必须是空的。goto是用于跳转功能,在满足某个条件下进行跳转,没有输出数据的必要;
(2)相较于其他情况,goto修饰的情况下多了标签部,表明最后要跳转的标签处;
(3)上面内嵌汇编的功能:当变量a是1时,则跳转到标签label处;

3.2、扩展汇编实例分析

//读取csr寄存器的宏
#define read_csr(csr)						\
({								\register unsigned long __v;				\__asm__ __volatile__ ("csrr %0, " #csr			\: "=r" (__v) :			\: "memory");			\__v;							\
})unsigned long val;
val = read_csr(mstatus);//将上面的代码按宏定义展开
val = ({ register unsigned long __v; \__asm__ __volatile__ ("csrr %0, " "mstatus" : "=r" (__v) : : "memory");\__v; });

3.3、内嵌汇编和宏结合

//用ATOMIC_OP宏定义内嵌汇编的函数,摘抄自linux源码
#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)		\
static __always_inline							\
void arch_atomic##prefix##_##op(c_type i, atomic##prefix##_t *v)	\
{									\__asm__ __volatile__ (						\"	amo" #asm_op "." #asm_type " zero, %1, %0"	\: "+A" (v->counter)					\: "r" (I)						\: "memory");						\
}	#define ATOMIC_OPS(op, asm_op, I)					\ATOMIC_OP (op, asm_op, I, w, int,   )				\ATOMIC_OP (op, asm_op, I, d, s64, 64)ATOMIC_OPS(add, add,  i)//将上面的宏展开
static __always_inline void arch_atomic_add(int i, atomic_t *v)
{__asm__ __volatile__ ( "amoadd.w " zero, %1, %0" : "+A" (v->counter) : "r" (i): "memory"); 
}

http://www.ppmy.cn/news/1117173.html

相关文章

泡泡玛特大火,潮玩行业如何利用软文推广出圈

随着经济的发展,各类潮玩创意落地、新产品层出不穷,也导致潮玩行业陷入了类目繁多,但是新品很难出圈的困境。泡泡玛特作为年轻人中十分受欢迎的品牌,紧跟消费浪潮,成为国内营销赛道上一个让人无法忽视的潮玩IP。那么潮…

aspose-words导出word方法

一、引用依赖 <dependency><groupId>com.aspose</groupId><artifactId>aspose-words</artifactId><version>19.5</version><classifier>jdk17</classifier></dependency>二、导出类 public class WordTable {//定…

高成本获客时代,企业如何通过营销自动化实现突围?

在数字化时代&#xff0c;随着市场竞争的不断升级&#xff0c;企业在获客方面面临了前所未有的挑战。不论是B端或C端的市场和运营部门纷纷寻求可降低获客成本的新运营路径&#xff0c;将有限的预算花在刀刃上。 企业迫切需要寻求更加智能和高效的方式来吸引、转化和留住潜在客…

华为华三40G带宽互通连接测试

郁闷了几天了&#xff0c;今天竟然做了件爽事&#xff01;慢慢说来。 今天下雨&#xff0c;下午娃上学&#xff0c;我送老婆去学校上课。之后到实验室&#xff0c;今年申请买的两台交换机正好送到&#xff1a; S5500V2-54S-EI&#xff1a;48个10/100/1000TX以太网端口&#x…

告白玫瑰||书信逐字打印效果

❝ 关注微信公众号「ClassmateJie」 更多惊喜等待你的发掘 ❞ 直接看实现效果 电脑端 手机端 使用场景 发给女神告白~ 提供一些文案 “自从遇见你&#xff0c;我的世界变得不一样了。每一天都因为你而变得特别。我想告诉你&#xff0c;我喜欢你&#xff0c;不仅仅是因为你的美丽…

AO天鹰优化算法|含源码(元启发式算法)|跑23个经典函数(含源码)

-------往期目录------ 1、灰狼优化算法 文章目录 天鹰优化器一、第一种搜索方法二、第二种搜素方法三、第三种搜素方法四、第四种搜索方法 代码实现 天鹰优化器 Aquila Optimizer&#xff08;AO&#xff09;&#xff0c;灵感来自Aquila在捕捉猎物过程中的自然界行为。因此&a…

组件切换之笨办法、动态组件(is属性、keep-alive)、插槽(不具名、具名)

组件切换之笨办法、动态组件、动态组件之keep-alive、插槽(不具名、具名) 1 组件切换之笨办法 2 动态组件 3 动态组件之keep-alive 4 插槽 4.1 不具名插槽 4.2 具名插槽 1 组件切换之笨办法 <!DOCTYPE html> <html lang"en"> <head><meta…

Vue2使用vue-router初始化项目

Vue2使用vue-router初始化项目 **项目版本号** vue2.6.14 vue-router3.6.5在components中创建Main.vue文件&#xff0c;输入页面要显示的内容&#xff1a; <template><h1>这是 Main 组件</h1> </template><script> export default {name: thisM…