假设我有$t0
,我想将其整数内容除以 2,并将其存储在$t1
.
我的直觉说:srl $t1, $t0, 2
...但是如果...说...最右边的位是1,那不是问题吗?还是因为最右边的位(如果是正数)产生$t0
了一个奇数,而除以它后变成偶数,所以这一切都在洗涤中出现了?
教我啊,聪明的人...
使用指令 sra:右移算术!!
sra $t1, $t0, 1
将 $t0 的内容除以 2 的第一次幂。
说明: 将寄存器值右移移位量 (shamt) 并将值放入目标寄存器。符号位被移入。
操作:$d = $t >> h;
Advance_pc (4);
语法:sra $d, $t, h
编码:0000 00-- ---t tttt dddd dhhh hh00 0011
为什么这很重要?检查这个将整数(程序的输入)除以 2 的简单程序。
#include <stdio.h>
/*
* div divides by 2 using sra
* udiv divides by 2 using srl
*/
int div(int n);//implemented in mips assembly.
int udiv(int n);
int main(int argc,char** argv){
if (argc==1) return 0;
int a = atoi(argv[1]);
printf("div:%d udiv:%d\n",div(a),udiv(a));
return 1;
}
//file div.S
#include <mips/regdef.h>
//int div(int n)
.globl div
.text
.align 2
.ent div
div:
sra v0,a0,1
jr ra //Returns value in v0 register.
.end div
//int udiv(int n)
.globl udiv
.text
.align 2
.ent udiv
udiv: srl v0,a0,1 jr ra //Returns value in v0 register. .end udiv
编译
root@:/tmp#gcc -c div.S
root@:/tmp#gcc -c main.c
root@:/tmp#gcc div.0 main.o -o test
试驾:
root@:~# ./test 2
div:1 udiv:1
root@:~# ./test 4
div:2 udiv:2
root@:~# ./test 8
div:4 udiv:4
root@:~# ./test 16
div:8 udiv:8
root@:~# ./test -2
div:-1 udiv:2147483647
root@:~# ./test -4
div:-2 udiv:2147483646
root@:~# ./test -8
div:-4 udiv:2147483644
root@:~# ./test -16
div:-8 udiv:2147483640
root@:~#
走着瞧吧?srl指令正在移位符号位
-2 = 0xffffffffe
如果我们向右移动一位,我们得到 0x7fffffff
0x7ffffffff = 2147483647
当然,当数字是正整数时这不是问题,因为符号位是 0。
做无符号整数除法,没错。这仅适用于无符号整数并且如果您不关心小数部分。
您需要使用 1 而不是 2 的移位量:
srl $t1, $t0, 1
如果您使用 2,您最终将除以 4。通常,右移x将除以 2 x。
如果您担心“四舍五入”并且想要四舍五入,则可以在进行逻辑(无符号)移位之前增加 1。
其他人之前已经说过,但您只需移动 1 即可除以 2。右移 N 位除以 2 ^ N。
要使用移位值 N 不是 1 的舍入(向上舍入 0.5 或更大),只需在移位前添加 1<<(N-1)。