MIPS 寄存器 $0 可以用来存储和检索值吗?

2024-03-07

当我了解 MIPS 处理器时,我的脑海中牢记着读取 $0 寄存器总是返回 0,而写入 $0 总是被丢弃。来自 MIPS 程序员手册:

2.13.4.1 CPU 通用寄存器 [...] r0 被硬连线到一个值 零,并且可以用作任何指令的目标寄存器 结果是被丢弃。 r0 也可以用作零时的源 需要价值。

由此可见,说明or $0,$r31,$0是一个空操作。

想象一下,当我在查看 ELF MIPS 二进制文件的启动代码时,看到以下指令序列,我会感到多么惊讶:

00000610 03 E0 00 25   or     $0,$ra,$0
00000614 04 11 00 01   bgezal $0,0000061C
00000618 00 00 00 00   nop
0000061C 3C 1C 00 02   lui    $28,+0002
00000620 27 9C 84 64   addiu  $28,$28,-00007B9C
00000624 03 9F E0 21   addu   $28,$28,$ra
00000628 00 00 F8 25   or     $ra,$0,$0

地址 0x610 处的指令将 $ra 的值复制到 $r0 中,根据上面的段落,这相当于丢弃它。然后,地址 0x628 处的指令从 $0 读回值,但由于 $0 硬连线为 0,因此导致将 $ra 设置为 0。

这一切看起来毫无意义:为什么要执行语句 0x610,而只执行 0x628 就足够了。 glibc 人员在编写这段代码时显然有一些意图。看来 $0 毕竟是可写和可读的!

那么在什么情况下程序可以像读取其他通用寄存器一样读取/写入 $0 寄存器呢?

编辑: 查看 glibc 源代码没有帮助。代码为__start使用宏:

https://github.com/bminor/glibc/blob/master/sysdeps/mips/start.S#L80 https://github.com/bminor/glibc/blob/master/sysdeps/mips/start.S#L80

ENTRY_POINT:
# ifdef __PIC__
    SETUP_GPX($0)
...

请注意这里是如何特意指定 $0 的。 SETUP_GPX 宏定义如下:

https://github.com/bminor/glibc/blob/master/sysdeps/mips/sys/asm.h#L75 https://github.com/bminor/glibc/blob/master/sysdeps/mips/sys/asm.h#L75

# define SETUP_GPX(r)                           \
        .set noreorder;                         \
        move r, $31;     /* Save old ra.  */     \
        bal 10f; /* Find addr of cpload.  */    \
        nop;                                    \
10:                                             \
        .cpload $31;                             \
        move $31, r;                             \
        .set reorder

“Save old ra”清楚地表明了保存寄存器的意图,但为什么是$0?


它正在使用$0因为在入口点没有理由保存$ra,所以它被丢弃了。由于它是来自宏的手写 asm 代码,因此它没有像通常情况那样进行优化。

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

