GCC内联汇编
来源:互联网 发布:淘宝客返利在哪里查看 编辑:程序博客网 时间:2024/06/05 11:07
GCC内联汇编
基本内联语法:
GCC用关键字asm
表示一段用汇编语言写的源代码。形式如下: asm ("assemble language");
说明:
1. 汇编指令必须用双引号扩起来
2. 如果有多条汇编指令,必须用换行符隔开(\n),每条语句之前最好加上tab(\t),为了区别汇编语言中的标号(label)。
编译器实际上把asm
括号中双引号引起来的语句逐字的插入到编译后产生的汇编文件中(.s),并进行了相应的替换操作。
可以这样: asm ("movl $1,%eax\n\tmovl $0,%ebx\n\tint $0x80");
看起来麻烦,可以分行,分开成多个双引号:
asm ("movl $1,%eax\n\t" "movl $0,%ebx\n\t" "int $0x80");
可以使用C程序中的全局变量:
#include <stdio.h>int a = 10;int b = 20;int result;int main(){ asm("pusha\n\t" "movl a, %eax\n\t" "movl b, %ebx\n\t" "imull %ebx, %eax\n\t" "movl %eax, result\n\t" "popa"); printf("the answer is %d\n",result); return 0;}
有时候编译器会对变易产生的汇编代码进行优化,可能导致产生的效果与我们预想的不一样。可以在asm
之后使用volatile
关键字进行说明,让编译器不进行优化。
Note:如果使用ANSI C标准,asm
和volatile
都要写成__asm__
__volatile__
。
扩展的ASM
基本形式有很多限制:输入输出只能使用C语言中的全局变量,而且不能随意地改变寄存器的值。(前面的例子中开头和结尾使用pusha和popa来保存寄存器)
扩展汇编形式: asm ("assembly code" : output locations : input operands : changed registers);
这种形式有四个部分,用冒号隔开:
汇编代码(assembly code):内联汇编代码,语法同基本asm格式。
输出位置(output locations):汇编代码中输出值所在的寄存器和内存单元列表。(执行汇编代码之后)
输入操作符(input operands):汇编代码中输入值所在的寄存器和内存单元的列表。(执行汇编代码前处理)
改变的寄存器(changed registers):内联汇编代码中改变的寄存器(用于提醒编译器对这些寄存器进行保护操作)。
在基本asm格式中,汇编语言中输入输出值可以直接使用C语言中的全局变量,但是在扩展asm格式中,格式不太一样:
“constraint”(variable) variable
是一个C语言变量(全局变量或局部变量都可以),constraint
定义了从哪里取这个变量(对于输入变量来说)或往哪里存放(对输出变量)。constraint
可能的取值如下表:
除了这些限制,输出值还包含一个限制修饰符,它指明编译器如何处理输出值。
举例: asm ("assembly code" : "=a"(result) : "d"(data1),"c"(data2));
这个例子中C变量data1
放在%edx
,data2
放在%ecx
。输出结果会被放到%eax
,然后送到result
变量。
#include <stdio.h>int main(){ int data1 = 10; int data2 = 20; int result; asm ("imull %%edx, %%ecx\n\t" "movl %%ecx, %%eax" : "=a"(result) : "d"(data1), "c"(data2) ); printf("The result is %d\n",result); return 0;}
asm volatile ("cld\n\t" "rep movsb" : :"S"(input),"D"(output),"c"(length));
由于没有指定输出规则,编译器会认为这段汇编是不必要的,因此要加上volatile
。
汇编语言部分(assembly language
)可以使用占位符(placeholder)用来引用输出输入变量。格式为%0 %1 ...
用来表示输出输入列表中的变量。
asm ("imull %1, %2\n\t" "movl %2, %0\n\t" :"=r"(result) :"r"(data1),"r"(data2) );
%0
代表存放result
的寄存器;%1
代表存放data1
的寄存器;%2
代表存放data2
的寄存器。
asm ("imull %1,%0" : "=r"(data2) : "r"(data1),"0"(data2));
“0”表示让编译器使用第一个命名的寄存器。
int dividend = 20 ;int divisor = 5;int result ;asm ("divb %2\n\t" "movl %%eax, %0" : "=m"(result) : "a"(dividend),"m"(divisor));
内联汇编可以使用标签,用来进行跳转。数字可以作为局部标签。
asm ("cmp %1, %2\n\t" "jge 0f\n\t" "movl %1, %0\n\t" "jmp 1f\n" "0:\n\t" "movl %2, %0\n" "1:" :"=r"(result) :"r:(a),"r"(b));
0:
1:
都是label,jmp 0f
中f
表示forward,如果向后跳转使用b
backward。
- gcc内联汇编
- GCC内联汇编基础
- GCC内联汇编
- GCC内联汇编入门
- GCC内联汇编基础
- GCC内联汇编
- Gcc内联汇编1
- Gcc内联汇编2
- GCC内联汇编基础
- gcc内联汇编入门
- GCC 内联汇编
- GCC内联汇编基础
- gcc内联汇编
- GCC 内联汇编测试
- GCC内联汇编
- GCC 内联汇编
- GCC内联汇编
- 汇编语言---GCC内联汇编
- c语言小练习6
- 【总结】Netty(RPC高性能之道)原理剖析
- linux
- JDBC:提取重复代码进行重构
- Linux下的重要命令详解
- GCC内联汇编
- 【转载】JAVA中线程同步的方法(7种)汇总
- java练习题6
- 盒模型以及相关样式
- 计算级系统基础知识
- 盒子垂直居中显示以及position的属性值问题
- hashmap的滥用
- NOIP2006金明的预算方案
- 「Unity3D」(6)协程使用IEnumerator的几种方式