汇编代码插入c++代码及函数效率比较

在c++中调用汇编代码用两种方法:内联调用和函数调用。

内联调用省去了参数压入栈和保存、还原寄存器的开销,提高了程序的效率,也比较简单安全,缺点是每次都要重新插入汇编代码。我用的编译器Virtual Stdio 2008使用 __asm保留字实现内联汇编。

函数调用比较复杂,具体来说,首先在汇编器中设计好原始的汇编代码,要求是:

一、使用 .model flat,C

二、对函数具有正确的原型声明

三、汇编代码中的函数名就是c++中调用所需的函数名

之后需要用汇编器将源文件编译为目标文件(.obj),加入到Virtual Stdio 2008的项目中,如图

图片

其中ASMlenthOfString.obj就是一个目标文件,它已经加入到了一个Virtual Stdio 2008项目中了

然后需要建立一个头文件,并在其中进行外部引用说明,然后让需要调用这段汇编代码的源文件包含这个头文件就大功告成了,具体步骤稍后说明。

下面的这个程序是调用了一个统计C风格字符串的长度的汇编过程,并将它的效率和C标准库“string.h”自带的strlen()函数的效率进行比较,程序中使用的是std::strlen(),即加入了std命名空间的strlen,它被包含在库“cstring”中。

具体测试的内容是让两个函数分别统计长度从16776216 到16777216 的1000个C风格字符串的大小,并将所用的总时间以毫秒为单位输出。

前段时间写过两个汇编版本的C风格字符串长度统计,今天发现效率都不高,又重新写了一个,总体而言,今天的版本效率如果是1的话,之前的版本效率在53%左右。

内联版本:

#include <memory.h>

#include <cstring>

#include <iostream> 

#include <ctime>

 

#define ARRAY_SIZE 16777216

#define START_POINT 16776216

#define TEST_TIMES 1;

char ap[ARRAY_SIZE]={" "};

std::clock_t start_time,end_time,total;

unsigned long len,i;

int main()

{ 

   memset(ap,'1',START_POINT);

   std::cout<<"Now we test c++ function."<<std::endl;

   total=0;

   for (i=START_POINT; i!=ARRAY_SIZE-2; ++i)

   {

     ap[i]='1';

     start_time=std::clock();

     len=std::strlen(ap);

     end_time=std::clock();

     total+=end_time-start_time;

   }

   std::cout<<"It cost "<<total<<"ms."<<std::endl;

   std::cout<<"Now we test ASM procedure."<<std::endl;

   total=0;

   memset(ap+START_POINT,0,ARRAY_SIZE-START_POINT);

   for (i=START_POINT; i!=ARRAY_SIZE-2; ++i)

   {

     ap[i]='1';

     start_time=std::clock();

    __asm

    {

      mov         esi,offset ap

      lea         edx,[esi+1] 

      L: mov         al,byte ptr [esi] 

      inc         esi

      test        al,al 

      jne         L

      sub         esi,edx

      mov         len,esi

    }

    end_time=std::clock();

    total+=end_time-start_time;

    }

  std::cout<<"It cost "<<total<<"ms."<<std::endl;;

 

  return 0;

}

 

一组测试结果如下:

图片

经过多组测试发现,本例中c++标准库和内联的汇编代码效率基本不相上下

非内联版本需要三个文件:

main.cpp:

#include "header.h"

#include <memory.h>

#include <cstring>

#include <iostream>

#include <ctime>

 

#define ARRAY_SIZE 16777216

#define START_POINT 16776216

#define TEST_TIMES 1;

char ap[ARRAY_SIZE]={" "};

std::clock_t start_time,end_time,total;

unsigned long len,i;

int main()

{ 

  memset(ap,'1',START_POINT);

  std::cout<<"Now we test c++ function."<<std::endl;

  total=0;

  for (i=START_POINT; i!=ARRAY_SIZE-2; ++i)

  {

    ap[i]='1';

    start_time=std::clock();

    len=std::strlen(ap);

    end_time=std::clock();

    total+=end_time-start_time;

  }

  std::cout<<"It cost "<<total<<"ms."<<std::endl;

  std::cout<<"Now we test ASM procedure."<<std::endl;

  total=0;

  memset(ap+START_POINT,0,ARRAY_SIZE-START_POINT);

  for (i=START_POINT; i!=ARRAY_SIZE-2; ++i)

  {

    ap[i]='1';

    start_time=std::clock();

    len=lenthOfString(ap);

    end_time=std::clock();

    total+=end_time-start_time;

  }

  std::cout<<"It cost "<<total<<"ms."<<std::endl;;

 

  return 0;

}


header.h:只有一行代码

extern "C" unsigned long lenthOfString(char string[]);

ASMLengthOfString.obj:它是由ASMLengthOfString.asm编译而成

ASMLengthOfString.asm原文

Title Length Of String

.386

.model flat,C

 

lenthOfString proto,

 string:ptr byte

.code

lenthOfString proc uses ecx esi,;it will change flag,ecx,esi

 string:ptr byte

mov         esi,string

lea         edx,[esi+1] 

L: mov         al,byte ptr [esi] 

inc         esi

test        al,al 

jne         L

sub         esi,edx

mov         eax,esi

 

ret

lenthOfString endp

end 

 这些都弄好后就可以调用了,其中一组测试结果如下:

图片

多组测试发现外部调用的话效率反而略高。

分析:

一、外部调用效率有时更高的原因,估计是cpu检测到这段代码被大量调用,于是将其存入cpu高速缓存中提高了速度

二、

repne scasb

的效率远低于

L: mov         al,byte ptr [esi] 

 inc         esi

 test        al,al 

 jne         L

下面的代码有4条指令,上面只有1条指令,效率却是上边的代码将近两倍。原因可能是

1、repne和scasb本身效率就低,如果是这样的话,Intel公司推出这两条指令莫非只是为了减少内存占用而拖慢了CPU????

2、虽然下边的指令数较多,但考虑到我电脑的CPU有四条流水线,CPU将工作平分给四条流水线,反而让效率增长不少。

我CPU型号是Intel Core(TM)2 Duo Cpu P7450

和这个问题相似的还有,lodsb的效率不如mov+inc组合来的高


以上两个问题还望高手指点。


三、通过比较发现,C标准库中的函数与直接汇编代码效率几乎不相上下,这说明,C或C++标准库中的一些函数是经过了汇编级别的精心优化的,因此调用库函数的效率往往非常高。


以上。

转载于:https://www.cnblogs.com/huanyan/archive/2010/10/22/1858791.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值