Assembly MIPS寄存器$0能否用于存储和检索值?
当我了解到MIPS处理器时,我的脑海中突然闪现出这样一个事实:对$0寄存器的读取总是返回0,而对$0的写入总是被丢弃。从MIPS程序员手册: 2.13.4.1 CPU通用寄存器 [...] r0硬连接到的值为 零,并且可以用作任何指令的目标寄存器 结果将被丢弃。r0也可以用作零时的源 价值是必需的 由此可知,指令Assembly MIPS寄存器$0能否用于存储和检索值?,assembly,mips,glibc,Assembly,Mips,Glibc,当我了解到MIPS处理器时,我的脑海中突然闪现出这样一个事实:对$0寄存器的读取总是返回0,而对$0的写入总是被丢弃。从MIPS程序员手册: 2.13.4.1 CPU通用寄存器 [...] r0硬连接到的值为 零,并且可以用作任何指令的目标寄存器 结果将被丢弃。r0也可以用作零时的源 价值是必需的 由此可知,指令或$0、$r31、$0是不可操作的 想象一下,当我翻阅ELF MIPS二进制文件的启动代码时,当我看到以下指令序列时,我会感到惊讶: 00000610 03 E0 00 25 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
这一切似乎都毫无意义:当只执行0x628就足够了时,为什么还要执行语句0x610呢。glibc的人在编写这段代码时显然有一些意图。似乎$0毕竟是可写和可读的
那么,在什么情况下,程序可以像读/写其他通用寄存器一样读/写$0寄存器呢
编辑:
查看glibc源代码没有帮助。\u启动的代码
使用宏:
注意这里是如何故意指定$0的。SETUP_GPX宏定义如下:
“保存旧ra”清楚地表明了保存寄存器的意图,但为什么是$0?它使用的是
$0
,因为在入口点没有理由保存$ra
,所以它被丢弃了。由于它是来自宏的手工编写的asm代码,因此没有像通常情况下那样进行优化。注意,glibc仅将此用于PIC。(见附件)
MIPS
jal
(与其他j
指令一样)不是PIC;它用imm26替换了PC的低28位,这没有什么明显的意义,但是glibc是开源的,所以也许可以检查一下它是从哪里来的?我有过,但代码没有解释为什么要写入$0而不是其他临时寄存器。它是glibc中手工编写的asm吗?你有链接吗?如果没有源代码,这可能只是你正在反汇编的数据,就像它是指令一样。需要确认来源我已经添加了问题来源的链接和副本。我理解bal
部分;它的x86对应项是call$+5;弹出ebx
序列,用于在ebx
中构建全局指针。在bal
之前写入$0似乎毫无意义,这让我很困惑。@JohnKällén:好吧,如果$0
不总是读取为0,bal
不可能是bgezal$0
的伪指令。我认为值得向未来的读者指出,他们想知道在$0
上有条件分支的意义是什么,作为Jester对你真正问题正确答案的补充。
ENTRY_POINT:
# ifdef __PIC__
SETUP_GPX($0)
...
# 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