分享
 
 
 

Delphi与汇编杂谈(2)

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

初级优化篇

说到优化,很多人又不屑一顾了,“现在计算机速度都那么快了,再快那么百分之几有什么意义啊”。这么说确实有些道理,现在的编译器编译后的结果已经是充分优化过了,除了图形图像多媒体等特定软件的开发外、多数情况下刻意的优化确实没必要,但是如果开发人员在编写代码的时候已经具有了优化意识,在完成优化的同时,又能保证了甚至提升开发效率,何乐而不为呢?

当然,算法的设计都是优化的核心,绝大多数情况下,程序的执行效率高低主要由开发人员对程序整体把握,算法的设计等来决定!但有时候针对细节的优化也是有一定意义的!

而且这种优化在很多情况下也并不需要直接通过汇编来写代码实现,但这种情况下却也能体现出掌握汇编知识的优越性!

如下面两个函数:

function GetBit(i: Cardinal; n: Cardinal): Boolean;

begin

Result := Boolean((i shr n) and 1);

end;

function GetBit(i: Cardinal; n: Cardinal): Boolean;

begin

Result := Boolean((1 shl n) and i);

end;

对应的汇编代码:

MOV ECX, EDX

SHR EAX, CL

AND EAX, $01

MOV ECX, EDX

MOV EDX, $01

SHL EDX, CL

AND EAX, EDX

它们的作用一样,都是取i某位的值,为1返回True,0返回False!

表面上看可能都会认为两个函数的执行效率一样,实际上还是有区别的,第一段程序是的移位操作是对i进行的,按照Delphi中默认的调用约定register,此时的i的值是存在寄存器EAX中,移位操作可直接完成;而第二段程序则不同,要对立即数1完成移位操作,必须先将其传送到寄存器,由此也就必然多出一条指令!当然也不是所有情况下,指令少就一定比指令多要快,具体执行时还要考虑指令执行的时钟周期和指令的配对等问题(后面再介绍些),独立出来也说明不了问题,只有在具体代码环境中才好作比较。

一般情况下这种效率上的执行差异实在是太微不足道了,但在编程期间时刻保持着优化的意识绝不是件坏事!如果此类代码位于循环的最里层,N个时钟周期经过大量循环的累积,产生的执行效率差异也可能变的很大!

上面只是个很小的例子,由此可以看出在开发中如果能站在汇编的角度思考一些问题,能在保证开发效率的同时用高级语言编写出更有效率的细节代码!但还有很多时候,细节优化还要用使用嵌入汇编代码来完成,而且有些时候由于嵌入汇编代码应用,还能使代码编写变得更有效率。

如需要将一个32位数的字节顺序颠倒,在Delphi中,完全用高级语言实现怎么做?用移位可以,多次调用内建函数Swap也可以,但是如果想到一条BSWAP指令,这一切变得很简单。

function SwapLong(Value: Cardinal): Cardinal;

asm

BSWAP EAX

end;

注:同上,Value的值是存在寄存器EAX中,而32位数的值也通过EAX返回,所以只需要一句即可。

当然多数的嵌入汇编优化没有这么简单,不过通过大学里所学的那一点点汇编知识也很难做到更深入的优化,也只能通过不断的积累,对比编译后的汇编代码获取经验!好在多数情况下,细节优化并不是程序设计的主体。

但如果所开发程序涉及到图形图像多媒体等方面,还是有必要进行更深入的优化的!好在不管是浮点指令的优化还是应用MMX、SSE、3DNow等完成优化,Delphi6都能提供良好的支持。即使是想早期版本的Delphi支持这些CPU扩展指令集或者想要支持以后新的CPU指令集,利用Delphi在嵌入汇编中所支持的DB、DW、DD、DQ等四条汇编指令(在Borland的Delphi6官方语言手册里只说支持DB、DW、DD)插入相关指令的数值表示也能灵活的实现。

如:

DW $A20F //CPUID

DW $770F //EMMS

DB $0F, $6F, $C1 //MOVQ MM0, MM1

了解指令只是基础,在围绕FPU,MMX,SSE设计完算法后,想更深一步的进行优化,还必须了解一些CPU本身的技术特性。

先看看下面两段代码:

asm

ADD [a], ECX

ADD [b], EDX

end

asm

MOV EAX, [a]

MOV EBX, [b]

ADD EAX, ECX

ADD EBX, EDX

MOV [a], EAX

MOV [b], EBX

end

第二个效率高?错了,如上面说的,指令少不意味着执行效率高,查查相关资料可知,第一段代码的两条指令执行的时钟周期为3(每条指令都需要完成读、改、写三步),第二段代码中的6条指令执行的时钟周期都为1。那么说两段代码效率一样?又错了,实际上第二段代码执行效率比第一段代码要高!为什么?因为奔腾级以后的CPU都有两条流水线来执行指令,所以当相邻的两条指令能够完成配对,那么它们就能够同时执行!具体到上面的两段代码来说具体原因又是什么呢?

第一段代码中的两条指令虽然可以完成配对,但需要的总执行时钟周期为5而不是3,而第二段代码的六条指令可以两两之间并行执行,所以也就导致了这个结果。

说到这里,都是些很浅显的例子,本身给不了大家太多的帮助。如果真的想优化特定程序,还是找些FPU,MMX优化的专题文章看看,或者找来技术手册好好专研专研“乱序执行”和“分枝预测”等技术。只希望各位在上大学的朋友们不要只专注于那些“能赚钱”的开发工具和时髦的新技术,能把更多的时间花在打基础上,有了扎实的基础才能快速掌握新知识、才能用更快的时间掌握新的开发工具、才能...(省略一千字)。

不过话又说回来,知识还是要用来解决实际问题的,如果每天就只在技术细节上做文章,也许能成为一个出色的黑客,但绝对开发不出一流的软件。所以还是要以创造价值为根本目的。所以...不说了,再说下去就真不像技术文章了。^_^

附:程序优化除了考虑执行效率以外,当然也要考虑体积的问题(体积小才能更快的载入内存,更快的完成指令译码等工作),比如清空EAX寄存器都是用SUB EAX, EAX或XOR EAX, EAX而不会用MOV EAX, $0,虽然它们的执行时钟周期都是1,但前者的指令长度(2字节)明显比后者(5字节)短。但因为上面说的都是些细节,所以没提到体积的问题。更多的缩小体积的问题还是交给编译器去解决吧,在编写嵌入ASM代码的同时稍微注意一下就可以了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有