快速业务通道

关于内联汇编的几个技巧

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29

有时我们的程序需要一些很高的执行效率或者执行系统底层的功能模块,这些关键的部分我们可以采用内联汇编直接插入汇编指令来达到我们的要求,以下是几个技巧与大家共同探讨.

1.内联汇编嵌入VC语句:

在VC中内联汇编非常方便,只需要按照如下格式

__asm{

//汇编语句

}

请看如下示例代码

void CAlcmemDlg::OnButton3()
{
  DWORD d=(m_size*1024*1024)/sizeof(DWORD);
  DWORD*p=(DWORD*)m_p;
  DWORD s;
  m_pr.SetMin(0);
  m_pr.SetMax((float)d);
  m_pr.SetEnabled(TRUE);
  if(NULL!=m_p){
    __asm{
        mov ecx,d
        mov eax,0
L:        mov edx,DWORD ptr p
        mov [edx+eax],1  //随便写入数据,此处写入1
        inc eax
        mov s,eax
        pushad
    }
    m_pr.SetValue((float)s);
    __asm{
        popad
        loop L
    }
  }
}

请注意示例代码中两个__asm块中的pushad 和 popad 语句,pushad保存了寄存器环境,popad恢复了寄存器环境,使得m_pr.SetValue((float)s);语句对寄存器的影响被抵销,你还可以调用其他任何语句。但建议是尽量少打断内联汇编块,以减少运行时来回倒腾寄存器环境的时间。笔者的测试是,当删除m_pr.SetValue((float)s);并且合并两个__asm块,同时删除pushad,和popad后,速度明显提高。可见这种打断通常是得不偿失。

通常要保存的寄存器环境还有Flags寄存器等,这些视具体情况而定。

2.自由使用FPU,MMX等指令void CAlcmemDlg::OnButton4()
{
  float f_t=.132;
  float f_s=0;
  __asm{
    fld f_s
    fld f_s
    fld f_s
    fld f_t
    fadd f_t
    fst f_t
//    fadd fs
  }
}

可以利用设置断点的方法来观察FPU寄存器的情况,通常你用VC写的代码,不会被编译为引用特殊指令集的代码,虽然微软号称编译器支持这些指令。所以你必须用内联汇编方法来调用这些指令以优化程序,充分利用资源。示例中的代码调用了FPU处理器的指令,使操作浮点数的能力被充分发挥。但当然你还可以调用3DNOW!指令,SSE,SSE2等指令,但笔者没有试过,如果你有什么新的发现,还望赐教,再此先谢了!

总的来说内联汇编提高了速度,尤其是游戏编程,更应该努力使用内联汇编,把CPU充分榨干,但坏处就是有些低端的机器无法运行,兼容性差。同时微软又号称,编译器不会去优化你写的汇编码,他只是简单的翻译为等价的机器码,优化的事情交给你自己来完成,所以你不但得是C++高手,同时还得是汇编高手。不过据我所知这种人十有八九是黑客。我是不鼓励你成为那类人的,撰写此文只为抛砖引玉。

本文配套源码

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号