assembly - 如何使用 MIPS 加载字
问题描述
也许这个问题听起来很愚蠢:)但我有点困惑,有人可以解释为什么代码使用andlw
来将单词从内存加载到寄存器,而0x1b430010
已经在寄存器 $t1 中吗?lui
ori
lui $t1,0x1b43
ori $t1,$t1,0x0010
lui $t2,0xabbb
ori $t2,$t2,0x8050
lw $t0,0($t1)
srl $t0,$t0,6
andi $t0,$t0,0x3
lw $t3,0($t2)
andi $t3,$t3,0xff9f
sll $t0,$t0,5
or $t3,$t3,$t0
sw $t3,0($t2)
解决方案
0x1b430010
以t1
数字(32 位无符号整数)表示,表示内存地址。从直接在指令操作码中编码的部分立即值lui + ori
构建这个常量(每个 MIPS 指令被编码为 32 位字,因此这些位的一部分形成 CPU 称为指令或指令的模式,其余的 16 位 IIRC,形成指令使用的立即数)。t1
lui/ori
lui
ori
lw $t0,0($t1)
完全不同,它会首先使用(t1
由常量“位移”+0修改-即括号前面的“0”)中的值作为内存地址,即CPU将地址总线设置为值0x1b430010,然后它将向内存芯片发出信号,它应该使用这些地址线并从该地址进行内存加载,在总线数据线上设置读取值。一旦内存芯片向 CPU 发出信号,表明数据已被读取并且数据线处于正确状态,CPU 就会将该状态存储为 的新值t0
。
简而言之,它会将地址 0x1b430010 的计算机内存中的字加载到寄存器t0
中 - 但是存储在内存中的实际值是什么,这无法从您的简短片段中看出。
JFYI:MIPS 上的内存可按字节寻址(地址总线是 28 位还是 30 位宽?还是全 32 位?可能取决于特定的目标硬件 = 地址总线的宽度定义了您可以寻址的最大区域,即它限制了最大可能的内存在 CPU 地址空间中可用)。因此,通过设置特定地址,您可以读取/修改任何字节的内存(只要您有足够的权限,并且它不是只读内存,或者任何内存芯片未映射的空白空间)。
有一个小问题,加载/存储字指令要求(以使内存管理单元的硬件设计更简单)内存地址是“字对齐”的,即可被 4 整除(等于“底部两位为零”)。与读取半字类似,存储器地址必须是半字对齐的(可被 2 整除 = 底部地址位为零)。如果您正在使用未对齐的数据缓冲区,则必须按单个字节加载它(并从四个字节读取中组合字值),以避免由于使用lw
错误的地址而导致未对齐的内存访问崩溃。
值 0x1b430010 可以被 4 整除(后四位为零,而两个就足够了,这实际上可以被 16 整除),并且该内存地址可能指向.data
区域,因此lw
从那里执行应该没有问题。
推荐阅读
- discord.py - 如何实现暂停命令(lavalink)?
- javascript - event.stopPropagation() 不起作用 - 捕获仍然传递函数
- php - 仅在 WooCommerce 前端将小数样式化为大写
- android - activity1 内部的 fragment1 和 activity2 内部的 fragment2 之间的共享转换
- c - 编写函数以返回大小有限的字符串数组的最佳方法(char *x [MAX] vs char **x)?
- c# - Process.Start 在尝试打开带有超链接的网站时抛出异常
- javascript - 使用原始 JavaScript 将音频添加到购物车
- regex - notepad++ 行合并
- javascript - 如何将 jQuery 中的 scrollTop 转换为 JavaScript?
- python - 在 Python 中解码/编码 html 转义的特殊字符