assembly - 分支和跳转中的地址
问题描述
在 MIPS 中,为了在分支的情况下计算新指令的地址,将偏移量(移位 16 位)添加到当前 PC。但是为了在跳转的情况下计算新指令的地址,当前 PC 被跳转后的新 26 位替换。用新值替换 PC 的全部值背后的逻辑是什么?为什么在分支的情况下我们只做与计算新地址相同的事情?
如何计算跳转目标地址和分支目标地址的详细信息在此链接如何计算跳转目标地址和分支目标地址?
解决方案
动机如下:
具有 26 位的 pc 相对分支可以达到 +/- 128MB,即 256MB 范围。对于代码段中间的代码,它可以到达该范围内的任何位置。但是,靠近开头或结尾的代码只能达到该代码段的 128MB — 开头的代码可以达到 +128MB,接近结尾的代码可以达到 -128MB,因此对他们来说,一半的范围是“浪费的” . 因此,无需关注或缓解的最大代码段为 128MB。
通过使用更绝对的概念,所有代码——无论是靠近代码段的开头、中间还是结尾,都可以达到 256MB 的完整范围。
这种方法的缺点是代码段实际上需要从 256MB 边界开始(即不会使链接变得非常复杂),从而将代码段的总数限制为 16 个。
相反,使用较大的 pc 相对位移会将代码段的大小限制为 ~128MB,这仍然是巨大的,并且会消除代码段计数限制,因为所有代码都是 pc 相对的。
RISC V 已经取消了这种方法,转而支持 pc 相对寻址——尽管 1 条指令中的最大位移在 21 位时较小,这意味着当代码段大于 1MB 时,1 指令调用模型可能会失败;下一个模型使用 2 条指令(AUIPC 和 JALR)以 32 位范围(即 +/-2GB)执行与 pc 相关的分支/调用。
RISC V 工具链还支持“Relaxation”,这意味着链接器可以在实际位移允许的情况下缩短多个指令分支或数据引用序列(即使对于内部分支和标签增量,编译器也会进行修正,因为生成的代码的大小可能内部改变!)。
我会看看我是否能找到一些参考,尽管逻辑似乎是有道理的。
来自“MIPS® 程序员架构第 II-A 卷:MIPS32® 指令集,修订版 5.04”,第 142 页(J 指令;第 143 页 JAL 指令)。
编程注意事项:
如果所有程序代码地址都适合在 256MB 边界上对齐的 256MB 区域,则通过连接 PC 和索引位而不是向 PC 添加有符号偏移来形成分支目标地址是一个优势。它允许从区域中的任何地方分支到区域中的任何地方,这是有符号相对偏移量所不允许的操作。
推荐阅读
- go - 为什么 path = os.Getenv("GOMOD"), path = "" 在项目中?
- apache-kafka - Flink 表接收器不适用于 debezium-avro-confluent 源
- windows - 使用 WM_MOUSEMOVE/WM_NCMOUSEMOVE 更新指定区域
- sql-server - Snowflake ODBC 驱动程序和 SQL Server Polybase
- javascript - 计算两个变量字符串之间的字数
- python - 当访问一个方法中更新的类变量时,它的更新值不会在scrapy spider的另一个方法中被拾取
- excel - 如何使用 VBA 将 Outlook 邮件中的“收件人:”字段与预定义的邮件 ID 进行比较?
- r - 如何根据主数据框中的选定特征生成动态汇总表
- swift - 使用 MVVM 架构快速更新数据
- visual-studio - 系统重新启动后,模拟器选项未在 VS 2019 中显示