天天看點

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即可實作同樣的功能。

可見,上述機器指令設計的精巧。(了解各個指令的功能,寫出通用的功能的簡潔的代碼,真的要下一番功夫!)

繼續閱讀