在 MIPS 中使用 SW 和 LW 访问代码段内存
Posted
技术标签:
【中文标题】在 MIPS 中使用 SW 和 LW 访问代码段内存【英文标题】:Accessing code segment memory using SW and LW in MIPS 【发布时间】:2018-06-06 21:01:04 【问题描述】:在给定指令地址的情况下,是否可以使用 MIPS 中的 SW
和 LW
指令访问代码段内存?
例如:
0x1000: ADDI $s1, $zero, 0x1000
0x1004: LW $s2, 4($s1)
代码会加载到$s2
中吗? 0x0000
(假设数据段为空)或0x1004
处指令的二进制表示?
编辑:
AFAIK,由于指令内存和数据内存的分离,MIPS 处理器中的流水线是可能的 - 如果我错了,请纠正我。
编辑 2:
我找到了question,其答案意味着可以使用LW
和SW
访问和修改指令。因此答案是$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 访问代码段内存的主要内容,如果未能解决你的问题,请参考以下文章