内联汇编的重要性体现在它能够灵活操作,而且可以使其输出通过 C 变量显示出来。因为它具有这种能力,所以 "asm" 可以用作汇编指令和包含它的 C 程序之间的接口。简单得说,内联汇编,就是可以让程序员在C语言中直接嵌入汇编代码,并与汇编代码交互C程序中的C表达式,享受汇编的高运行效率。
内联汇编的格式是直接在C代码中插入以下格式:
asm(
....
....
)
其中的"..."为汇编代码,比如下面例子中,在 result=a*b和printf("%d\n",result)之间插入一段汇编,
下面的这段汇编什么都不做,每个nop指令占用一个指令的执行时间
result=a*b;
asm("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop");//4个nop指令,\n\t表示换行,然后加上TAB行首空,因为每个汇编指令必须在单独一行,需要换行,加上制表符是为了适应某些编译器的要求。
printf("%d\n",result);
可以很明显地看到:
汇编代码之间用“\n\t”间隔,并且每条汇编代码单独占用一行,共有4个nop指令,每个指令后的“\n\t”表示换行,然后加上TAB行首空,因为每个汇编指令必须在单独一行,需要换行,加上制表符是为了适应某些编译器的要求。
下面是一个完整的例子,内嵌的汇编完成对2个C程序定义的全局变量c和d的相加,并将相加结果存入全局变量addresult中:
#include <stdio.h>
int c=10;
int d=20;
int addresult;
int main(void){
int a=6;
int b=2;
int result;
result=a*b;
asm("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop");//4个nop指令,\n\t表示换行,然后加上TAB行首空,因为每个汇编指令必须在单独一行,需要换行,加上制表符是为了适应某些编译器的要求。
printf("%d\n",result);
asm("pusha\n\t"
"movl c,%eax\n\t"
"movl d,%ebx\n\t"
"add %ebx,%eax\n\t"
"movl %eax, addresult\n\t"
"popa");//使用全局C变量c和d
printf("%d\n",addresult);
return 0;
}
编译上述代码
$ gcc -o test test.c
$ ./test
12
30
在汇编代码中可以直接使用变量名称操作C程序定义的全局变量,比如c、d和addresult就是全局变量:
"movl c,%eax\n\t"
"movl d,%ebx\n\t"
"movl %eax, addresult\n\t"
内联汇编部分如果不需要编译器优化( 优化可能破坏汇编代码的内部结构,因为汇编代码直接操作寄存器,而寄存器使用优化是编译器提供的功能), 可以在 "asm" 后使用关键字 "volatile"。
asm volatile(
....
....
)
如果程序必须与 ANSI C 兼容,则应该使用 __asm__ 和 __volatile__。
__asm__ __volatile__(
.........
.........
)
下面的代码和刚才代码功能一样,唯一的区别是不需要优化
#include <stdio.h>
int c=10;
int d=20;
int addresult;
int main(void){
int a=6;
int b=2;
int result;
result=a*b;
//ansi c标准的asm有其它用,所以用__asm__,__volatile__表示内联汇编部分不用优化(可以用volatile,但是ansi c不行),以防优化破坏内联代码组织结构
__asm__ __volatile__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop");//4个nop指令,\n\t表示换行,然后加上TAB行首空,因为每个汇编指令必须在单独一行,需要换行,加上制表符是为了适应某些编译器的要求。
printf("%d\n",result);
__asm__ __volatile__("pusha\n\t"
"movl c,%eax\n\t"
"movl d,%ebx\n\t"
"add %ebx,%eax\n\t"
"movl %eax, addresult\n\t"
"popa");//使用全局C变量c和d
printf("%d\n",addresult);
return 0;
}
如何在内联汇编中访问C程序的局部变量呢,请看下面这段代码
#include <stdio.h>
int main(void){
//不使用全局变量,必须使用扩展GNU的asm
//格式为:asm("汇编代码":输出位置:输入位置:改动的寄存器列表)
//a为eax,ax,al;b为ebx等;c为ecx等;d为edx等;S为esi或si;D为edi或di
//+读和写;=写;%如果必要,操作数可以和下一个操作数切换;&在内联函数完成之前,可以删除或重新使用操作数
int xa=6;
int xb=2;
int result;
//ansi c标准的asm有其它用,所以用__asm__,__volatile__表示内联汇编部分不用优化(可以用volatile,但是ansi c不行),以防优化破坏内联代码组织结构
asm volatile(
"add %%ebx,%%eax\n\t"
"movl $2,%%ecx\n\t"
"mul %%ecx\n\t"
"movl %%eax,%%edx"
:"=d"(result):"a"(xa),"b"(xb):"%ecx");//注意扩展方式使用2个%表示
printf("%d\n",result);
return 0;
}
这个例子完成这个计算:(xa+xb)*2=(6+2)*2=16
汇编代码中涉及寄存器部分的使用2个“%”,如:使用%%eax表示eax寄存器
输出位置、输入位置的特殊命名规则为:
输出位置、输入位置、改动的寄存器列表部分为:
:"=d"(result):"a"(xa),"b"(xb):"%ecx"
先来看汇编代码部分,使用双%号表示寄存器,比如:
"add %%ebx,%%eax\n\t"
关于输出位置、输入位置部分,可以这么理解:将变量与寄存器绑定,绑定后,对寄存器的操作就是对变量的操作。
:"=d"(result):"a"(xa),"b"(xb)
将result与寄存器edx绑定,xa与寄存器eax绑定,xb与寄存器ebx绑定。
%ecx属于需要改动的寄存器
如果转载请注明来源,如有错误之处,请及时指出
分享到:
相关推荐
vc内联汇编示例代码,介绍了VC++的一些被封装的汇编代码,有愿意深入了解VC++的人请进
VB支持内联汇编的插件 VB支持内联汇编的插件
ibm-basics-inline-assembly,内联汇编介绍
VC内联汇编资料 VC内联汇编资料 VC内联汇编资料 VC内联汇编资料
易语言学习-WonderWall内联汇编支持库(11-28).zip
ARM GCC 内联汇编参考手册
1. NEON优化库(Optimized libraries) 2. 向量化编译器(Vectorizing compilers) 3. NEON intrins
行业-电子政务-内联发电机.zip
ARM GCC 内联汇编参考手册 - 中文版
针对软件代码混淆算法中的内联方法存在混淆结果单一性问题,提出了一种多态内联代码混淆算法。基于有限状态自动机(FSM)建立了算法理论模型,对每个内联的方法体选择差异性的混淆实现,并通过理论分析说明了提出的...
易语言置入代码内联汇编源码,置入代码内联汇编,减法1,加法1,乘法1,除法1
工程主要时C++内联汇编的示例,内部简单的用汇编实现了函数传参及调用,循环以及if语句的实现
Keil_内联汇编的设置问题。
行业资料-电子功用-内联式非晶硅太阳能电池及制造方法的说明分析.rar
gcc 内联汇编官方手册最新版 ThisHOWTOexplainstheuseandusageoftheinlineassemblyfeatureprovidedbyGCC.
网络游戏-基于浮点数运算内联函数库的神经网络优化方法.zip
内联汇编2.rar
行业资料-电子功用-内联式超薄弱光型非晶硅光电池生产线的说明分析.rar
在Visual_C++中使用内联汇编 本文档主要详细介绍如何在c/c++代码内涵汇编代码,推荐给学习c/c++的同学们下载
行业资料-电子功用-内联式低内压高电位输出镍氢动力蓄电池及其制备的说明分析.rar