1、传值传参:
把实参的数据拷贝一份,放进寄存器,然后赋值给对应的形参
- 把x,y的值,分别放入一个寄存器里面(后面用call调用函数)
然后调用函数
- 创建栈帧的前两步就把寄存器edx,ecx的值放进对应的a,b的位置了(这里0x000000DAF16FF510和0x000000DAF16FF518就是后面a,b的地址)
进行加法操作
- int c = a + b:分别将a、b的值放入ecx、eax中,然后eax加到ecx中,再将ecx的值覆盖入eax中,然后将eax的值放入c中。
- a++:将a的值放入eax中,然后eax的值自加1,最后将eax中的值放回到a中
- 最后将c的值放入了寄存器eax中,准备出栈帧
最后出栈帧
- 出了作用域,栈帧销毁,a,b的空间也自然被销毁,但销毁之前将返回值放入了一个寄存器中,所以就将eax中的值覆盖入ret1中
- 但是x,y的值并没有任何变化。传值不会影响实参
以上就完成了传参的值传递
2、传址传参:
将实参的地址拷贝一份,放进寄存器,压入新栈帧里面,在新的栈帧里面就可以知道原来实参的位置
- 将x,y的地址,放入寄存器中
然后调用函数
- 创建栈帧,把rdx,rcx中的值(就是x,y的地址)放入两个位置(这个位置就是新栈帧对应的a,b的位置),此时a,b中的值就是x,y的地址,可以通过这个来找main函数中x,y的地址
进行加法操作
- int c = *a + *b:先将a的值放入rax寄存器中,然后将rax中的值放入eax寄存器中;再将b的值放入rcx寄存器中。此时eax中是a的值,rcx中是b的值。再将eax和rcx的值相加,相加后的值覆盖eax,最后将eax的值放入c中。
- (*a)++:将a的地址放入rax中,再将rax的地址放入eax中,然后对eax自加1,,然后把a的地址放入rax中,再将eax的值放入rax中,就完成了操作
- 出栈帧之前把c的值放入了eax中,用来做返回值
最后出栈
- 出了作用域,栈帧销毁,a,b的空间也自然被销毁,但销毁之前将返回值放入了一个寄存器中
- 并且x,y的值也发生了变化。传址会影响实参
以上就完成了传参的址传递
3、传引用传参:
可以理解为传进去的就是x,y本身,这就是传引用的特点
- 将x,y的地址,放入寄存器中
然后调用函数
- 这里执行完函数的调用后,发现a的地址就是main函数的x的地址、b的地址就是main函数中的y的地址,并且他们的值都是对应的x,y的值。(这就是和指针不一样的点,指针存的是实参的地址)
进行加法操作
- 这里看似是对形参a,b进行操作,实际上是直接对x,y进行操作(先记下a,b的地址,后面可以看出)。最后通过eax寄存器保存c的值(eax中存的是3,上图还需要走一步才能体现出)
最后出栈
- 返回值成功接收,ret1==3;并且x的值也跟着改变了(这里地址和前图对不上,因为是在不同的调试中)
以上就完成了传参的引用传递