《深入理解计算机系统》学习(4):过程(如函数)和栈存储

目录

  • 过程
    • 1 运行时栈
    • 2 转移控制
    • 3 数据传送
    • 4 栈上局部存储

过程

过程中是软件中一种很重要的抽象,提供了一种封装代码的方式,用一组指定的参数和一个可选的返回值实现了某种功能。然后,可以在程序的不同的地方使用这个功能。设计良好的软件用过程作为抽象机制,隐藏某个行为的具体实现,同时又提供清晰简洁的接口定义,说明要计算的是哪些值,过程会对程序状态产生什么样的影响。不同的编程语言中,过程的形式多样:函数、方法、子例程、处理函数等,但是它们有一些共有的特性。

假设过程P调用过程Q,Q执行后返回到P。这些动作包括下面一个或多个机制:

  • 传递控制,在进入过程Q的时候,程序计数器必须被设置为Q的代码的起始地址,然后在返回时,要把程序计数器设置为P中调用Q后面那条指令的地址。
  • 传递数据,P必须能够向Q提供一个或多个参数,Q必须能够向P返回一个值。
  • 分配和释放内存,在开始时,Q可能需要为局部变量分配空间,而在返回前,又必须释放这些空间。

1 运行时栈

C语言过程调用机制的一个关键特性在于使用了栈数据结构提供的后进先出的内存管理原则。程序可以使用栈来管理过程所需要的存储空间,栈和程序寄存器存放着传递控制和数据、分配内存所需要的信息,当P调用Q时,控制和数据信息添加到栈顶,当Q返回时,这些信息会释放掉。

当x86-64过程需要的存储空间超出寄存器能够存放的大小时,就会在栈上分配空间。这个部分称为过程的栈帧。当函数满足两个条件时不需要分配栈帧:(1)该函数不会调用其他函数,(2)所有局部变量都可以保存在寄存器中。

请添加图片描述
当前正在执行的过程的栈帧总是在栈顶。当过程P调用过程Q时,会把返回地址压入栈中,指明当Q返回时,要从P程序的哪个位置继续执行。返回地址作为P的栈帧的一部分,存放的是与P相关的状态。Q的代码会拓展当前栈的边界,分配栈帧所需的空间。在这个空间中可以保存寄存器的值,分配局部变量空间,为调用过程设置参数。通过寄存器,过程P最多可以传递6个整数值(也就是指针和整数),但是如果Q需要更多的参数,P可以在调用Q之前在自己的栈帧中存储这些参数。

2 转移控制

将控制从函数P转移到函数Q只需要简单地把程序计数器设置为Q的代码的起始位置。从Q返回时,处理器必须记录需要继续P的执行的代码位置。

在x86-64机器中,指令call Q调用过程Q,记录起始位置。该指令将地址A(返回地址)压入栈中,并将PC设置为Q的起始位置。ret指令会从栈中弹出地址A,并将PC设置为A。请添加图片描述
图为两个函数topleaf的反汇编代码,以及在main函数中调用top处的代码。main中的callq指令将栈指针%rsp的值设置为该指针后的mov指令地址 0x400560,程序计数器的值设置为top的起始指令地址 0x400545
在这里插入图片描述

类似的,top中的callq指令将栈指针%rsp的值设置为该指针后的add指令地址 0x40054e,程序计数器%rip的值设置为leaf函数的起始指令地址0x400540。而leaf函数中的retq指令弹出add指令地址(调用leaf函数的返回地址)0x40054e,栈指针%rsp的值变为栈中弹出指令的上一条指令地址,即mov指令地址(调用top函数的返回地址) 0x400560 ,程序计数器%rip的值设置add指令地址 0x40054e

3 数据传送

在x86-64中,大部分过程间的数据传送是通过寄存器实现的。当过程P调用过程Q时,P的代码必须首先把参数复制到适当的寄存器中,参数在寄存器%rdi%rsi和其他寄存器中传递。当从Q返回到P时,P的代码可以访问寄存器%rax中的返回值。

