学习记录:CS161(二)

编译器、汇编器、链接器、加载器(CALL)

运行 C 程序有四个主要步骤:
(1)编译器将 C 代码转换为汇编指令。
(2)汇编程序将编译器中的汇编指令转换为机器代码(原始位)。
(3)链接器解析对外部库的依赖关系。链接器完成链接外部库后,它会输出可以运行的程序的二进制可执行文件。
(4)当用户运行可执行文件时,加载程序会在内存中设置地址空间,并在可执行文件中运行机器代码指令。

内存布局

运行程序时,地址空间分为四个部分。从最低地址到最高地址,它们是:

  • CODE:代码部分包含程序的可执行指令(即代码本身)
    -STATIC: static 部分包含常量和静态变量,这些常量和静态变量在程序执行期间永远不会更改,通常在程序启动时分配。
  • HEAP:存储动态分配的数据。当您在 C 中调用 malloc 时,内存会在堆上分配并提供给您使用,直到您调用 free。堆从较低的地址开始,随着分配的内存增加而“增长”到更高的地址。
  • STACK:存储与函数调用关联的局部变量和其他信息。堆栈从更高的地址开始,并随着调用更多函数而“增长”。

寄存器

== EIP (指令指针)==:存储当前正在执行的机器指令的地址。在RISC-V中,这个寄存器被称为PC(程序计数器)。

== EBP (基指针)==:存储当前堆栈帧顶部的地址。在RISC系统中,该寄存器称为FP(帧指针)。

== ESP (堆栈指针)==:存储当前堆栈帧底部的地址。在RISC-V中,这个寄存器被称为SP(堆栈指针)。

注意:
(1)当前栈帧的顶部是与当前堆栈帧关联的最高地址,栈帧的底部是与当前堆栈帧关联的最低地址
(2)健全性检查:这些寄存器通常指向 C 存储器的哪个部分(代码、静态、堆、栈)?

函数调用

具体步骤:

  1. 将参数推送到栈上
    RISC-V 通过将参数存储在寄存器中来传递参数,而 x86 通过将参数推送到堆栈上来传递参数。
    请注意,当我们将参数推送到堆栈上时,esp 会递减。参数以相反的顺序推送到堆栈上。
  2. 将旧的 eip (rip) 推到栈上
    我们即将更改 eip 寄存器中的值,因此我们需要将其当前值保存在栈上,然后再用新值覆盖它。当我们在堆栈上推送此值时,它被称为旧 eip 或 rip(返回指令指针)。
  3. 移动 eip
    将 eip 更改为指向被调用方函数的指令。
  4. 将旧的 ebp (sfp) 推送到栈上。
    请注意,esp 已递减。
  5. ** 将 ebp 向下移动。**
    将 ebp 更改为指向新栈帧的顶部。新栈帧的顶部是 esp 当前指向的位置,因为我们即将在 esp 下方为新堆栈帧分配新空间。
  6. ** 向下移动 esp。**
    通过递减 esp 来为新的堆栈帧分配新空间。
    编译器查看函数的复杂性,以确定 esp 应该递减多远。例如,只有几个局部变量的函数不需要堆栈上太多空间,因此 esp 只会递减几个字节。另一方面,如果一个函数将一个大数组声明为局部变量,则 esp 将需要减少很多以适应堆栈上的数组。
  7. 执行函数。
    局部变量和任何其他必要的数据现在可以保存在新的栈帧中。
    此外,由于 == ebp == 始终指向栈帧的顶部,因此我们可以将其用作参考点来== 查找栈上的其他变量 ==。例如,参数将从存储在 ebp 中的地址加上 8 开始。
  8. 向上移动esp
    一旦函数准备好返回,我们就会递增 esp 以指向堆栈帧 (ebp) 的顶部。这有效地擦除了栈帧,因为栈帧现在位于 esp 下方(esp 下方堆栈上的任何内容都是未定义的。
  9. 恢复旧的 ebp (sfp)
    堆栈上的下一个值是 sfp,即我们开始执行函数之前 ebp 的旧值。我们将 sfp 从堆栈中弹出,并将其存储回 ebp 寄存器中。这会将 ebp 返回到调用函数之前的旧值。
  10. 恢复旧的eip(rip)
    堆栈上的下一个值是 rip,即我们开始执行函数之前 eip 的旧值。我们将 rip 从堆栈中弹出并将其存储回 eip 寄存器中。这会将 eip 返回到调用函数之前的旧值。
  11. **从堆栈中删除参数。**由于函数调用已经结束,我们不再需要存储参数。我们可以通过递增 esp 来删除它们(回想一下,esp 下面的堆栈上的任何内容都是未定义的)。
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值