c 语言中嵌入 asm
作者:
| 更新日期:以前在acm比赛的时候,经常听说某些人在代码中嵌入汇编把题水过去,今天查了一下资料。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
__asm__ 与 asm
在网上查询资料时,有的是用 asm 嵌入汇编,有的是用__asm__ 嵌入汇编。
后来在 gnu gcc 的官网的alternative keywords文档中发现原来它们是一个意思,而且建议使用__asm__ 。
-ansi and the various -std options disable certain keywords.
-ansi 和 -std 选项可以禁用某些关键字。
在编译的时候使用 -ansi 或 -std 参数就会使 asm, typeof 和 inline 变为无效。
解决这个问题的方法是在每个有问题的关键字的前面和后面加上 __ .
例如 使用 __asm__ 代替 asm, 使用 __inline__ 代替 inline.
其他 c 编译器 不接受 alternative keywords,所以一般需要重新定义这些关键字。
#ifndef __GNUC__
#define __asm__ asm
#endif
基本的 Asm
这个小节主要参考 Basic-Asm.
asm 关键字允许我们在C代码中嵌入汇编指令。
语法
asm [ volatile ] ( AssemblerInstructions )
为了兼容性,一般使用 __asm__ 替代 asm.
__asm__ [ volatile ] ( AssemblerInstructions )
限定符
可选的限定符没有什么效果,因为默认就是 volatile。
参数
参数就是汇编解释器可以识别的指令。
一般C编译器不对参数做任何处理,只是copy输出到汇编程序文件里面。
唯一的区别是寄存器的表示有点不同: 扩展汇编用 %%eax ,基本汇编用 %eax。
备注
使用扩展汇编会代码量更少,更安全,执行效率更高。
在 c 函数之外嵌入汇编时必须用基本汇编。
扩展汇编
这个小节主要参考Extended-Asm.
语法
__asm__ [volatile] ( AssemblerTemplate : [OutputOperands] [ : [InputOperands] [ : [Clobbers] ] ] )
__asm__ [volatile] goto ( AssemblerTemplate : : [InputOperands] : [Clobbers] : GotoLabels )
使用分号分割操作数。
参数
- AssemblerTemplate 汇编代码
- OutputOperands 输出操作数,使用逗号分隔
- InputOperands 输入操作数,使用逗号分隔
- Clobbers 寄存器或一些改变的变量,使用逗号分隔
- GotoLabels 汇编代码中可能使用的C语言中的 标签。
备注
int src = 1;
int dst;
asm ("mov %1, %0\n\t"
"add $1, %0"
: "=r" (dst)
: "r" (src));
printf("%d\n", dst); //2
其他知识
关于其他知识,请自己查看官方的 c语言中嵌入汇编 的文档.
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。