MIPS 汇编指令学习指令-abs

  mips 中求一个数的绝对值的指令:

abs  $d, $s   ​    ​    # $d =  $s>=0 ? $s  : -($s);

这条指令是mips编译器中的宏指令,其展开后的机器指令如下:

宏指令:abs  $d, $s   ​    ​    # $d =  $s>=0 ? $s  : -($s);

机器指令:

 ​    => sra $at, $s, 31​    ​    #assume it's mips32,  $at = $s<0 ? -1 : 0;

​    ​    ​   xor $d, $s, $at  ​     #  $d= $s xor $at ;

           subu $d, $d, $at    #  $d =  $d - $at; 

分析:该指令为求一个整数的的绝对值,若该整数是负数,其绝对值为其相反数;否则,为其本身。

对一个整数的二进制补码求其相反数的补码的方法是:对其各位(包括符号位)取反,末位加1;

对于异或 xor有这样的特性:设 Y 为一位二进制位(bit), 则有

​    Y xor 0 = Y; 

​    Y xor 1 = ~Y;   //~Y 为 Y 的非,即对 Y 取反

​    Y xor Y = 0;

对一个32位整数 Z 的各位取反,即可通过使其异或(xor)一个32位全为 1的整数即 mips32中的-1的补码;

​    Z xor -1 = Z xor (11111111 11111111 11111111 11111111)= ~Z;

 

Z的相反数的补码: -Z = ~Z + 1 = (Z xor -1) + 1;

 

其实求一个整数的相反数的补码的另一种快捷的机器实现方法是:

          对该整数的各位从右往左(从低位到高位)扫描, 除最右边的零和第一个出现的1保持不变,其余的各位依次取反。

 

下面分析关于宏指令 : abs $d, $s 机器指令的实现:

第一条机器指令:  sra $at, $s, 31; 

  通过算术右移指令sra,将 $s 右移 31 位,算术右移时带符号扩展的,其结果是$at寄存器中32位的每一位都和$s的符号位相同,即$at的32位要么全为1(if $s<0), 要么全为0 (if $s >=0);

 

第二条机器指令: xor $d, $s, $at;

有异或的特性可知,当$s<0时, $at=-1; $d = ~$s;  否则, $at=0, $d=$s;

 

第三条指令:  subu $d, $d, $at; 

当$s < 0 时  $at=-1,相当于对于负数求其相反数的加1操作;

当$s >= 0时, $at=0 , $d 保持不变。

 

可见,以上三条指令既能实现求一个负整数的绝对值,也能实现求一个正整数的的绝对值,而且其机器指令是一致。

note:对于mips64中abs 只须将 31 变为63即可实现同样的功能。

 

可见,上述机器指令设计的精巧。(了解各个指令的功能,写出通用的功能的简洁的代码,真的要下一番功夫!)

 

 

 

 

 

你可能感兴趣的:(汇编,扩展,编译器)