引用 写给想用汇编优化程序的程序员朋友们

来源:互联网 发布:mac 窗口跨两屏幕 编辑:程序博客网 时间:2024/05/10 09:16
 本文转自:http://saturnman.blog.163.com/blog/static/557611201083014829361/

 我是引用别人的文章,但是也谈一点自己的看法。我有些观点是与作者不同的。

1. 在现在的这个时代,学习汇编的主要目地是能读得懂汇率代码,这对于理解系统底层的工作机制有好处,而了解底层的软件工程师更易于写出高效的代码。

2.编译理论已经发展几十年,想用汇编来优化代码运行速度几乎是不可能的,编译器知道对于什么平台生成什么优化的代码,先择什么样的优化策略,编译器也知道什么部分的代码永远不会运行到,什么地方代码就算运行也不会有影响而直接去掉,这些都是非人力所能及的,而且汇编也有很强的平台相关性,这里正确的那里就不对了,用C/C++写高效的代码是实际的做法。

3.不要尝试以汇编来完全了解底层,今天这样可能明天就不这样了,但是上层的接口不会变,对于那些想通过精通汇编而成为大神的人哥可以直接告诉你这是行不通的。

令本人还有一点对于汇编的看法写于下面:

http://saturnman.blog.163.com/blog/static/557611201083015658711/

引用

Gamebaby Rock Sun  写给想用汇编优化程序的程序员朋友们
 

记得是在2003年,偶还在西安的时候,写了几篇关于VC内联汇编的文章,发到了www.vckbase.com网站上(现在已经转会我的博客)。从那以后,时不时总有一些网友就加我的QQ,然后疯狂问我关于使用汇编的各种问题。2010年了,还有网友在问,现在偶也开了博客,算是一个交流的平台,毕竟QQ的聊天记录不能保存很长时间,而且有些问题也不是QQ聊天就能说清楚的,所以今天就写这么篇文章为初学者,或者想用汇编优化程序的网友回答一些共性基础性的问题。当然我的目的是为了“授人以渔”,而不是“授人以鱼”,因此注重的是教大家如何自己找到解决问题的方法。很多时候学会寻求帮助也是一种技能。

不知不觉已经是Windows 7的时代了,CPU都是n核了,传说中Intel都搞了48核的CPU给其伙伴用于改进软件的并发特性。现在的PC机,性能已经高到用夸张都无法形容的地步,但是人们依然在抱怨为什么电脑还是会越来越慢,优化似乎成了程序界的永恒话题,就像是电影电视中反复出现的爱情主旋律一样。

提到优化,很多搞C/C++甚至VC的网友,第一个反应就是用汇编,其实,这是一种错误的认识,或者说一个错误的开始。很多时候由于编译器的优秀优化策略(严格讲叫更有效的代码生成),实际最终生成的汇编代码性能已经很令人满意了,有些性能甚至超过了自己手工编写的汇编代码。

在MSDN中,关于内联汇编,有一段很有意思的说明,大意就是对于内联的汇编代码,VC的编译器就不在做任何优化了,只是翻译为等价的机器码程序,对于代码的效率和性能则完全有编写者负责,同时提醒编写者,在没有十足的把握下,不要轻易使用内联汇编,但是内联汇编的编译速度是非常快的。

对于VC的编译器来说,并不是像很多公版C/C++编译器那样先将源代码编译成等价汇编码然后再汇编成机器码,VC的编译器是直接生成机器码的(对于托管代码是个例外,本文不讨论托管代码,有理论认为编译器直接生成机器码,比先生成汇编,再由汇编器生成机器码,可以得到更高效的可执行代码段,详情请参看编译原理相关的专著),同时VC代码生成优化是很出色的,当然指在X86/X64平台上。就在最近,在分析一个语句的等价汇编时,我无意中发现了VC生成下面的汇编:

原语句:x = x?0xff:0;

生成的等价汇编:

movsx       eax,byte ptr [x]

neg         eax 

sbb         eax,eax

and         eax,0FFh

mov         byte ptr [x],al

当时看到这段汇编时,我除了感叹还是感叹,曾几何时,我一直以为问号表达式会产生跳转指令,当这段汇编出现在我的眼前时,心中那难以抑制的惊叹却无法再用语言描述。巧妙!厉害!我想若是我来直接优化这个问号表达式时,是无论如何也想不到不用跳转指令如何做到的,这个思维的囹圄,瞬间就被这段汇编化作了乌有。这里我不打算详细解释这几个指令的含义,因为它们既熟悉又陌生,大家可以自己搜索下资料,深刻体会下这里算法改进的精要。

