您的位置:首页 > 其它

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__进行修饰。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: