gcc 内联asm
2015-12-02 22:19
281 查看
1.基本的内联汇编
1)asm格式 http://blog.csdn.net/guzhou_diaoke/article/details/8393548
GNU的C编译器使用asm关键字指出使用汇编语言编写的源代码段落。基本格式:asm("assembly code");
括号中的汇编格式:指令必须在引号里;指令超过一条,必须使用新行字符分隔。如:
[cpp] view
plaincopyprint?
asm ( "movl $1, %eax\n\t"
"movl $0, %ebx\n\t"
"int $0x80" );
3)volatile修饰符
编译器会试图优化生成的汇编代码以提高性能。但对内联汇编来说,优化有时并不是好事。如果不希望编译器处理内联汇编代码,可以明确地说明。用volatile修饰符可以完成这个请求:asm volatile ("assembly code");
gcc 内联汇编的格式如下:
[cpp] view
plaincopy
asm ( 汇编语句
: 输出操作数 // 非必需
: 输入操作数 // 非必需
: 其他被污染的寄存器 // 非必需
);
我们通过一个简单的例子来了解一下它的格式(gcc_add.c):
[cpp] view
plaincopy
#include <stdio.h>
int main()
{
int a=1, b=2, c=0;
// 蛋疼的 add 操作
asm(
"addl %2, %0" // 1
: "=g"(c) // 2
: "0"(a), "g"(b) // 3
: "memory"); // 4
printf("现在c是:%d\n", c);
return 0;
}
内联汇编中:
第1行是汇编语句,用双引号引起来, 多条语句用 ; 或者 \n\t 来分隔。
第2行是输出操作数,都是 "=?"(var) 的形式, var 可以是任意内存变量(输出结果会存到这个变量中), ? 一般是下面这些标识符(表示内联汇编中用什么来代理这个操作数):
a,b,c,d,S,D 分别代表 eax,ebx,ecx,edx,esi,edi 寄存器
r 上面的寄存器的任意一个(谁闲着就用谁)
m 内存
i 立即数(常量,只用于输入操作数)
g 寄存器、内存、立即数 都行(gcc你看着办)
在汇编中用 %序号 来代表这些输入/输出操作数,序号从 0 开始。为了与操作数区分开来,寄存器用两个%引出,如:%%eax
第3行是输入操作数,都是 "?"(var) 的形式, ? 除了可以是上面的那些标识符,还可以是输出操作数的序号,表示用 var 来初始化该输出操作数,上面的程序中 %0 和 %1 就是一个东西,初始化为 1(a的值)。
第4行标出那些在汇编代码中修改了的、又没有在输入/输出列表中列出的寄存器,这样 gcc 就不会擅自使用这些"危险的"寄存器。还可以用 "memory" 表示在内联汇编中修改了内存,之前缓存在寄存器中的内存变量需要重新读取。
上面这一段内联汇编的效果就是,把a与b的和存入了c。当然这只是一个示例程序,谁要真这么用就蛋疼了,内联汇编一般在不得不用的情况下才使用。
4)__asm__替换关键字
ANSI C 规范把关键字asm用于其他用途,不能将它用于内联汇编语句。如果希望使用ANSI C 约定编写代码,必须使用关键字__asm__替换一般的关键字asm。汇编代码段则与asm一样。__asm__可以使用__volatile__进行修饰。
相关文章推荐
- leetcode---Add Digits
- asp连接sql server
- 超级强大的formValidator
- u3d关于system.data每次在vs上重新加载都会丢失引用的问题
- Java关键字instanceof
- memcpy, memccpy函数实现——string.h库函数
- Ubuntu14.04下手动安装Firefox的Flash插件
- submit与execute区别
- Linux学习笔记(三)
- 架构之路(七)MVC点滴
- 《系统运维全面解析:技术、管理与实践》纠错汇总
- C6416启动失败
- smart pointer总结
- CSS居中之美
- NASA 雾天标准图像/低对比度图像 /水下图像网站
- 利用R语言计算国内两个地点的距离
- Python爬虫教程——新浪微博登陆
- 如何将Chromium Embedded Framework (CEF) 嵌入到你自己的程序中
- 对用户标识与鉴别的认识
- Linux内核Socket CAN中文文档