x86-64中,可以通过寄存器最多传递6个整型(如整数和指针)参数,根据参数在参数列表中的顺序分配寄存器。寄存器使用的名字取决于要传递的数据类型的大小,可以通过64位寄存器适当的部分访问小于64位的参数。例如,如果第一个参数是32位的,那么可以用%edi来访问。
在这里插入图片描述
如果一个函数有大于6个整型参数,超出6个的部分就要通过栈来传递。假设调用过程Q,有 n 个整型参数,且 n > 6,那么P的代码分配的栈帧必须要能容纳7到 n 号参数的存储空间。也就是把参数7~ n 放到栈(P的栈帧)上,参数7位于栈顶。参数准备完成后,程序才执行call指令将控制转移到过程Q。
在这里插入图片描述

4 栈上局部存储

在部分情况下,局部数据必须放在内存中,常见的情况包括:

  • 寄存器不足够存放所有的本地数据
  • 对一个局部变量使用地址运算符&,因此必须能够产生一个地址
  • 某些局部变量是数组或结构,因此必须能够通过数组或结构引用或被访问到

一般来说,过程通过减小栈指针在栈上分配空间,分配的结果作为栈帧的一部分,标号为局部变量。

图3-32是一个必须在栈上分配局部变量存储空间的函数示例。
在这里插入图片描述
在这里插入图片描述
call_proc的汇编代码从第2行到第15行都是为调用proc做准备,其中包括为局部变量(第3行到第6行)和函数参数(第7行到第15行)建立栈帧,将函数参数加载至寄存器(第10行到第15行)。x1、x2、x3、x4为局部变量,首先在栈帧中为四个局部变量分配空间,然后将前六个函数参数(x1、&x1、x2、&x2、x3、&x3)加载到寄存器,后两个函数参数x4、&x4存放在栈空间。最后,调用过程proc。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/490063.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FLUOR DE LYS® HDAC fluorometric activity assay kit组蛋白去乙酰化酶荧光活性检测试剂盒

