除法和算术右移之间的巧妙取代

在大多数机器上,整数 的除法很慢,需要30多个时钟周期,除以2的幂也可以用移位运算来实现    

先码上代码

    #include "stdio.h"
   int main()
   {
   int x=-128; 
   int y=x/4;
   printf("y=%d",y);
   }


再附上汇编代码

         pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movl $-128, 24(%esp)   
movl 24(%esp), %eax
leal         3(%eax), %edx
testl         %eax, %eax  //这一步是测试%eax寄存器的值是否为0.并将标志位ZF和SF置为0或者1.
cmovs %edx, %eax //cmovs代表,sign为1的时候,也就是有符号数的时候,就执行mov指令。这是一个条件指令。
sarl          $2, %eax     //因为比如像c语言中就规定,右移是进行算术右移。那么就相当于c表达式(x<0 ? (x+(1<>k,因为c代码是除以4,那么就是右移2位。
movl %eax, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf

写这个笔记,主要目的有两点。

第一,在大多数机器上,进行除法指令比整数乘法指令更慢,需要30几个时钟周期。而移位只需要1个或几个时钟周期。这节省了很多时间。

所以一些编译器会把除法,编译为右移指令。

第二,进行算术右移的时候,是要分类讨论的。因为在大多数编程语言中,右移就是算术右移。

x/(2^k),若x为正数,那么右移,高位补0,这个没问题;

当x为负数的时候,右移,高位补1,那么由于得到的数是向下取整的(例如,得到的理论上的值为-2.1,那么结果为--3)

所以要在低位加1,也即在第k位置1.换成c语言为

(x<0 ? (x+(1<>k,

你可能感兴趣的:(深入理解计算机系统,算术右移,除法指令)