自制操作系统番外 2:编程语言中函数参数的传递
简介
上篇中我们探索了从汇编的角度看 C 和 Go 中的变量声明,这篇我们继续探索下函数的参数传递时的基本类型和指针类型
前言
在我们开始学习编程的时候,相信都接触过类似下面的代码吧:在函数内部改变值,一个传入的是基本类型,一个是指针类型,外部的变量是否改变
下面是 go 的示例代码:
运行结果:
第一个并没有改变,第二个改变了,下面我们从汇编代码看看其原理
Go 汇编探索
将上面的代码生成汇编代码,命令可以参考上篇
下面是关键部分代码的摘抄,就不放全部上去
首先是声明了变量在栈上,并赋值 100
开始调用函数 pb,可以看到直接将 100 赋值给了寄存器 AX(应该编译器阅读的传参,指定给寄存器 AX)
在函数 pb 内部(函数内部也有自己的变量,所以将传递过来的参数保存在栈上),这里赋值就直接赋值给了函数内部栈的变量了,和 main 函数上的不是一个,所以没有改变外部的变量
开始调用函数 pbp,不像第一个第一个函数 pb 直接传值,而是将变量地址给寄存器 AX
在函数 pbp 内部,虽然也将 AX 赋值给了函数内部的变量的,但赋值 10 时是直接给到了 AX 对应内存地址,直接改变了变量的值
通过上面的汇编,应该有了些感悟,我们继续看看 C 的
C 汇编探索
对应的 C 代码如下:
将其生成汇编代码(32 位的)后,对应的关键汇编代码如下:
可以看到,C 编译器约定的寄存器是 eax,第一个函数复制给了函数栈上,第二个给了 eax 对应的内存变量
可能对应 100 这个值的存储和赋值有点疑惑:
100 是存储在内存中,不是存放在寄存器 SP 中,内存中有一个程序对用栈(这个涉及到内部布局、分配相关的点,博主目前还在研究中,暂时还没有通透,等后面稍微清晰了再写篇文章讲讲)
SP 是个寄存器,是放了 100 这个值对应的内存地址
总结
通过上面的 Go 和 C 对一个的函数调用的汇编探索,对于函数传值和传指针时能不能改变值应该有了一定的认知了
核心感觉还是两点:
函数内部变量是独立于外部的(栈是整个程序通用,只是存放在栈上的位置不同而已)
指针是函数内部直接改变对应的内存地址的值
但还是有很多的疑问:
Java 中是没有指针这一手的,那传值对应的情况是啥呢(Java 的汇编还有点麻烦,后面再探索探索)
上面研究是基本类型,如果是字符串或者类,那是不是只有传指针,没有传值这一说
传类的时候,赋值等操作对应的汇编是怎样的,也就是汇编中是怎样对应类的操作
了解更多,不知道的更多,后面继续探索
版权声明: 本文为 InfoQ 作者【萧】的原创文章。
原文链接:【http://xie.infoq.cn/article/e271852becc343ac43da55aea】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论