2013-11-22 39 views
0

我正在研究一些关于程序集和我正在阅读的材料,作者说在x86操作系统上编译为16位的程序旋转速度更慢,对于x64也是如此,对于x64,32位编译程序运行速度较慢...为什么在x86操作系统上运行16位程序会变慢?

这是为什么发生? 在计算机内存和处理器中会发生什么情况,以便程序的16位或32位机器分别以32位和64位的速度缓慢旋转?

+1

简短回答:因为CPU为最近构建的代码的优点进行了优化,代价是旧代码,旧代码。 –

回答

2

关于16在32位系统上运行较慢位程序,我可以告诉你这一点。 当Intel从16位变为32位时,他们不得不扩展指令集来处理新的32位寄存器,但保持与16位程序的二进制兼容性。

为了实现这个目标,如果我记得很清楚,他们添加了一个前缀66h,当应用于任何使用16位寄存器的指令时,使该指令使用32位寄存器。

例如,一个16位指令,如MOV AX,BX,以66H前缀,变成MOV EAX,EBX

但是,这则规定的罚款对新的32个指令,因为它们需要在至少需要一个额外的内存读取周期才能执行。然后英特尔创建了所谓的32位段和16位段。

基本上,任何一段代码都必须驻留在代码段中。在80386之前,所有段都使用16位指令,所有指令都假定使用16位寄存器。

Intel的32段也包含代码,但是这次每条指令都假定使用32位寄存器,所以在32位段中,MOV EAX,EBX的操作码与MOV AX的操作码相同,BX在16位段。

这允许程序不必为每个32位指令使用66h前缀。没有惩罚了。

但是...如果我必须在一个32位段的程序中使用16位寄存器,该怎么办?这些使用16位寄存器的指令必须使用前缀66h。

因此:使用16位寄存器的指令在16位段中前缀不固定,并且在32位半角前缀。使用32位寄存器的指令在32位段中前缀固定,并在16位段中前缀。另外:从奔腾处理器开始,我们有两条并行执行指令的管道。对于要使用的这些管道,进入它们的指令必须属于Intel命名为“RISC核心”的内容:指令的子集不再作为CPU内部的微程序执行,而是使用有线逻辑。你猜怎么了?前缀指令和使用16位寄存器在16位段中执行的代码不属于该组,因此不能与另一个并行执行。当前缀指令设法输入其中一条管道时,另一条流水线被阻塞,从而影响CPU的性能。

0

我不知道你所说的旋转的意思,但一般来说有可能是这里的几个因素(装配作业?) -

  1. CPU企业没有真正去支持的努力旧的遗留模式和ISA子集。 x87就是一个很好的例子,任何并不真正需要这种精确度的水平都会使用SSE/AVX进行性能关键任务,而不仅仅是因为矢量化。

  2. 每当x86 CPU公司增加它们的寄存器大小时,它们都保留旧的寄存器组,并为较长的版本添加逻辑名称。对兼容性的需求要求旧操作仍然可以在同一个寄存器上工作,因此现在可以在同一个程序中写入ah/al,ax,eax和rax。在这些情况中的一些情况下(即8位/ 16位部分),这种兼容性要求您的CPU在写入较低部分时保持寄存器的上半部分完好无损,这样做会隐式引入合并操作,这可能会导致减速。更糟糕的是,您可能会引入错误的依赖关系,因为每次写入16位寄存器都会要求您在上一部分操作的上半部分进行合并。

也在这里看到的 - Why do most x64 instructions zero the upper part of a 32 bit register

1

关于“程序旋转速度更慢”...呃...程序不“旋转”,而是“执行”。如果你正在谈论位旋转指令......那么。恰巧8086有两个版本的位循环指令:一个使用指定要旋转的位数的inmediate参数,另一个使用寄存器(通常是CX/ECX)来指定它。

问题是8086处理器不允许任何其他值为1的inmediate参数(但CX/ECX中的值可能大于1)。 80386及更高版本的处理器允许使用任何其他值作为中间操作数。此外,32位处理器仅使用指定旋转量的操作数的低5位,所以操作不超过31(将32位reigster旋转超过31次毫无意义)。 8086处理器不会强加此限制,因此需要花费更多时间进行操作。

我真的不知道这是不是你的书的意思是“旋转得更慢”。我记得旋转操作只能在其中一个管道中执行,而不能同时在两个管道中执行,因此两个连续的旋转指令不能配对。

相关问题