程序运行的过程

前言

过程是软件中一种很重要的抽象。它提供了一种封装代码的方式,用一组指定的参数和一个可选的返回值实现了某种功能。然后可以在程序中不同的地方调用这个函数。

要提供对过程的机器级支持,必须要处理不同的属性。为了讨论方便,假设过程P调用Q,Q执行后返回到P。这些动作包括下面一个或多个机制:
传递控制。在进入Q的时候,程序计数器必须被设置为Q的代码起始地址,然后在返回时,要把程序计数器设置为P中调用Q后面那条指令的地址。
传递数据。P必须向Q传递一个或者多个参数,Q必须能向P返回一个值。
分配和释放内存。在开始的时候,Q可能要为局部变量分配空间,而在返回前又必须释放这些内存空间。

运行时栈

x86-64的栈向低地址方向增长,而栈指针%rsp指向栈顶元素。可以用pushq和popq指令将缓存数据存入栈中或是从栈中取出。
栈空间

转移控制

将控制从函数P 转移到函数Q 只需要简单地把程序计数器(PC)设置为Q 的代码的起始位置。不过,当稍后从Q 返回的时候,处理器必须记录好它需要继续P 的执行的代码位置。在x86-64 机器中,这个信息是用指令call Q 调用过程Q 来记录的。.该指令会把地址A 压入栈中,并将PC 设置为Q 的起始地址。压人的地址A 被称为返回地址,是紧跟在call 指令后面的那条指令的地址。对应的指令ret 会从栈中弹出地址A,并把PC 设置为下表给出的是call 和ret 指令的一般形式:
在这里插入图片描述

数据传送

当调用一个过程时,除了要把控制传递给它沐在过程返回时再传递回来之外,过程调用还可能包括把数据作为参数传递,而从过程返回还有可能包括返回一个值。X86-64 中,大部分过程间的数据传送是通过寄存器实现的。例如,我们已经看到无数的函数示例,参数在寄存器 %rdi%rsi 和其他寄存器中传递。当过程P 调用过程Q 时,P 的代码必须首先把参数复制到适当的寄存器中。类似地,当Q 返回到P 时,P 的代码可以访问寄存器 %rax 中的返回值。

X86-64 中,可以通过寄存器最多传递6 个整型(例如整数和指针)参数。寄存器的使用是有特殊顺序的,寄存器使用的名字取决于要传递的数据类型的大小,如下图所示。会根据参数在参数列表中的顺序为它们分配寄存器。可以通过64 位寄存器适当的部分访问小于64 位的参数。例如,如果第一个参数是32 位的,那么可以用 %edi 来访问它。

在这里插入图片描述
如果一个函数有大于6 个整型参数,超出6 个的部分就要通过栈来传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值