我无法访问.word中的索引。我可以在list: .word 1, 2, 3, 4
时执行此操作,但是当我list: .word 0x12345678
时,我收到错误“获取地址未在字边界上对齐”。这是我的代码:
.data
list: .word 0x12345678
outbuff: .space 40
.text
la $t3, list
la $t5, outbuff
li $t2, 3
add $t5, $t2, $t3
lw $t4, 0($t5)
jr $ra
我不知道为什么我无法访问列表的特定索引。我的最终目标是采用十六进制,如上所述并输出它的二进制表示。如果你能帮我弄清楚如何访问lis的特定索引,那将非常感激。谢谢。
编辑:
.data
list: .word 0x12345678
outbuff: .space 40
.text
la $t3, list
la $t5, outbuff
li $t1, 0
loop:
addi $t1, $t1, 1
beq $t1, 32, end
la $t2, ($t3)
#addi $t2, $t2, 2
lb $t4, 0($t2)
and $t5, $t4, $t1
sll $t2, $t2, 1
j loop
end:
答案 0 :(得分:2)
在MIPS上,您无法从未在字边界上对齐的地址加载单词。这是CPU的限制。
在您的情况下,t5中的地址未对齐 - list
已对齐,但随后您将其添加3。我不知道那是什么3。如果要逐字节处理,可以;但是不要使用lw
。无论如何,这都是非常不理想的。
如果要写出二进制表示,请在list
加载单词,然后使用shift和AND操作逐一从中提取位。
编辑:你错误地假设数字的十六进制表示在编译代码中存活。在编译的代码中,你得到的只是二进制。当您在list
加载单词时,您会在寄存器中获得一个值为0x12345678(十六进制)的整数,该值与305419896(十进制)或10010001101000101011001111000(二进制)相同。
无论如何,手头的任务就是用它来制作一个二进制字符串。赋值应涵盖输出是否应包含前导零。假设前导零是正常的 - 这将使逻辑更容易。
整数在内部存储为位序列。您希望从左到右取每个位,并将其转换为ASCII数字 - “0”或“1”。
为了从一个数字中取一个位,你必须用一个只有这个位的常量执行按位AND运算,AKA是掩码。换句话说,要检查第0位,你用一个1,为了检查第31位,你和0x80000000。如果操作结果为0,则该位开始为零。如果结果非零(实际上,等于掩码本身),则该位为1。
另一个助手是换档操作。它可以让你遍历位。由于你要拼写从左到右的位,我们将检查最左边的位并向左移位。
所以回顾一下:你把你的单词加载到一个寄存器中。您创建了32次迭代的循环。在每次迭代时,检查掩码0x80000000处的位值。根据其值,将“0”或“1”写入输出数组。
我是否应该进一步拼写这个,或者你可以将这样的算法翻译成MIPS汇编?
编辑:代码。
您不必在每次循环迭代时加载变量;在循环之前加载一次。否则不会起作用,因为你正在改变它。 t2的初始值是0x12345678,但是你开始逐个处理位;重新加载该值会破坏这一点。
lb
毫无意义。你已经记住了你的话。
输出数组没有条件写入。你做一个AND,但是以一种非常奇怪的方式。顺便说一句,在你的AND命令中你破坏了t5的值。而且你没有跟进那个AND。应该有某种逻辑在输出数组中存储一个字节,该字节的值取决于AND的结果。
我认为你仍然对list
所代表的内容感到困惑。它是不内存中的数组。它是四个字节,AKA是一个32位字。没有必要循环遍历list
的字节,需要遍历这些位。
整个混乱始于调用变量“list”。这是一个极具误导性的名字;变量不是任何东西的集合,它是一个标量,一个32位整数。
答案 1 :(得分:1)
如果需要访问32位字中的单个字节,则应使用LB
(加载字节)指令:
la $t3, list
la $t5, outbuff
li $t2, 3
addu $t5, $t2, $t3
lb $t4, 0($t5)
LW
(加载字)指令要求地址与4字节字边界对齐。