能力值:
( LV2,RANK:10 )
|
-
-
26 楼
|
能力值:
( LV2,RANK:10 )
|
-
-
27 楼
Originally posted by dwing 除极为复杂的算法程序外,一般的条件转移和循环VC都能有效地优化. 而类似lea eax,[eax]这样的指令也是故意安排的,使下面的指令被对齐.以利于指令cache充分地装入指令流.
除非汇编水平极高的人外,VC以最短代码方式编译比手工写汇编可能更短. 我发现许多人喜欢这样写程序: ........
我认为不见得如你所说的:
push 压入的是立即数 ,指令长 16位;但是 push压入立即数 时钟周期是 1(如果压入内存是2);
lea 内存和寄存器 时钟周期都是 1,xor 寄存器是 1, 异或其余的是2和3,但是像上面那样 索引寄存器变址的复杂寻址模式,将受到速度惩罚;
push 压入寄存器 时钟也是 1;
这样来比压入立即数和压入寄存器CPU的速度是一样的,但问题是 你的那个多了一个鸡肋 xor;
这样从代码来看,压入立即数 共花了 3个时钟周期,你的压入寄存器却花了十几个时钟周期; 你的不但没有"优化"快,反而"优化"慢了,还增加了阅读难度,我认为这是多此一举的优化(俗话说就是制造垃圾)
另外,只有数据对齐和指令配对(U-管道和V-管道),至于指令对齐一说,我还是孤弱寡闻。
lea eax,[eax] \ push eax, 和 xor eax, eax \ push eax 这两本身就是AGI延迟地址互锁(通常在前面的指令或是指令对运行的时候它已经在流水线上计算好了. 但是如果地址的计算倚赖上个时钟周期的运行结果的话, 你就需要额外时钟周期来等待地址的计算. 这就叫做AGI延迟)
|
能力值:
(RANK:170 )
|
-
-
28 楼
最初由 dwing 发布 [CODE] // Release方式编译,结果是1KB的可执行程序 #pragma comment(linker,"/MERGE:.data=.text") #pragma comment(linker,"/MERGE:.rdata=.text") #pragma comment(linker,"/ENTRY:main") ........
tst2.obj : warning LNK4229: 遇到无效的指令“/OPT:NOWIN98”;已将其忽略
LINK : warning LNK4078: 找到多个“.text”节,它们具有不同的属性(C0000040)
编译倒是过去了,但是两个warning,hehe
|
能力值:
( LV4,RANK:50 )
|
-
-
29 楼
最初由 Aker 发布 tst2.obj : warning LNK4229: 遇到无效的指令“/OPT:NOWIN98”;已将其忽略 LINK : warning LNK4078: 找到多个“.text”节,它们具有不同的属性(C0000040)
编译倒是过去了,但是两个warning,hehe
"/OPT:NOWIN98"只在VC6上起作用,不用VC6的去掉这句.
然后在最前面加上下面这句就没警告了:
#pragma comment(linker,"/SECTION:.text,RWCE")
|
能力值:
( LV4,RANK:50 )
|
-
-
30 楼
最初由 Ivanov 发布 push 压入的是立即数 ,指令长 16位;但是 push压入立即数 时钟周期是 1(如果压入内存是2);
lea 内存和寄存器 时钟周期都是 1,xor 寄存器是 1, 异或其余的是2和3,但是像上面那样 索引寄存器变址的复杂寻址模式,将受到速度惩罚; push 压入寄存器 时钟也是 1;
这样来比压入立即数和压入寄存器CPU的速度是一样的,但问题是 你的那个多了一个鸡肋 xor; 这样从代码来看,压入立即数 共花了 3个时钟周期,你的压入寄存器却花了十几个时钟周期; 你的不但没有"优化"快,反而"优化"慢了,还增加了阅读难度,我认为这是多此一举的优化(俗话说就是制造垃圾)
你说的不错,但那两段程序比较的是"最短代码方式",不是"最快速度方式".
遇到lea eax,[eax]这样的指令可以发现下面的指令的地址是一个地址边界的开始处,而且会有指令会跳转到此处.这样的循环就会少用一个指令cache块,以提高cache使用率.
|
|
|