帧指针有什么优点?

2023-11-21

我们正在学习 MIPS 汇编器(我想这个问题可以适用于一般的汇编),老师向我们介绍了帧指针.

如果我有一个函数序言,我曾经直接执行堆栈指针:

addiu $sp, $sp, -8   ; alloc 2 words in the stack
sw $s0, 4($sp)       ; save caller function $s0 value in the stack
sw $ra, ($sp)        ; save the return address for the callee function

在函数尾声中:

move $v0, $0         ; set 0 as return value
lw $s0, 4($sp)       ; pick up caller $s0 value from the stack
lw $ra, ($sp)        ; pick up return address to return to the caller
addiu $sp, $sp, 8    ; dealloc the stack words I used
jr $ra               ; return back to caller

老师说,当我们用汇编语言编写函数时,使用帧指针对于我们人类来说很有用:

addiu $sp, $sp, -12  ; alloc 3 words in the stack
sw $fp, 8($sp)       ; save caller frame pointer in the stack
addiu $fp, $sp, 8    ; set $fp to the uppermost address of the activation frame
sw $ra, -4($fp)      ; saving like the first example, but relative 
sw $s0, -8($fp)      ; to the frame pointer

老师还说,有时堆栈指针会继续分配其他空间,并且在函数内引用激活帧会更困难,因为我们需要注意。 使用帧指针,我们将有一个指向激活帧的静态指针。

是的,但是我会ever需要在函数内使用激活,因为它只包含调用者函数保存的数据?

我认为这只会让事情变得更难实施。有没有一个真正的实际例子表明帧指针对程序员来说是一个很大的优势?


当在堆栈上动态分配可变数量的空间时,您绝对只需要一个帧指针。使用可变长度数组和/或allocaC 中是需要帧指针的函数示例。由于函数使用的堆栈量是可变的,因此您不能使用堆栈指针的常量偏移量来访问变量,并且您需要一种方法在函数返回时撤消可变长度分配。使用帧指针可以解决这两个问题。您可以使用它来使用常量偏移来寻址堆栈变量,并将堆栈指针恢复到函数开始时的值。

在 MIPS 上,如果总堆栈分配超过 32k,则在仅使用固定大小堆栈分配的函数中使用帧指针作为优化也是有意义的。 MIPS 支持的有限寻址模式仅允许相对于堆栈指针或任何其他寄存器的 16 位符号扩展偏移。由于堆栈指针指向堆栈底部,因此堆栈指针只能使用非负偏移量,因此单条指令只能寻址堆栈上的 32k。通过使用帧指针并将其指向堆栈帧的中间(而不是帧的顶部),它可以用于在单个指令中寻址最多 64k 的堆栈。

否则,使用帧指针只会有利于程序员,而不是程序。如果程序中的所有函数都使用带有帧指针的标准堆栈帧,则帧指针和堆栈中存储的所有保存的帧指针值形成堆栈帧的链接列表。在调试时可以轻松地遍历此链表以创建函数调用的引用。但是,使用合适的现代调试器,还可以将元数据(展开信息)嵌入到可执行文件中,即使不使用帧指针,调试器也可以使用这些元数据来遍历堆栈帧。现代编译器可以自动执行此操作,但在汇编语言中,包含所有必要的额外指令以使其工作可能会非常痛苦。

如果堆栈指针可以在函数期间通过固定大小的分配和释放来多次更改,那么在程序中的任何给定点跟踪变量相对于堆栈指针的位置可能会很痛苦。虽然它在任何给定位置始终处于固定偏移处,但它会根据位置而变化。确定偏移量可能很棘手且容易出错。使用帧指针将为每个变量提供一个相对于帧指针的偏移量,该偏移量永远不会改变,因为帧指针值不会改变。

请注意,如果您觉得需要使用帧指针,因为最后两个原因之一,您必须首先考虑为什么要在汇编中进行编程。在这些情况下,现代编译器不需要使用帧指针,因此会生成更好的代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

帧指针有什么优点? 的相关文章

