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

在大多数机器上,整数 的除法很慢,需要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)-1) : x)>>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)-1) : x)>>k,

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值