gcc内联汇编

基本格式

asm asm-qualifiers ( AssemblerTemplate 
                 : OutputOperands 
                 [ : InputOperands
                 [ : Clobbers ] ])

对于ARMCC,使用__asm而不是asm

ARM Compiler User Guide Version 6.6

asm-qualfiers

asm-qualifiers说明
volatile提示编译器不要对汇编代码进行优化(例如移动代码位置,甚至直接忽略掉代码)
inline提示编译器估算汇编代码长度的方式(很少用)
goto提示编译器此内联汇编可能会执行跳转到某些标号的操作(很少用)。

AssemeblerTemplate

这部分是传递给汇编器的汇编代码编写部分,可以使用任何合法的汇编指令。汇编指令的操作数可以设置为一般的寄存器、立即数、内存地址等,也可以设置为占位符,由后续OutputOperands以及InputOperands来决定。

%(百分号)被用作特殊转义字符,因此%%表示%{}|被用作特殊字符,因此%{表示{%}表示}%|表示|

在如下例子中,使用了寄存器eax,以及占位符%0, %1来作为操作数。

asm volatile (
		"movl %%eax, %0\n\t"
		"addl %0, %1"
		: "=r" (variable1)
		: "r" (variable2)
		: "eax"
);

"=r" (variable1)指定输出操作数,其表示第一个占位符变量%0为C语言变量variable1, 并且在汇编中使用寄存器(r)的方式存储,且变量是只写的(r之前的=,只写表示不关心变量之间的值)。变量对应的占位符的名称可以自定义,例如[v_name] "=r (variable)"就指定变量variable对应的占位符名称为%[v_name],没有指定占位符名称的变量其占位符名称按照变量定义顺序依次为%0,%1,%2...

"r" (variable2)指定输入操作数,其表示第二个占位符变量%1为C语言变量variable2, 并且在汇编中使用寄存器(r)的方式存储,变量是只读的(读写变量需要在输出操作数中指定)。变量对应的占位符的名称可以自定义,例如[v_name] "=r (variable)"就指定变量variable对应的占位符名称为%[v_name],没有指定占位符名称的变量(从第一个变量开始,不分输出和输入操作数),其占位符名称按照变量定义顺序依次为%0,%1,%2...

"eax"则表示汇编代码内部会修改eax寄存器

OutputOperands

输出操作数位于AssemeblerTemplate后,使用:(分号)隔开,可以为空,也可以指定多个输出操作数,每一个操作数由如下三个部分来定义(第一部分asmSymbolicName,也就是上文所提到的占位符变量名称可以省略),多个输出操作数之间通过,逗号隔开。

[asmSymbolicName] constraint (cvariablename)

如下例子定义了三个输出操作数,对应c语言变量variable1, variable3以及variable4

asm volatile (
		"movl %%eax, %0\n\t"
		"addl %0, %1"
		: [v1] "=r" (variable1), "+r" (variable3), [v4] "=r" (variable4)
		: "r" (variable2)
		: "eax"
);

constraint主要由两部分,第一部分表示读写操作限制,第二部分为变量存储的方式限制,读写限制只能指定一种,存储限制可以指定多种让编译器选择最合适的方式,例如"=rmi"

读写限制说明
+该变量即被读取也被写入
=该变量仅被写入(即不关心变量之前的值)
存储限制说明
r使用寄存器保存
m使用内存保存
i使用立即数保存

InputOperands

InputOerands位于OutputOperands之后,使用:(分号)隔开,其格式同OutputOperands一致,唯一的区别是InputOerands变量默认是只读的,并且无法使用读写限制符号进行控制(即constraint中无法使用+=),因此同时需要读写的变量只能写在OutputOperands

[asmSymbolicName] constraint (cvariablename)
asm volatile (
		"movl %%eax, %0\n\t"
		"addl %0, %1"
		: [v1] "=r" (variable1), "+r" (variable3), [v4] "=r" (variable4)
		: "r" (variable2)
		: "eax"
);

Clobbers

Clobbers描述汇编代码对寄存器和内存的修改情况(除开InputOperandsOutputOperands中指定的变量之外),位于InputOerands之后,使用:分号隔开, 如果需要修改多个寄存器,使用,隔开,通过指针修改内存则需要加入"memory"

: ”eax“, "ebx", "memory" 

例子

使用内联汇编实现字节序转换

// x86
#define BSWAP4(des, src) asm ( "movl %1, %0\n"\
                               "bswap %0" \
                               : "=r"(des) \
                               : "r"(src))
// arm
#define BSWAP4(des, src) asm ("rev %0, %1" \
                        : "=r"(des) \
                        : "r"(src))

参考 Extended Asm (Using the GNU Compiler Collection (GCC))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值