MIPS 寄存器 $0 可以用来存储和检索值吗? 的相关文章

  • 汇编编程语言:程序仅当输入为 ESC 时退出,并在退出前要求确认(y/n),否则循环

    我只是汇编语言编程的初学者 我们的第一个任务是让程序仅在输入为 ESC 时退出 退出之前请求确认 y n 否则循环 我知道 ESC 在 ASCII 代码中具有等效值 但我对插入位置或是否需要添加更多内容感到困惑 请帮我 这是程序 model
  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • DASM 汇编器中的 ASCII 到 C64 屏幕代码

    我正在通过 C64 模拟器学习 6502 micro 的汇编 目前正在尝试将字符串输出到屏幕 这是我的代码 processor 6502 org 1000 ldx 00 using x register as column counter
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 汇编指令陷阱有什么作用?

    当程序需要时 程序通常会发出软件陷阱 由操作系统提供服务 通用异常处理程序 操作系统确定陷阱的原因并做出响应 适当地 汇编指令 trap 和 BASIC 中的 TRAP 指令一样吗 答案似乎是肯定的 你能接受还是拒绝我的结论 不中断 的代码
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 这段汇编语言代码是什么意思?

    我是一名学生 刚刚开始学习汇编语言 为了更好地理解它 我只是用 C 写了一个简短的代码并将其转换为汇编语言 奇怪的是我有点听不懂 代码是 include
  • “损坏的双链表”是什么意思

    我最近从我的 PHP 中收到以下错误 WARNING pool www child 42475 said into stderr glibc detected php fpm pool www corrupted double linked
  • Visual Studio 2017 上的简单装配程序

    386 model flat c stack 100h printf PROTO arg1 Ptr Byte data msg1 byte Hello World 0Ah 0 code main proc INVOKE printf ADD
  • 近调用/跳转表并不总是在引导加载程序中工作

    一般问题 我一直在开发一个简单的引导加载程序 并在某些环境中偶然发现了一个问题 在这些环境中 此类指令不起作用 mov si call tbl SI Call table pointer call call tbl Call print c
  • 为什么 RISC-V S-B 和 U-J 指令类型以这种方式编码?

    我正在读一本书 计算机组织与设计RISC V版 我遇到了 S B 和 U J 指令类型的编码 我上面提到的那些类型有奇怪的编码立即字段 S B 类型将直接字段分为两部分 这是有道理的 因为所有指令编码都必须相似 但我无法理解为什么立即字段以
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 汇编8086监听键盘中断

    我有与此完全相同的问题 边画边听键盘 https stackoverflow com questions 13970325 8086 listen to keyboard while drawing 但第一个答案 接受的答案 只听键盘一次
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 弹出 x86 堆栈以访问函数 arg 时出现分段错误

    我正在尝试链接 x86 程序集和 C 我的C程序 extern int plus 10 int include
  • 从 exe 文件中获取汇编级代码?

    我当时正在做linux汇编编程 在过去的几天里我已经转而学习windows汇编编程 我在用ml作为我的汇编器和golink作为我的链接器 我有我的汇编代码并已获得我的exe从中 现在我需要取回它的十六进制 xff xab x55等等 在li
  • 程序集比较标志理解

    我正在努力理解汇编程序中的以下代码片段 if EAX gt 5 EBX 1 else EBX 2 在汇编程序中 可以写如下 根据我的书 模拟jge操作说明 https www felixcloutier com x86 jcc您通常会使用
  • 使用 MIPS 从 Big Endian 到 Little Endian 无需逻辑运算?

    我正在使用 MIPS QtSpim 将 32 位字从 Big Endian 转换为 Little Endian 我下面显示的内容已检查且正确 不过我想知道还有什么其他方法可以让我进行转换 我虽然只使用了旋转和移位 但如果没有逻辑运算 我就无
  • MikeOS 引导加载程序中的堆栈段

    我不明白这段代码 mov ax 07C0h Set up 4K of stack space above buffer add ax 544 8k buffer 512 paragraphs 32 paragraphs loader cli
  • X86 预取优化:“计算 goto”线程代码

    我有一个相当重要的问题 我的计算图有循环和多个 计算路径 我没有制作一个调度程序循环 其中每个顶点将被一一调用 而是将所有预先分配的 框架对象 放置在堆中 代码 数据 这有点类似于线程代码 甚至更好 CPS 只是在堆中跳转 执行代码 每个代

