汇编角度解释 a=a++

文章通过汇编角度分析代码a=a++在VS2019和DevC++中的不同执行过程,揭示了不同编译器环境下自增操作的顺序差异,强调编程时应考虑代码的移植性。
摘要由CSDN通过智能技术生成

一 问题引出

一个比较有意思的问题,有以下代码,大家猜一猜结果是多少

int a=10;
a=a++;
printf("%d",a);

网上溜达一圈,大家在编译器上运行有结果为11的,有结果为10的,而且大家对自己所得的结果,基本上都有一些自洽的解释,不过在我看来,没有解释的太到位

二 解决问题的工具

想要搞清楚这个式子到底怎么算的,我们需要去了解两样东西
1、寄存器
2、汇编
这二者的详细内容,建议大家出门左拐百度或者就在csdn搜索一下,此处只进行一个最最基本的解释,够用就行

2.1 寄存器

我们在进行运算、赋值的时候,并不是直接把一个变量内存中的值,放在另一个变量的内存中,而是会在中间,经过寄存器的手,寄存器在此期间,起到一个数据的传输(赋值)、以及数据的处理(运算)的功能

2.2 汇编指令

我们的代码在编译的时候,会生成汇编指令,而汇编已经要涉及到代码运行的底层了,所以看汇编,我们就可以知道代码的底层运行逻辑,对于一些运行结果与人脑推算不符的代码,我们可以去看一看汇编,看电脑是怎么想的

三 解决问题

3.1 学一点基础的汇编

首先我们来学习两个汇编指令,在后边要用到

3.1.1 mov

mov指令,主要是实现数据的传送的,如寄存器之间的数据传送、寄存器与内存之间的数据传送
如: mov A B
就是将B的值,传送到A
有如下代码:

int a=10,b;
b=a;

我们看一下b=a这句话的汇编

在这里插入图片描述

第一句,使用mov指令,将变量a所在的地址空间内的值,传送到eax寄存器中
第二句,使用mov指令,将寄存器eax中的值,传送到变量b所在的地址空间
至此,经过eax寄存器的中间倒手,我们把变量a的值,赋给了变量b

3.1.2 add

add指令,加法指令
如: add A B
是将A与B相加的值,存入A所在的寄存器
有如下代码:

int a=0;
a++

我们看一下a++这句话的汇编

在这里插入图片描述

第一句,使用mov指令,将变量a所在的地址空间内的值,传送到eax寄存器中
第二句,使用add指令,对eax寄存器中的值加1,并将结果给eax寄存器
第三句,使用mov指令,将寄存器eax中的值,传送到变量b所在的地址空间
至此,我们的a++执行完毕,a里边存的是加过1后的值

3.2 解决问题

在VS中,我们的a=a++结果是11
而在DevC++中,结果为10
原因就在于我们这个后置加加先用再加
但是这个“用”,即把a的值拿出来赋值给a的过程的后半段
即a加1之前的值被拿到寄存器中之后,把寄存器中的值给a的这一步,是在自增前完成的,还是自增后完成的

3.2.1 VS2019(MSVC环境)

以下是VS2019中的汇编代码:
在这里插入图片描述

五句汇编被分为两个部分,第一个部分是赋值操作,第二个部分则是自增
也就是说
在VS2019中,我们先把a的值(10)放在寄存器eax中,然后将寄存器eax中的值(10)给a
此时a=10
而在这之后,我们进行了自增操作,从而得到了最终结果:a=11

3.2.2

以下是DevC++(gcc环境)中的汇编代码:
在这里插入图片描述
这里的赋值操作和自增操作都与VS中有一些不同

在DevC++中,
第一行,是将0xa,也就是16进制的10给内存地址[esp+0x1c]处,这句是int a=10的汇编
在后续的汇编中,[esp+0x1c]就代表着变量a
在此之后
第二句,表示我们将a的值(10)放在eax寄存器中
第三句,此处比较重要,在DevC++中,a++这里不是add指令,而是使用lea指令将eax寄存器中的值拿出来并加1后,放入新的寄存器edx中
第四句,将edx寄存器中的值(11)给变量a,自此完成a++的操作
第五句,我们之前将变量a的值给eax寄存器但是并未像VS一样对eax寄存器中的值直接进行加1,而是将加1的值存在寄存器edx中,所以此处eax中的值还是10,此时将eax中的值给变量a
于是再DevC++中,代码运行结果为10

总结与注意点

总结

这段代码在两种环境下的差异,来源于开发者对于这种有歧义的代码,有自己的理解,于是在不同的编译器中,执行顺序便有可能不一样

  1. 在VS中,是先赋值,再自增
  2. 在DevC++中,是先执行赋值的前半段(将a的值存在寄存器eax中),再执行自增操作,最后执行赋值的后半段(将eax寄存器中的值给a)

注意点

这种带有连续自增、赋值、运算性质的代码,往往会有歧义,导致在不同平台执行结果不一样
我们在写代码的过程中要避免这种情况出现,写出具有良好移植性的代码

但在专升本、考研中,经常会出现这种具有歧义的代码,要求写出结果
而答案并不是:不确定,此代码在不同平台下结果不同
往往是一个DevC++、VC6.0跑出来的所谓的“标准答案”
所以虽然现在对于学习C语言来说推荐使用VS2019、22这种流行的、各大公司都在用的IDE,好处我就不多说了
但如果是考生,那么在备考期间,就应当熟悉这个Dev、VC这些环境,对于这些有歧义的代码应当理解在这些编译器会如何运行,毕竟拿分要紧
请添加图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值