在 MIPS 中使用 SW 和 LW 访问代码段内存

Posted

技术标签:

【中文标题】在 MIPS 中使用 SW 和 LW 访问代码段内存【英文标题】:Accessing code segment memory using SW and LW in MIPS 【发布时间】:2018-06-06 21:01:04 【问题描述】:

在给定指令地址的情况下,是否可以使用 MIPS 中的 SWLW 指令访问代码段内存?

例如:

0x1000: ADDI $s1, $zero, 0x1000
0x1004: LW $s2, 4($s1)

代码会加载到$s2 中吗? 0x0000(假设数据段为空)或0x1004处指令的二进制表示?

编辑:

AFAIK,由于指令内存和数据内存的分离,MIPS 处理器中的流水线是可能的 - 如果我错了,请纠正我。

编辑 2:

我找到了question,其答案意味着可以使用LWSW 访问和修改指令。因此答案是$s2 将在 0x1004 处包含指令的二进制表示。

【问题讨论】:

MIPS 有设置吗? @old_timer: segments of the executable file (data / text / bss),不是分段内存模型。但是,是的,OP 似乎对程序段与 x86 样式的分段内存(MIPS 没有)感到困惑。 @old_timer 是的,根据谷歌的第一个结果:):cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/dataseg.html 您的意思是写ADDI $s1, $zero, 0x1000?或者只是LW $s2, 0x1004($zero)?否则你的加载地址取决于$s1的初始值。 【参考方案1】:

您将在地址0x1004 处加载指令的机器编码。

MIPS 有一个平坦的内存模型;不同的segments of an executable 被映射/加载到单个平面内存地址空间的不同部分; it's a Von Neumann architecture 其中代码字节和指令字节是同一个东西,共享同一个地址空间。

代码地址与数据地址使用相同的地址空间。 Martin 的回答表明,可以创建一个至少权限不同的 MIPS,当然,其代码在 ROM 中的嵌入式 MIPS 无法通过存储修改其指令。但即便如此,代码和数据也必须映射到同一物理地址空间的不同部分,即使存储到代码地址出错。可能您可以构建一个 MIPS,即使加载的代码地址也会出错,但这不太可能。如果您在该区域/页面上禁用了执行权限,跳转到数据地址也可能会出错。

在普通 MIPS 上,其指令在 RAM 中,self-modifying code is possible 如果您配置了写入+执行权限。 (但请注意,为了正确起见,您通常需要刷新 i-cache,而 Q&A 中的代码没有这样做。)


顺便说一句,asm 源代码中的.data 真正意味着.data section,链接器最终将其链接到可执行文件的数据segment。见What's the difference of section and segment in ELF file format。

这里最重要的一点是可执行文件的段与 x86 样式的分段内存不同。 (不过,该术语的来源相似)。

【讨论】:

AFAIK,由于指令内存和数据内存的分离,MIPS 处理器中的流水线是可能的 - 如果我错了,请纠正我。 @ArieR:你错了。如果我没记错的话,MIPS 不能保证如果你存储到即将执行的指令会发生什么。旧指令或新指令可能会运行。如果您希望存储的数据作为指令可见,则必须在执行之前刷新缓存或其他内容。 (ARM 以这种方式工作:指令缓存和管道与数据存储不一致,并且有 isync 指令或其他东西)。我没有提到这些,因为您只询问负载,并且共享只读访问作为代码和数据是微不足道的。 但是 x86 确实有一致的 I-cache。现代 x86 实现 snoop stores and clear the pipeline if they detect self-modifying code,因此当在程序计数器之前存储几条指令必须对代码提取可见时,甚至可以对 CPU 进行流水线处理。但是,如果没有连贯的代码缓存/管道,流水线架构会容易得多! (所以是的,这是一个问题,但解决方案就是说“如果你想要可预测的结果,就不要这样做”。) 如果你能提供一些在线资源的参考,我会接受这个答案——我很难找到一个 找到了我自己的参考...***.com/questions/29262391/self-modifying-mips-code【参考方案2】:

取决于您对“MIPS”的含义:

像您在某些 WLAN 路由器中找到的真正的 MIPS CPU?

某些 MIPS 仿真器,例如 SPIM 或 MARS?

对于真正的 MIPS CPU,这取决于内存管理单元的配置方式:

如果内存管理单元允许对代码段进行读取访问,您确实会在地址 0x1004 处获得指令的二进制表示。

(顺便说一句:您需要使用addi $s1, $0, 0x1004 来确保$s1 确实包含0x1004,因为$s1 可能包含除0 之外的其他值。)

如果内存管理单元不允许访问代码段,程序将崩溃。 (大多数 MIPS CPU 似乎不允许此设置。)

如果您使用一些模拟器,如 SPIM、MARS(或任何其他),这取决于模拟器的工作方式......

理论上可能有三种类型的模拟器:

一些崩溃 读取二进制表示的一些 有些读到一些“愚蠢”的价值

【讨论】:

MIPS 是否真的允许您设置具有执行但不具有(数据)读取权限的内存区域/页面?您是否还暗示代码获取可能使用与数据不同的地址空间(读取一些“愚蠢”值)?除了使用有问题的模拟器之外,除了阅读说明词之外,我看不出其他任何东西是合理的。 感谢您的回答。我会接受它 - 但我在这里错过了默认行为。在现实世界的 MIPS CPU 中,您期望什么作为默认值? @ArieR:绝对的“默认”期望是您会在地址0x1004 处获得指令的机器编码。 MIPS 有一个平坦的内存模型;可执行文件的不同段被映射/加载到单个平面内存地址空间的不同部分;这是一个冯诺依曼架构,其中代码字节和指令字节是相同的。顺便说一句,asm 源代码中的.data 真正意味着.data 部分,链接器最终将其链接到可执行文件的数据段中。 @PeterCordes 我刚刚查阅了 MIPS R 4400 参考手册,因为我也不知道。据我了解,至少 R 4400 不允许这样做。但是我知道一些 MPU(不是 MIPS),其中 SoC 中的内存保护单元是由不同的供应商设计的。在这种情况下,第 3 方 MPU 可能会保护代码内存不被读取。 @Ped7g:这将是一个错误,IMO。如果模拟器想要缓存解码的指令,它必须在内部进行,而不是在客户内存空间中!我不确定模拟器与模拟器之间是否存在一致同意的具体含义。您是否认为模拟器意味着它只能在 asm-source 级别工作?我想这是一种可能的模拟器,它不能完全模拟 MIPS 机器。

以上是关于在 MIPS 中使用 SW 和 LW 访问代码段内存的主要内容,如果未能解决你的问题,请参考以下文章

设计mips32cpu时,运算指令溢出怎么处理

MIPS,将寄存器中的值放入RAM?

如何在 IDE 之外使用 python 代码

MIPS 到 C 的翻译

MIPS汇编指令集

MIPS 汇编语言,带有 MARS