如何在机器级别实现的两个数字之间进行“比较”?

时间:2015-01-24 08:19:13

标签: java optimization assembly comparison low-level

首先,这个问题与for循环性能无关。这只是背景。

所以,我以某种方式发现,在使用Java时,对for循环进行倒计时要比计算循环快得多。我的意思是,for(int i=0; i < n; i++)for(int i=n-1; i >=0; i++)慢。 (是的,我知道过早优化是所有邪恶的根源,但我只是想找出原因)。所以,这让我觉得差异是因为cmp在机器级语言中的实现方式。关于本地编写compare函数的其中一个方法就是这样:

public int compare(int a, int b) {
  int diff = a-b;
  if(diff == 0) {
    return 0;
  }
  if(b ==0) {
    return((is MSD of a 1)?-1:1);
  }
  return(diff,0);
} 

我可以通过按位机大小右移数字来检查MSD位,看看它是1还是0.但是,即使这样,我也需要==。这将再次回到同样的问题。所以,我的问题是,在汇编或机器级别,<,>,==如何仅使用按位运算和jmp序列来实现?

2 个答案:

答案 0 :(得分:2)

  

for(int i=0; i < n; i++)for(int i=n-1; i >=0; i++)

不,不是。在它被JITC优化之前它只会慢一些。写一个CaliperJMH基准来看这个(我前段时间做过)。否则你很可能会完全没有意义(是的,Java基准测试真的很难)。

  

所以,这让我觉得差异是因为cmp是如何用机器级语言实现的。

后一个循环中没有cmp。它看起来就像(类似Java的语法)

i--;
if (!zero_flag) goto loop_start;

这是表演胜利的来源。

  

我能想到的关于本地编写比较函数的方法之一就是这个

不,没有这样的。在大多数CPU上,cmp指令的工作方式与sub类似,但无处可写。它只设置标志(零,进位,负数,......),这正是以下条件跳转所使用的。

所有有意义的标记组合都是implemented,即您可以使用单个指令执行任何条件a < ba <= b,....

  

&lt;,&gt;,==如何使用按位运算和jmp序列实现?

完全没有。那里没有一点点摆弄。

答案 1 :(得分:0)

在机器级别,知道结果是否为零,正或负是“自由操作”。在几乎每个算术运算之后,编译器在“flags”中反映出这一点,在其中可以使用分支指令。因此,您经常尝试将循环安排为完全避免比较指令(即使它很快),并且当某个寄存器通过DECrement操作达到零时,依赖于完成循环的快速。优化编译器应该为您做到这一点,但是这有点奇怪,这应该是显而易见的。