也许这个问题听起来很愚蠢:),但我有点困惑,有人可以解释为什么lw
已经在寄存器$ t1中时,代码为什么使用0x1b430010
从存储器中加载单词进行寄存器了吗? 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)
答案 0 :(得分:1)
0x1b430010
在t1
中为数字(32位无符号整数),代表内存地址。 lui + ori
根据t1
指令操作码中直接编码的部分立即值在lui/ori
中建立此常量(每个MIPS指令均编码为32位字,因此这些位的一部分形成了一个已知的模式CPU作为lui
指令或ori
指令,其余的16位IIRC构成该指令要使用的立即值。
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
区域,因此请执行{{ 1}}应该可以正常工作。