随机推荐

  • 无论设置是否正确,PHP 连接都会在大文件上传时重置

    我遇到了一个非常常见的问题 似乎找到的所有可用解决方案都不起作用 我们有一个接收大量流量的 LAMP 服务器 使用此服务器 我们执行定期文件提交上传 在小文件上传时 它工作得很好 对于大约 4 5MB 的文件 此提交上传会间歇性失败 有时有
  • 带有 PhoneGap 的 Google+ 登录按钮

    我们如何将 JS Google 登录按钮与 Phonegap 一起使用 专门针对iOS 我已经发现本文关于使用phonegap和childbrowser插件进行oauth 但是我不确定该方法是否适用于Google 登录按钮 有任何想法吗 G
  • 在 SQLAlchemy 中映射大量相似的表

    我有许多 2000 个位置的时间序列数据 每个时间序列都有数百万行 我想将它们存储在 Postgres 数据库中 我当前的方法是为每个位置时间序列建立一个表 以及一个存储每个位置信息 坐标 海拔等 的元表 我正在使用 Python SQLA
  • 使用什么转换属性进行变换?

    我不确定这是否是正确的方法 但我想旋转一个元素 而且我知道transform rotate 90deg transition property all会起作用 但我不想过渡all的转变 What transition property我应该
  • 我的应用程序的 Facebook 故事:无法生成故事

    在我的 Facebook 应用程序的 Open Graph 仪表板中 在使用标准对象创建自定义或故事后 我的故事出现错误 显示 无法生成故事 因此 在 facebookdeveloper apps myapp story openGraph
  • 当解决方案具有多个 Web 应用程序时,TFS 2010 + MSDeploy

    我有两个解决方案 SolutionA sln WebApplication1 csproj SolutionB sln WebApplication1 csproj WebApplication2 csproj 我还有两个 TFS 2010
  • 以编程方式在表变量中设置身份种子

    我需要创建一个带有标识种子的表变量 该标识种子以另一个表中字段的最大值开头 我试过这个 DECLARE IdentitySeed int SET IdentitySeed SELECT MAX HHRecId 1 FROM xxx DECL
  • 推送通知代码执行(强制退出应用程序)

    我想知道像 Whatsapp 这样的应用程序如何能够向消息的发件人提供送达收据 双绿色支票 我发现 即使您强制退出 Whatsapp 使用应用程序任务切换器并将应用程序滑开 发件人仍然会在手机收到推送通知时收到送达收据 双绿色勾号 显然 他
  • 是否可以从 JavaDoc 创建 Java 类?

    问题是 目前我的团队为一家供应商工作 该供应商为我们提供了他们库中的大量 JavaDoc 规范 但没有提供带有存根或实现的 jar 文件 我们已经与他们交谈过 但他们只会在 2 到 3 周内提供 jar 文件 我不想等到这个时候才开始我们的
  • SQL:从全名字段中解析名字、中间名和姓氏

    如何使用 SQL 从全名字段中解析名字 中间名和姓氏 我需要尝试匹配与全名不直接匹配的名称 我希望能够将全名字段分解为名字 中间名和姓氏 数据不包含任何前缀或后缀 中间名是可选的 数据格式为 First Middle Last 我对一些实用
  • 如何在项目中导入Angular Material?

    我已经安装了 Angular Material Design 现在我尝试将其添加到app module ts file import MaterialModule from angular material 我应该在部分中确定什么 impo
  • 从 websocket 监听器发出全局事件

    我想为一个项目做出贡献 它是用 Vue 编写的 而我是 Vue 的初学者 我有两个组件 Setup and MainApp 两者都需要根据来自 websocket 的不同消息来更新某些状态 有些 websocket 消息会影响前者 有些则影
  • 如何获取实际的监视器名称?如分辨率对话框中所示

    我正在尝试获取系统上监视器的友好名称 我正在使用 C 我努力了Screen 这只是给了我 DisplayXX 我也尝试过Win32 DesktopMonitor and EnumDisplayDevices 它们都给了我以下的变体 Disp
  • pycharm 和子进程 - 在控制台中有效的内容在 Pycharm 中无效

    Pycharm 的解释器似乎已经停止理解我的一些控制台命令 它不断识别默认的 shell 命令 但不识别已安装的实用程序 例如 subprocess模块理解touch命令但不理解heroku命令 有趣的是 当我使用相同的解释器 来自相同的
  • 如何获取乌龟的位置?

    如何在Python中找到乌龟的坐标 例如 如果乌龟位于 200 300 我如何检索该位置 如Python文档所示 turtle pos 以 2D 向量形式返回海龟的当前位置 x y
  • 拼写错误的 Ace 编辑器选项

    我已经为 PHP 实现了 Ace 编辑器设置 工作正常 但是当我尝试使用 Ace 的 API 设置其他选项时 我在控制台中收到警告 这是用于初始化编辑器并尝试设置选项的代码 ace require ace ext language tool
  • 按因子计算组的平均值

    有没有办法可以改进或更简单地做到这一点 means by lt function data INDEX b lt by data INDEX function d apply d 2 mean return structure t matr
  • 在锁定的 Windows 10 计算机上的后台进程中将文本放入剪贴板

    我正在构建一个进程 到目前为止 我已在 Net Framework 4 7 2 上尝试过 VBA Python 和 C 该进程需要将一些字符串放入 Windows 10 计算机锁定屏幕后面的剪贴板上 为了测试 我将其减少到只有两个命令 伪代
  • 如何在 SQL Server 上执行 SQL 脚本期间显示某些内容?

    例如 我有一个数据库升级脚本 用于向数据库表添加列 它看起来有点像这样 IF NOT Exists SELECT FROM SysColumns sc SysObjects so WHERE sc Name dealer number AN
  • 帧指针有什么优点?

    我们正在学习 MIPS 汇编器 我想这个问题可以适用于一般的汇编 老师向我们介绍了帧指针 如果我有一个函数序言 我曾经直接执行堆栈指针 addiu sp sp 8 alloc 2 words in the stack sw s0 4 sp