0

我无法访问 .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:
4

2 回答 2

2

在 MIPS 上,您不能从未在字边界上对齐的地址加载字。这就是CPU的限制。

在您的情况下, t5 中的地址未对齐 -list已对齐,但随后您将 3 添加到其中。我不明白那是什么 3。如果要逐字节处理,可以;但不要使用lw。无论如何,这将是非常不理想的。

如果您想写出二进制表示,请加载单词 atlist并使用移位和 AND 操作从其中一位一位地提取位。

编辑:您错误地假设数字的十六进制表示形式在编译代码中仍然存在。在编译后的代码中,你得到的只是二进制文件。当您在 处加载单词时list,您会在寄存器中获得一个值为 0x12345678(十六进制)的整数,它与 305419896(十进制)或 10010001101000101011001111000(二进制)相同。

无论如何,手头的任务是用它制作一个二进制字符串。分配应涵盖输出是否应包含前导零。让我们假设前导零是可以的 - 这将使逻辑更容易。

整数在内部存储为位序列。您希望从左到右获取每一位,并将其转换为 ASCII 数字 - “0”或“1”。

为了从一个数字中取出一个位,您必须对一个只有这个位的常量执行按位与运算,也就是掩码。换句话说,要检查第 0 位,您与 1 进行与,为了检查第 31 位,您与 0x80000000 进行与。如果运算结果为 0,则该位开始时为 0。如果结果不为零(实际上等于掩码本身),则该位为 1。

另一个助手是移位操作。它使您可以循环访问位。由于您想从左到右拼出位,我们将检查最左边的位并左移。

所以回顾一下:你把你的词加载到一个寄存器中。您创建了一个包含 32 次迭代的循环。在每次迭代中,您检查掩码 0x80000000 处的位值。根据其值,您将“0”或“1”写入输出数组。

我是否应该进一步说明这一点,或者您可以将这样的算法翻译成 MIPS 程序集?

编辑重新:代码。

您不必在每次循环迭代时都加载变量;在循环之前加载一次。否则不会工作,因为你正在改变它。t2 的初始值为 0x12345678,但随后你开始一个一个地处理比特;重新加载值会破坏它。

lb是没有意义的。你已经记住了你的话。

输出数组中没有条件写出。你做了一个 AND,但是以一种完全奇怪的方式。顺便说一句,在您的 AND 命令中,您正在破坏 t5 的值。而且你没有跟进那个AND。应该有某种逻辑在输出数组中存储一个字节,该字节的值取决于 AND 的结果。

而且我认为您仍然对所list代表的内容感到困惑。它不是内存中的数组。它是四个字节,也就是一个 32 位字。不需要遍历 的字节list,需要遍历位。

整个混乱始于调用变量“列表”。这是一个极具误导性的名字。该变量不是任何东西的集合,它是一个标量,一个 32 位整数。

于 2014-03-19T19:31:42.990 回答
1

如果您需要访问 32 位字中的单个字节,您应该使用LB(load byte) 指令:

la   $t3, list
la   $t5, outbuff
li   $t2, 3
addu $t5, $t2, $t3
lb   $t4, 0($t5)

LW加载字)指令要求地址与 4 字节字边界对齐。

于 2014-03-19T19:35:31.603 回答