0xAA55 发表于 2017-3-22 06:35:45

【汇编】一张图描述汇编执行的执行效率受到什么因素的影响。

直到现在都有很多人认为自己写的内联汇编的运行效率比编译器生成的指令效率高,但事实上你除非能巧妙应用高级指令集,否则只能起反效果。不少人认为写C用short、WORD比用long、DWORD效率更高,但事实上现在的桌面用机CPU至少都是32位,写入一个short或者char、BYTE到内存,需要经过多步操作才能完成——先读取一个32bit整数,然后把其中指定的部分修改为我们的short或者char,然后再将做好的32位整数写入内存。编程的时候,不要捡了芝麻丢了西瓜,这些细节的指令优化并不能拯救你的程序的运行效率或者内存使用状况。一个典型的例子就是,当你打算操作某个字节的某个bit的时候,你必须先读取这个字节,然后用and或者or来设置某些bit的值,再把它写回内存。同理你CPU操作一个Byte也是需要先读取一个DWORD(或者QWORD,就算是16bit模式至少也是WORD),进行and或者or的操作后,才能存回内存。事实上你就算看不到它有这样的操作,CPU内部也是这样做的。因为DDR内存中的数据本身就不是按bit、byte来寻址的。

真正的优化方向应该先从算法优化上做起,系统地管理你的资源的使用情况,把其它进程对CPU、内存资源和硬盘的使用也考虑在内,才是可取的做法。不少人为了去掉call指令的调用过程而强制展开程序,导致整个程序编译出来的二进制长度过长,超出了CPU的缓存能力,反而导致程序的运行效率的降低——明明是4GHz的CPU,这程序偏只能跑到内存频率的速度(667 MHz),实在是既降低了开发效率又降低了执行效率。而这些开发者自己却沾沾自喜,认为自己的程序天下无双快!(毕竟自以为没有call指令这种“无用的”跳转,效率“肯定”能得到提升)

CPU运行的指令(此处特指x86),速度到底怎么看?请看下图。并不是说我少占用点内存它效率就能上去的。



如何才能让数据不跨16字节边界呢?通常C语言编译器会自动把你的数据安排为32bit对齐的位置,尤其是栈上的变量更是如此(每次push、pop操作,对内存的改动都是等于你的位数的,而且sp、esp、rsp也是对齐的)。而对于堆上的玩意儿,C11有aligned_alloc这种玩意儿(微软比较二,他们给的函数是“_aligned_malloc”,虽然用法一样,但函数名字不太一样),使用它就能在堆上分配到对齐了的buffer。

对于多线程操作,你可能会非常依赖内存对齐了的变量,因为各种原子操作都只对对齐了的变量有作用。(哦对了提示一下不知道原子操作的朋友们请看上面的图,里面所说的“lock前缀”就是这玩意儿了。)

Ayala 发表于 2017-3-22 12:14:25

本帖最后由 Ayala 于 2017-3-22 12:24 编辑

只考虑指令速度
那么比较下 下面4组哪个更快
mov al,byte ptr    mov eax,
mov al,byte ptr    mov eax,


mov byte ptr ,al      mov ,eax
mov byte ptr ,al    mov ,eax






0xAA55 发表于 2018-5-28 06:20:28

Ayala 发表于 2017-3-22 12:14
只考虑指令速度
那么比较下 下面4组哪个更快
mov al,byte ptr    mov eax,


mov eax,
页: [1]
查看完整版本: 【汇编】一张图描述汇编执行的执行效率受到什么因素的影响。