`
deepfuture
  • 浏览: 4400675 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
博客专栏
073ec2a9-85b7-3ebf-a3bb-c6361e6c6f64
SQLite源码剖析
浏览量:80078
1591c4b8-62f1-3d3e-9551-25c77465da96
WIN32汇编语言学习应用...
浏览量:70056
F5390db6-59dd-338f-ba18-4e93943ff06a
神奇的perl
浏览量:103363
Dac44363-8a80-3836-99aa-f7b7780fa6e2
lucene等搜索引擎解析...
浏览量:285833
Ec49a563-4109-3c69-9c83-8f6d068ba113
深入lucene3.5源码...
浏览量:15014
9b99bfc2-19c2-3346-9100-7f8879c731ce
VB.NET并行与分布式编...
浏览量:67577
B1db2af3-06b3-35bb-ac08-59ff2d1324b4
silverlight 5...
浏览量:32155
4a56b548-ab3d-35af-a984-e0781d142c23
算法下午茶系列
浏览量:45992
社区版块
存档分类
最新评论

算法下午茶系列-重温汇编(5)[内联汇编(1)]

 
阅读更多

内联汇编的重要性体现在它能够灵活操作,而且可以使其输出通过 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

     不使用全局变量与汇编代码交互,我们必须使用扩展GNU的asm ,格式为:

      asm("汇编代码":输出位置:输入位置:改动的寄存器列表)   

       汇编代码中涉及寄存器部分的使用2个“%”,如:使用%%eax表示eax寄存器

       输出位置、输入位置的特殊命名规则为:

      a为eax,ax,al;b为ebx等;c为ecx等;d为edx等;S为esi或si;D为edi或di   

      +读和写

      =写

      %如果必要,操作数可以和下一个操作数切换

      &在内联函数完成之前,可以删除或重新使用操作数

    上述代码中,汇编代码部分为

 

 

    输出位置、输入位置、改动的寄存器列表部分为:
     :"=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属于需要改动的寄存器

 

如果转载请注明来源,如有错误之处,请及时指出
分享到:
评论

相关推荐

    asm.rar_vb.net 内联汇编_内联汇编插件

    1. 引入`Microsoft.VisualBasic.CompilerServices`命名空间,它包含了`IntrinsicFunction`类,这个类可以用于调用内联汇编。 2. 使用`&lt;DllImport&gt;`特性来导入包含内联汇编代码的动态链接库(DLL)。 3. 在适当的位置...

    NEON编程-优化心得及内联汇编使用心得1

    - **内联汇编**:在C/C++代码中嵌入汇编语句,简化了代码调用,但格式复杂,且跨平台移植性较差。例如,使用`asm volatile`关键字插入内联汇编代码,可以更直接地控制NEON指令的执行。 在使用NEON编程时,需要注意...

    cpp-ARMGCC内联汇编参考手册中文版

    1. **性能优化**:对于计算密集型的算法,汇编可以实现比C/C++更高效的代码。 2. **硬件接口**:直接操作GPIO、中断控制器等硬件寄存器。 3. **原子操作**:在多线程环境中,内联汇编可以实现无锁数据结构或原子操作...

    ARM GCC 内联汇编参考手册

    ### ARM GCC 内联汇编参考手册解析 #### 关键知识点概述 本手册主要介绍了如何在C语言中使用GCC提供的内联汇编功能来编写针对ARM架构的代码。内联汇编是一种强大的技术,允许开发者在C代码中插入低级汇编指令,...

    易语言学习-WonderWall内联汇编支持库(11-28).zip

    在易语言学习-WonderWall内联汇编支持库(11-28)的压缩包中,可能包含了一系列教程、示例代码、文档等资源,涵盖了从基础到进阶的内联汇编使用方法。这些资料将引导学习者逐步了解和掌握如何在易语言中插入汇编代码...

    vc内联汇编示例代码.zip.rar_VC 汇编_内联汇编

    vc内联汇编示例代码,介绍了VC++的一些被封装的汇编代码,有愿意深入了解VC++的人请进

    VC内联汇编资料 VC内联汇编资料

    3. **优化代码**:对于某些难以用高级语言表达的算法,内联汇编可以提供更直接的实现方式。 三、内联汇编的限制与挑战 1. **可移植性差**:内联汇编高度依赖于特定的处理器架构,代码不适用于其他平台。 2. **维护...

    C++内联汇编示例

    本工程通过一系列示例,展示了如何在C++程序中使用内联汇编来实现函数调用、参数传递、循环以及条件判断。 首先,我们来看"Less1"这个示例。在这个例子中,开发者可能用内联汇编来演示如何手动管理函数调用的过程。...

    gcc内联汇编手册

    ### gcc内联汇编手册知识点解析 #### 一、引言与版权许可 - **版权与许可**:本文档由Sandeep S.撰写并享有版权(2003年)。文档遵循GNU通用公共许可协议发布,允许自由再分发与修改。版权许可基于GNU通用公共许可...

    在Visual_C++中使用内联汇编

    1. **可移植性差**:由于不同的处理器架构有不同的汇编指令集,因此内联汇编代码通常只适用于特定的处理器架构。 2. **维护困难**:汇编语言相对于高级语言来说较为复杂,难以阅读和维护。 3. **开发难度大**:需要...

    易语言置入代码内联汇编

    "减法1, 加法1, 乘法1, 除法1"是内联汇编中常见的算术运算,这些基本运算在易语言中可能通过简单的函数调用就能完成,但使用内联汇编可以实现更高效的计算,尤其是对于大量重复的计算操作,汇编的执行速度通常优于...

    内联汇编2.rar

    标签"内联汇编2.rar内联汇编2.rar"重复了标题,进一步强调了内联汇编的主题,可能表示这是一个系列的第二个部分,涵盖更多的主题或更深入的探讨。 压缩包内的文件名称列表如下: 1. 说明.htm:这可能是一个HTML文档...

    IBM内联汇编指导

    IBM内联汇编指导主要介绍的是如何使用IBM XLC/C++编译器在IBM z系统Linux平台上进行内联汇编编程,以提升应用程序性能。在文章中,作者Anh Tuyen Tran提供了对内联汇编基础知识的深入讲解,并指出了该技术的优势和...

    论文研究-一种多态内联代码混淆算法.pdf

    针对软件代码混淆算法中的内联方法存在混淆结果单一性问题,提出了一种多态内联代码混淆算法。基于有限状态自动机(FSM)建立了算法理论模型,对每个内联的方法体选择差异性的混淆实现,并通过理论分析说明了提出的...

    GCC内联汇编入门(中文版)

    GCC内联汇编入门 GCC内联汇编是GCC编译器提供的一种功能强大的特性,它允许开发者在C语言中嵌入汇编代码,从而提高程序的执行效率和性能。本文将详细介绍GCC内联汇编的使用方法和原理。 GCC内联汇编的基本概念 ...

    易语言置入代码内联汇编源码

    1. **了解基础汇编指令**:首先需要掌握汇编语言的基本指令,如数据传输、算术运算、逻辑运算、跳转指令等,这些是编写内联汇编的基础。 2. **内联汇编语法**:易语言中的内联汇编有其特定的语法结构,需要熟悉如何...

    GCC内联汇编, PDF 格式

    ### GCC内联汇编知识点详解 #### 一、GCC内联汇编概述 **GCC内联汇编**是一种特殊的编程技术,允许开发人员在C/C++程序中直接嵌入汇编代码片段。这种方式有助于实现高性能的系统级编程,特别是在需要精确控制硬件...

    GCC内联汇编入门[参照].pdf

    5. 基本内联汇编(basic inline assembly):指C语言中内联汇编程序的一种形式,和extended asm对应。 6. 扩展内联汇编(extended assembly):和基本内联汇编对应,比它多了一些特性,如可以指明输入、输出等。 ...

    在 Visual C++ 中使用内联汇编

    在Visual C++中使用内联汇编是一种高级编程技术,它允许程序员在C/C++代码中直接嵌入汇编指令,从而实现更底层的控制和优化。以下是对该主题的详细解析,涵盖其优势、使用场景、关键字及具体用法等。 ### 一、内联...

Global site tag (gtag.js) - Google Analytics