int main(int argc, char* argv[])
{
int i;
scanf("%d", &i);
int j = i / 2;
printf("%d", j);
return 0;
}
编译后:
10: int j = i / 2;
00401039 mov eax,dword ptr [ebp-4]
0040103C cdq
0040103D sub eax,edx
0040103F sar eax,1
00401041 mov dword ptr [ebp-8],eax
即:M / 2 为
mov eax,M
cdq
sub eax,edx
sar eax,1
这是为什么呢?思考了一段时间后,我给出这样的回答,不知道够不够严谨
M与-M在计算机中的表示是互为补码的
即 [-M]=[M]补
因此 ,[M]/2分2个情况考虑
1,M为正数,正数的除法就是算术右移一位
mov eax , M
sar eax,1 //右移1位,即除以2
2,M为负数,则[M]/2= [ [-M]/2 ]补 = [-[[M]补/2] ]补
M为负数,所以,上面的计算过程是:
M取反加1,算术右移1位,再取反加1
设M为1字节
M取反加1可以表示成 (FF-M+1)
因此,上面的计算过程转化为
FF - ( (FF-M+1)/2 ) +1 = FF-(FF/2) + (M+1)/2
这里的 /2意思为向右带符号移一位,而FF 算术右移1位还是FF
所以可以简化为
(M+1)/2
注意,这里的M是负数
所以:
mov eax, M
sub eax,-1 //减-1就是+1
sar eax,1 //右移1位,除以2
然后解释一下 CDQ指令就可以了
当EAX >=0 ,CDQ结果 EDX=0
当EAX < 0 ,CDQ结果 EDX=-1
因此,M/2可以写成
mov eax, M
cdq //扩展符号位,到EDX
sub eax,edx //EAX>0 ,则EAX - 0 ;EAX<0 ,则EAX - (-1)
sar eax,1 //右移2位