随机推荐

  • 使用以位集作为键的映射时出现问题

    我正在尝试创建一个map在 C 中bitset作为钥匙 但是编译器会生成以下错误消息 In file included from usr include c 4 6 string 50 0 from usr include c 4 6 bi
  • Presto 中的用户定义函数

    我目前正在使用 Presto 0 80 我必须编写一个用户定义的函数来在选择查询期间将摄氏度转换为华氏度 我使用 Hive QL 做了同样的事情 但想知道我们是否可以在 Facebook Presto 中复制相同的内容 任何帮助将不胜感激
  • GAE组织数据结构问题

    好的 我正在与 GAE 合作 我想创建这样的东西 我有类型 组 主题 标签 每个 组 可以有尽可能多的 根据需要 主题 每个 主题 可以有任意多个 标签 如所须 每个 组 可以有任意多个 标签 如所须 它就像一个圆圈 现在我有这样的事情 c
  • QuickDraw 中的 python3 递归动画

    我有一个文本文件 其中包含行星及其相应的卫星 卫星以及它们的轨道半径和周期 我想用它来创建动画quickdraw类似于下面的 文本文件如下 RootObject Sun Object Sun Satellites Mercury Venus
  • 如何通过 Golang 的 json 解组嵌套数组中的对值

    JSON 数据如下 xxx xxx asks 0 00000315 1022 53968253 0 00000328 200 0 00000329 181 70008541 bids 0 00000254 2685 36319716 0 0
  • _PFBatchFaultingArray 对象索引:

    2012 06 15 17 53 25 532 BadgerNew 3090 707 Terminating app due to uncaught exception NSRangeException reason PFBatchFaul
  • 两个不同表中任意一个的参考键[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有以下两个表 employees id name address designation salary phone email bu
  • 使用MVC设计模式时如何加载重型模型

    我正在使用 wxPython 和使用 Tensorflow 创建的深度学习模型构建一个应用程序 我使用的设计模式是MVC 我的问题是深度学习模型非常重 需要很长时间才能加载 大约 2 分钟 同时 GUI 会挂起 我创建了一个描述该过程的示例
  • Typescript 中 `typeof x` 的类型是什么?

    在打字稿中 您可以像这样定义一个类 class Sup static member any static log console log sup 如果您执行以下操作 let x Sup 为什么 x 的类型等于typeof Sup 当我在 v
  • 以管理员身份运行与管理员组运行

    我有一个 C 应用程序 需要允许用户更改计算机名称 这是一项相当特权的操作 仅当用户以管理员身份运行应用程序 Windows 7 右键单击可执行文件 以管理员身份运行 时 我才能使其正常工作 很好 但是用户是管理员 那么为什么他们需要运行A
  • NSAttributedString initWithHTML 字符编码不正确?

    NSMutableAttributedString initWithHTML documentAttributes 似乎破坏了特殊字符 NSString html Hello World notice the smart quotes NS
  • C 三元表达式语句不起作用[重复]

    这个问题在这里已经有答案了 include
  • C# 中的 Xml 比较

    我正在尝试使用 C 代码比较两个 Xml 文件 我想忽略 Xml 语法差异 即前缀名称 为此我正在使用微软的C API 它适用于某些 Xml 但我找不到将其配置为与以下两个 Xml 一起使用的方法 XML A
  • 如何打开一个文件以进行读和写?

    有没有办法打开一个文件进行读取和写入 作为解决方法 我打开文件进行写入 关闭它 然后再次打开它进行读取 但是有没有办法打开文件both读写 以下是如何读取文件 然后写入文件 覆盖任何现有数据 而无需关闭并重新打开 with open fil
  • jQuery的toggleClass回调如何进行?

    我有这个简单的 jQuery 事件toggleClass this on click function this toggleClass fa stop circle 我想调用一些方法 如果fa stop circle被添加 我如何监控此事
  • Docker:从另一台服务器的私有注册表中提取问题

    我刚刚开始学习docker 我有一个在一台服务器 server1 上运行的私有注册表 并且可以通过键入以下内容从 server1 上提取测试映像 docker pull 127 0 0 1 5000 test 但是 当我从另一台服务器键入上
  • libgdx Shaperenderer line ..如何绘制特定宽度的线

    我正在尝试使用 libgdx 形状渲染器绘制一条特定宽度的线 我跟着这个link https stackoverflow com questions 18650619 increasing the width of line drawn u
  • R - 图中线交点的坐标

    的结构data是以下 df1 lt structure list V2 1 10 V1 c 1 4 1 5 1 9 4 5 6 7 7 8 8 1 8 2 8 3 8 9 class data frame row names c NA 10
  • 计算位数 - 哪种方法最有效?

    查找给定数字中的位数有不止一种解决方案 例如 方法一 int findn int num char snum 100 sprintf snum d num return strlen snum 方法2 int findn int num i
  • MIPS 寄存器 $0 可以用来存储和检索值吗?

    当我了解 MIPS 处理器时 我的脑海中牢记着读取 0 寄存器总是返回 0 而写入 0 总是被丢弃 来自 MIPS 程序员手册 2 13 4 1 CPU 通用寄存器 r0 被硬连线到一个值 零 并且可以用作任何指令的目标寄存器 结果是被丢弃