FLUOR DE LYS HDAC fluorometric activity assay kit组蛋白去乙酰化酶荧光活性检测试剂盒 目前,组蛋白去乙酰化酶抑制剂已经显示出其作为抗肿瘤药物的前景,这也自然激发了研究者们对于筛选HDAC(Histone deacetylase,组蛋白去乙酰化…

【AI】使用Azure OpenAI创建自己的AI应用!

【AI】使用Azure OpenAI创建自己的AI应用! 目录 【AI】使用Azure OpenAI创建自己的AI应用!创建工作区模型介绍部署模型API参数计算Token使用Python SDK调用补全模型调用对话模型流式调用异步调用提示技巧生成对话分类推荐超级课程: Docker快速入门到精通Kubernetes入门到大师…

超越Sora!StreamingT2V AI视频模型,轻松打造120秒视觉盛宴

近日,来自美国德克萨斯大学奥斯汀分校(UT奥斯丁)等机构的研究人员提出了一项名为StreamingT2V的AI视频生成技术,引起了业界的广泛关注。这项技术打破了传统视频生成的局限,实现了高度一致且长度可扩展的视频生成&#…

使用 nodejs + zx 编写脚本更新本地 hosts

在日常的开发和运维工作中,我们经常需要修改本地的 hosts 文件来实现一些特定的网络配置,比如将某个域名指向特定的 IP 地址。而使用 Node.js 结合 zx 工具可以让我们更轻松地编写和运行脚本来更新本地的 hosts 文件。 一、功能介绍 目标: 通…

黑马头条day5总结

1、surefire-reports for the individual test results. 借鉴:【已解决】surefire-reports for the individual test results.-CSDN博客 Please refer to D:\javashizhan01\heima-leadnews\heima-leadnews-service\heima-leadnews-article\target\surefire-report…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标:搭建一个jenkins环境,实现jenkins调用cmake和svn和VS编译c项目,并将生成的库上传svn。 环境:win10虚拟机(练习流程用,正式用的话还是放到服务器),VS2017. 二、…

54、Qt/对话框、事件机制相关学习20240325

一、完善对话框,点击登录按钮,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配&#…

四大AI神器,助你开启智慧家居新生活

曾经,人工智能还只是科幻电影里的未来幻想,而今,它已悄然融入我们生活的方方面面。不再只是工厂里的自动化手臂,或是电影中的情感机器人,AI技术已经走进了寻常百姓家,让家居生活也焕发出智慧的光彩。 想象…

并发-多线程

目录 进程 线程 线程的串行 区别 多线程 进程 是指计算机中已执行的程序,曾经是分时系统的基本运作单位在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,是程序的基本执行实体在面向线程设计的系统…

【PL理论】(1) 语法与语义:归纳的定义 | 推理规则 | 推导树 | 数学归纳法证明 (MI)

💭 写在前面:在学习编程的过程中,我们经常会听到 "语法" 和 "语义" 这两个词,这对于理解和编写高质量的代码至关重要。在本博客中,我们将深入探讨这两个概念,从而帮助读者更好地理解编…

趣味算法,猴子算法。python如何实现猴子算法

给一只猴子一台打印机,虽然这只猴子根本不识字,但会乱按,经过一段时间后,在它乱按出来的单词里总能找到一些至少看起来是有意义的部分,比如一两个简短的单词,由此可以推出:只要给它足够长的时间…

vite+vue3动态模块化导入并使用pinia

一、安装引入pinia 1.安装 pnpm install pinia # 或者使用 yarn yarn add pinia # 或者使用 npm npm install pinia 2.在main.js里引入 import { createApp } from vue import App from ./App.vue import { createPinia } from pinia createApp(App).use(createPinia()).mo…

辽渤湾海现已加入2024第七届燕窝天然滋补品博览会

参展企业介绍 大连辽渤湾海产品有限公司,是一家主营海参、鲍鱼、海胆等大连海产品的加工和销售的综合型水产企业,拥有国内精良的整条加工流水线,拥有上千平米的现代化加工办公场地的现代化企业。现已发展成为大连海参产品的主导型深加工基地。…

如何清理释放群晖客户端缓存?

任正菲说:企业最大的浪费,是经验的浪费! 而一个一个的经验,又都来自企业的每一个工作者。 因此当我们在工作过程中遇到一些问题时,我们就应该下意识的把解决问题的经验沉淀下来,从而可以与大家进行分享。…

软件设计师19--文件管理

软件设计师19--文件管理 考点1:文件相关概念例题: 考点2:树形目录结构(绝对路径与相对路径)例题: 考点3:位示图例题: 考点4:索引文件索引文件结构例题: 考点1…

武汉星起航:跨境电商行业的领军者,互帮互助共创佳绩

武汉星起航电子商务有限公司,作为跨境电商行业的领军者,以其出色的业绩和卓越的团队实力,在业内赢得了广泛的赞誉。公司自运营团队在亚马逊平台上成功开设了多家店铺,凭借着深耕跨境电商行业多年所积累的经验,取得了令…

[自研开源] 数据集成之分批传输 v0.7

开源地址:gitee | github 详细介绍:MyData 基于 Web API 的数据集成平台 部署文档:用 Docker 部署 MyData 使用手册:MyData 使用手册 试用体验:https://demo.mydata.work 交流Q群:430089673 介绍 本篇基于…

面试笔记——Java集合篇

Java集合框架体系 重点:单列集合——ArrayList、LinkedList;双列集合——HashMap、ConcurrentHashMap。 List相关 数组(Array) 是一种用连续的内存空间存储相同数据类型数据的线性数据结构。 数组获取其他元素: 为什…

为什么在vite中使用eslint报错‘__dirname‘ is not defined?

问题分析 发生这种情况是因为 ESLint 不知道 vite.config.js 中的代码在 Node.js 中使用,__dirname 未在浏览器中定义,也未在 ES 模块中定义。因此要告诉 ESLint 代码将作为 CommonJS 模块在 Node.js 中运行。 解决方案 请打开 ESLint 配置并在该 env …

关于 boost::asio::strand 初始化 socket、stream、resolver、deadline_timer 对象

在 boost::asio 之中默认情况下,大家使用 io_context 来为这些对象初始化传递的执行者,但我需要这里说明。 对于 boost::asio 构造类似 socket 对象必须构造传递 io_context 是个伪命题,boost::asio 对象并非只允许传递 boost::asio::io_cont…