写到这里,其实我本意不是说有了这么优秀的VC编译器,就不用再自己使用汇编优化了,相反,我给出的例子,其实是一个用汇编优化算法的典范。更是鼓励大家,朝这个方向努力。什么方向呢?就是从算法逻辑的角度入手用汇编来优化你的程序。

很多时候,有些所谓的汇编优化并不是优化,只是简单的将我们熟悉的C/C++程序翻译为等价的汇编了事,甚至有时候这种翻译还不如编译器的翻译高效。而我要说的就是,真正的汇编优化应当从程序的结构入手,从算法和逻辑的角度入手,直接用汇编来思考问题,也就是:Think in assemble language!并充分利用汇编语言自身的优点。

这里提供几个参考的思路:

1、利用指令本身的强悍运算优势,因为很多的运算指令在高级语言中大多数是被丢失的,比如移位运算,位运算等,除了C/C++等少数几种语言还有这个运算外,其它的一些语言中是没有的,而移位运算的优点就是我们可以利用它来快速实现2的n此方的乘除法,具体实现就去看相应的二进制算法书。如果你不知道CPU本质只是一个能够高速计算加法的笨蛋的话,那么建议你还是不要玩汇编了,珍惜生命,远离汇编!比如:我们可以利用FPU的指令:FSIN,FCOS等来直接得到正弦、余弦,甚至用F2XM1指令来高速计算2的n此方-1的值。再有就是可以考虑充分利用SSE等系列扩展指令的优点去改进你的运算。

2、熟悉常用的数值算法,根据算法选择合适的汇编指令直接加以实现。因为CPU的设计者的一个重要目标就是让CPU具有强悍的计算能力,这就是计算机这个名字的本身含义,所以他们已经在CPU中固化了很多常用数值算法的子程序集,并作为指令直接提供出来,你要做的就是直接调用这些子程序编写和实现你自己的具体的算法程序,比如前面提到的FSIN指令就是一个正弦函数运算的子程序,不要说你连正弦运算是干嘛的都不知道哈,那你就真的要转行了,呵呵呵。

3、不要用计算的定义去实现某个运算,而是用那些经院学家实现的算法来实现你的计算,比如最常见的计算阶乘的算法,甚至有些算法书中拿它来做递归函数的经典例子程序,而我要告诉你的就是如果你真的用阶乘的定义去计算阶乘的话,呵呵呵,你就是个不适宜搞计算机程序的人,为什么这么夸张呢?因为阶乘超过一定数的阶乘之后,用那个连乘的定义已经无法计算了,因为你的寄存器最大只能表示64位的一个整数,而这个数对于阶乘来说,只是个小的可怜的位数,很快你就会发现,这个算法不但耗时,而且结果只能保证一些比较小的数才能用,数一大了,这个算法基本无效了。而你作为一个程序员,连这个起码的问题都心中无数,那真的不用搞程序了。而替代的你应该使用“斯特林”公式(谷歌?百度!)及改进的高精度算法,快速高效的算出一个数的阶乘,具体的算法和公式去谷歌百度,此时我的任何语言描述都是多余的。当然搜索完了,知道了这个世界上还有这么个神奇的算法,先不要为你的无知而惊叹,而是老老实实的买一本数值分析方面的书带在你的身边吧。当然乍一看这个问题跟汇编有毛关系啊?其实你知道了斯特林公式,而又能够充分利用CPU的指令实现它的话,这才是真正讨论这个话题的目的。让你明白汇编优化不只是简单的翻译等价的C/C++源代码为汇编这么简单。汇编不是高级语言的附庸!它才是真正的计算机语言!

       以上的建议其实贯穿起来就是一句话,首先,熟悉汇编、起码了解大多数指令、其次明白算法,并知道算法的具体内容,最后就是知道怎么找到最好的算法然后再用汇编去实现。这才是使用汇编优化的王道。

如果你现在还停留在那种翻译C/C++源代码为等价汇编的层次,并为此而沾沾自喜的话,那么建议你还是静下心来好好的补补汇编吧。汇编优化不是让你用add指令代替+运算符这么简单!

这样我们就又讨论到如何学好汇编,打好汇编基础的这个问题上来,所谓:工欲善其事必先利其器,那么汇编的器是什么呢?就是汇编的IDE,也许你早知道了MASM甚至你还记得那个TASM,但是你也知道在这个窗口应用IDE环境大行其道的今天,这种基于命令行的工具除了使问题趋向复杂化之外,似乎没什么优势了。别急,现在就告诉你一款非常非常好用的汇编IDE环境——RadASM,它非常的出色和优秀,比起那个VC6.0来说,一点也不逊色,用它写汇编,就是一个爽!最新的版本似乎是2.2.1.9,赶紧去搜索下载、安装吧。而且有汉化版的哦!

