c语言内嵌汇编作用,C语言内嵌汇编学习笔记

本文详细介绍了C语言内嵌汇编Extended Asm的语法,包括asm-qualifiers、AssemblerTemplate、OutputOperands、InputOperands和Clobbers的用法,并通过实例解析了如何在汇编模板中引用C语言变量以及如何定义输入输出约束。同时,讨论了内存屏障的实现和clflush指令的应用,帮助读者深入理解内嵌汇编在实际编程中的应用。
摘要由CSDN通过智能技术生成

这里只谈Extended Asm。

Extended Asm的基本语法:

asm asm-qualifiers ( AssemblerTemplate

: OutputOperands

[ : InputOperands

[ : Clobbers ] ])

其中asm-qualifiers是修饰符,常用的有volatile,表示不要优化。

AssemblerTemplate 是汇编模板,可以有多条(一般用"\n\t"隔开)。OutputOperands是输出,InputOperands是输入,Clobbers是受影响的东西。

Assembler Template

AssemblerTemplate 里引用C语言变量时可以使用编号,比如%i表示OutputOperands和InputOperands里的第i个变量。

例子:

uint32_t Mask = 1234;

uint32_t Index;

asm ("bsfl %1, %0"

: "=r" (Index)

: "r" (Mask)

: "cc");

%0就是Index,%1就是Mask。

所以这段代码的意思是把Mask的最高的"1"位的下标存入Index中。

参考:https://blog.csdn.net/zdl1016/article/details/8763803

也可以使用名字。例子:

uint32_t Mask = 1234;

uint32_t Index;

asm ("bsfl %[aMask], %[aIndex]"

: [aIndex] "=r" (Index)

: [aMask] "r" (Mask)

: "cc");

其中aIndex可以直接换为Index,aMask可以直接换为Mask。

Output Operands

一个operand的格式如下:

[ [asmSymbolicName] ] constraint (cvariablename)

不同的operand之间用逗号隔开。

prefix

Output operands的constraint必须以=或+开始。

=: 把结果写入

+: 既读又写。此时这个operand不需要在Input Operands里出现。

additional constraints

Input Operands

一个operand的格式如下:

[ [asmSymbolicName] ] constraint (cexpression)

constrain

没有prefix

数字(例如i):表示这个输入操作数的物理位置必须与第i个输出操作数的物理位置一致。

asm ("combine %2, %0"

: "=r" (foo)

: "0" (foo), "g" (bar));

方括号括起来的变量名:表示这个输入操作数的物理位置必须与这个变量名对应的输出操作数的物理位置一致。

asm ("cmoveq %1, %2, %[result]"

: [result] "=r"(result)

: "r" (test), "r" (new), "[result]" (old));

其他(与Output operands的constrain一样)

Clobbers

一些常见的:

cc: 修改了标志寄存器

memory: 进行了除Input operands和Output operands外的内存读写。可用于实现read/write memory barrier。

例:

#define barrier() __asm__ __volatile__("": : :"memory")

内存屏障有效率问题。所以如果知道会读写哪些内存,就可以在Input operands和Output operands里指定,而不需要使用"memory"。

例子:

假设指令vecmul x, y, z含义是*z++ = *x++ * *y++,那么写成内嵌汇编应该是

asm ("vecmul %0, %1, %2"

: "+r" (z), "+r" (x), "+r" (y), "=m" (*z)

: "m" (*x), "m" (*y));

这样虽然进行了内存读取,但是在Input operands和Output Operands范围内,不需要使用开销很大的"memory"。

同理,如果知道只会读后面的10个字节,可以把Input operand写成这样:

"m" (*(const char (*)[10]) p)

解读

clflush

static inline void clflush(volatile void *__p)

{

asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));

}

clflush(p)的含义简单来说就是把包含p指向的内存的cache line写入内存,然后将这个cache line无效化,也就是说今后读取这个cache line对应的部分时都要重新从内存中读取。

64bbcce86afd5f32aa51ba8356d947c5.gif

4a668feaa3018a2e1706f07e5002bcc8.png

search_star

发布了71 篇原创文章 · 获赞 2 · 访问量 3047

私信

关注

标签:__,内嵌,汇编,Index,Mask,C语言,内存,https,asm

来源: https://blog.csdn.net/qq_41961459/article/details/104518801

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值