访问.word Mips汇编语言的索引

时间:2014-03-19 18:54:31

标签: assembly alignment mips mars-simulator

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

2 个答案:

答案 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字节字边界对齐。