<转>VC编译的除法的一段汇编代码解释

简介: int main(int argc, char* argv[]){      int i;      scanf("%d", &i);      int j = i / 2;      printf("%d", j);return 0;} 编译后: 10:         int j = i /...

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位

相关文章
|
1月前
|
存储 自然语言处理 编译器
编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境)
编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境)
|
4月前
|
编译器 Linux C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(上)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
VC8 常用代码汇编 返回值,入参,全局变量
VC8 常用代码汇编 返回值,入参,全局变量
|
8月前
|
C++
VS code 编写汇编代码【微机原理】3
VS code 编写汇编代码【微机原理】3
48 0
|
3月前
|
存储 缓存 Linux
C语言编译过程——预处理、编译汇编和链接详解
C语言编译过程——预处理、编译汇编和链接详解
|
4月前
|
编译器 C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(下)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
VC8常用代码对应汇编 成员变量赋值
VC8常用代码对应汇编 成员变量赋值
|
8月前
|
编译器 C++ Windows
VS code 编写汇编代码【微机原理】2
VS code 编写汇编代码【微机原理】2
81 0
|
8月前
|
C++ Windows
VS code 编写汇编代码【微机原理】1
VS code 编写汇编代码【微机原理】1
67 0