有了工具,那么是不是就可以学好汇编呢?非也,非也!你还需要看很多东西,学习很多技能。

首先你要知道一个网站——罗云彬的编程乐园(http://www.win32asm.com.cn/),不过貌似目前他的网站在备案当中,所以暂时关闭了,不过你可以搜索到很多他写的汇编资料。通过这些你主要需要掌握的就是如何用纯Win32汇编实现一个应用程序,更重要的是掌握如何用纯Win32汇编实现一个DLL,当然除了这些,你还需要掌握如何编写一个纯汇编的模块,与VC编译出来的obj文件一起链接出你的Exe、DLL甚至ocx,当然你可以不用这么辛苦,干脆只掌握VC中的内联汇编即可,相关资料可以在我的博客中找到。

其次,你要去Intel的网站下载最新的汇编指令参考手册(当然这个最好是你定期就去搜搜看,这个手册不时都会有更新),这个手册很重要(真的、真的很重要,它里面的内容是你用来为难你的老师最好的武器),它里面有最最全面的关于X86/X64系列CPU(包括兼容CPU,主要指AMD的CPU)的所有指令,下载的方法就是首先到www.intel.com的首页,在搜索的窗口中输入Software Developer’s Manual,然后在结果中找到Intel? 64 and IA-32 Architectures Software Developer’s Manual,点击链接下载即可,或者点击[More results fromwww.intel.com/design/processor/manuals],查看完整的列表,这套手册以供有3卷,分为5册,第一卷是基础,可以认为是Intel系列CPU汇编绝世武功的目录,而第二卷是指令的详细参考,详细的描述了每个指令的格式、操作数类型、算法、影响的寄存器、以及可能引起的异常等,这卷分为A、B两册,而第三卷也分为A、B两册,主要是为有志于开发操作系统和编译器的程序员准备的,详细的描述了Intel系列CPU关于系统管理架构等方面的各种信息,同时还有Intel机器指令格式等的详细信息,当然这一卷如果你有兴趣的话,可以深入的看看,对于理解硬件级的内存管理、IO操作等等非常有帮助,也是你能够深入理解和掌握Windows操作系统的完全基础。

当然如果你说你的英文不好的话,那我奉劝你要么转行,要么就硬啃,没有别的办法了,我就是再能耐也没办法让你瞬间就能看懂英文,其实我的英文也是硬啃下来的,在这里要特别感谢开发了金山词霸的程序员兄弟们,没有你们,没有金山词霸,就没有我现在的英文水平,当然我还要感谢薄冰先生,没有他的英语语法书,单靠金山词霸,想看懂这些英文专著,是几乎不可能完成的任务。当然说这些就是告诉你,去买薄冰的英语语法书,安装金山词霸,开始你的英文阅读之旅。Just do it!

最后众所周知像如此重要的文献资料,国内一般都是没有翻译版的,真正有用的东西那些翻译者是不会去费心费力为你服务的,呵呵呵。所以你不要痴心妄想着那个人帮你把这个翻译出来,你再去看,这套资料算来我已经接触了有5-6个年头了吧,我手头都有很多它的不同时期的版本,但直到现在,很少见有人翻译它,更少见有人介绍它,甚至连讨论它的信息都很少见,实在是一件让我不知道说什么好的事情,所以这也是我特别在这里介绍这套资料的缘故。在这套书的面前,Windows系统甚至VC++编译器本身对你来说就没有什么秘密可言了,你要做的就是阅读之,参考之,学习之,实践之!

最后,你需要的就是下一番苦功夫,练好汇编,当然这不是一朝一夕之功,如何练,如何学习,那就是我在前一篇写给初学者文章中的:多看看书、多看看代码、多写写代码了。除此,别无第二法门。

当然如果你的汇编练到一定程度,可以考虑向编写系统工具,编写驱动程序,编写嵌入式系统、编写木马、病毒、外挂等方向发展,这些都是很有钱途的职业方向,但最终这个就看你自己的兴趣爱好了。我始终相信这个世界上没有卑鄙的事情,只有卑鄙的人!所以做什么事情不重要,重要的是你是一个什么样的人。但是千万别想着去写操作系统,因为这不是你一个人就可以完成的任务,我曾为此至少荒废了3年时间,呵呵呵。

原创粉丝点击