曾几何时研究汇编时(大约2013~2014年左右吧),主要研究的是Xilinx ISE 14.x自带的gcc文档,它是Sourcery CodeBench版本的gcc文档,时隔多年遗忘不少,因此打算发表一个《汇编学习笔记》的文章,方便日后观看~~
文章目的:为避免之后遗忘,总结一些汇编的笔记
1. C语言中的asm(内嵌汇编)
经常会看到C中会插入如下代码:
__asm__("nop");
其实这是编译器扩展C语言的汇编实现功能,__asm__等同于asm
asm语法如下:(GNU官网提供http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html)
asm [volatile] ( AssemblerTemplate : OutputOperands [ : InputOperands [ : Clobbers ] ]) asm [volatile] goto ( AssemblerTemplate : : InputOperands : Clobbers : GotoLabels)
下面那一种不太常用(涉及goto语句),分析上面的那种,我们以colons (‘:’) 为区分,分别说明
第一个:汇编代码,用""括起来
第二个:输出参数(必须有"="符号)
第三个:输入参数
第四个:Clobber或叫Modify,破坏或说改变的寄存器或memory
举一个简单的例子(源于Xilinx Vivado2015.4中gcc.pdf(gcc4.9.2, CodeBench Lite 2015.05-16))
asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
这是个简单的内嵌汇编指令,执行的是fsinx函数,这里%0指第一个参数(result)、%1指第二个参数(angle),"=f"中"="表输出,"f"表该变量为浮点数,后面类同,括号里的为变量名,简单吧~~~
再举个实际的例子,以Linux内核中barrier()函数为例
#define barrier() __asm__ __volatile__("": : :"memory")
这里可以说是这样,执行汇编代码为空,输出为空,输入为空,clobber为memory说明该语句需要操作存储器,而编译器在遇到"memory"会把registers里的值flush回存储器,并且不优化读/写存储器区域,Xilinx Vivado2015.4中gcc.pdf(gcc4.9.2, CodeBench Lite 2015.05-16)中有这样的描述
This causes GCC to not keep memory values cached in registers across the assembler instruction and not optimize stores or loads to that memory.
这样就实现了编译器的优化屏障(即linux的barrier函数功能)
此外,这里__volatile__作用是因为,输入和输出全是空,不加的话这段代码会被编译器优化掉(防止优化作用哈)
2. LDREX和STREX
ARM汇编指令,用于mutex操作时使用,为独占访问操作指令,具体可参考链接:http://bluereader.org/article/67865540