Procedure Call and Stack

xiaoxiao2021-02-28  53

文章来源:陈同学 | Procedure Call and Stack

文章简介

最近查资料时,偶然在youtobe看到了华盛顿大学自然科学与工程一位老师 关于 Procedure & Stacks 的课程,深入讲解了基于Stack的过程调用,展示了应用级别和寄存器级别的处理过程,演示非常形象,受益良多。以下是课程重点及视频链接,可以自行翻墙观看。

1-Stacks2-Procedure Calls and Returns3-Stack-based languages4-Linux stack frame5-Registers and variables6-x86-64 Procedure Calling Convention

文本作为学习笔记,仅先记录过程调用时Stack和寄存器的变化.

课程笔记

Procedure Call Overview

下图为Caller(调用方) 调用 Callee(被调用方)的示例.

Caller需要保存它在寄存器上的数据,因为Callee会覆盖;Caller需要设置参数,调用Callee,然后清理参数,将数据重新存储到寄存器,然后找到返回值。

Callee需要保存局部变量,存储返回值,将一些数据存储到寄存器,再返回到Caller

save regs 表示保存寄存器数据;args 表示参数;local vars 表示局部变量; return val 表示返回值

为了实现上述过程,需要解决以下问题。

Callee 需知道去哪儿找参数(机器没有传参之说,它只知道去哪儿读取数据,然后做何种计算)Callee 需知道去哪儿找 “return address”, 即Callee执行结束后如何返回到上图中Caller部分的call代码处,并继续执行Caller中的指令Caller 需要去哪儿找Callee返回的结果由于Caller 和 Callee 运行在同一个CPU上,它们共享寄存器,因此它们需要自行存储寄存器上的数据。Caller 和 Callee 之间需要一定的约定,例如:Callee约定将返回值存到某个寄存器,Caller去某个寄存器读取数据即可,这是一种通过约定共享信息的方式。这种约定成为 Procedure call linkage

Procedure Control Flow

通过 Stack 来支持 procedure call 和 return.

先假设几个概念,方法main调用方法B,假设方法main的代码如下:

B(123); // call println("123"); // return address

我们暂且称调用B()方法的指令为call指令,称call之后需要执行的指令(println("123"))的地址为 return address(返回地址)

那么调用时执行的指令可以用下图来表示:

call 8048b90: 表示调用方法B()的指令8048553: 表示返回地址,即执行call之后需要返回到Caller处继续执行(println("123"))的指令,需要把这条指令push到栈顶,这样B()执行完后可以返回回来,那么 return address 的值就是8048553当B() return时,将 return address 从stack 中pop出来,这样就拿到了下一条需要执行的指令。然后再读取return address上存储的指令并执行即可(这条指令做的事情就是println(result))

Procedure Call Example

说明:%eip、%esp、

转载请注明原文地址: https://www.6miu.com/read-2629860.html

最新回复(0)