了解MIPS算法

时间:2017-06-03 19:24:08

标签: mips mips32

我对编码很新,我们从MIPS开始。我们有点“投入到冷水中”并且必须实现一种算法,该算法检查数组的元素是否按升序排序。如果它已排序,则1将存储在$ v0中,否则为0。 给我们的解决方案:

.data
A: .word 1, 2, 3, 4, 5
l: .word 5

.text
main:
la $s0, A #address of A
lw $s1, l
add $t0, $0, $0 #counter for loop
addi $v0, $0, 1
sub $s1, $s1, $v0
for:
beq $t0, $s1, done
sll $t1, $t0, 2 #byte offset
add $t1, $t1, $s0
lw $t1, 0($t1) #$t1 = A[j]
addi $t2, $t0, 1
sll $t2, $t2, 2
add $t2, $t2, $s0
lw $t2, 0($t2) #$t2 = A[j + 1]
sub $t3, $t2, $t1 #$s3 = A[j+1] - A[j]?
slt $t4, $t3, $0
addi $t3, $0, 1
beq $t3, $t4 unsort #A isn’t sorted if A[j+1] - A[j] has a negative value
addi $t0, $t0, 1 #$t0 = $t0 + 1
j for

unsort:
add $v0, $0, $0 #set $v0 if array isn’t sorted

done:

我无法理解这段代码/算法。首先是什么是数组,为什么我们需要具体的5个呢? 但对我来说更重要的是理解这个代码/算法。所以我需要一个善良的人,并一步一步地用简单的词语向我解释:D,这段代码的工作原理。

非常有帮助,并提前感谢。

1 个答案:

答案 0 :(得分:1)

简短回答

基本上,这个程序在循环计数器的循环中迭代数组A,比如i。索引i初始化为0,并且在每次循环迭代中递增1,直到达到l-1,其中l是数组A的大小/长度。在每次迭代中,算法检查是否A[i] < A[i + 1](即,如果A中的第i个和第(i + 1)个元素是按升序排序并因此被排序)。如果是,则继续执行,$v0保持为1.否则,它将$v0设置为0并终止。

长答案

数组和内存

数组基本上是一个有序的数据列表 - 在这种情况下,它是一个有序的字列表(MIPS中的一个字表示:32位值,它由4个字节组成,每个其中有8位信息)。所以在这种情况下,每个单词代表一个32位整数 如果我们有一个长度为A的数组l,则元素会从0索引到l-1。数组A中的第一个元素(符号:A[0])保存在内存中的某个地址,我们称之为addr。然后AA[i])中的第i个元素保存在内存地址addr + 4*i中。这是因为MIPS中的存储器是字节可寻址的,即每个字节都有自己的地址,并且由于一个字由4个字节组成,所以字地址偏移4(见下文)。

byte-addressable memory

.data部分

A: .word 1, 2, 3, 4, 5
l: .word 5

有了这个,你会发现你没有5个数组但只有一个(称为A)并且它包含值1,2,3,4和5.因此,长度为5,它在l一词中指定。你可以为你的数组添加更多的值,但是你必须调整长度,否则会发生奇怪的事情(或者至少结果是随机的)。您的数据在此.data部分中指定,因此存储在程序的内存空间中。

MIPS汇编

为了理解.text部分中的代码,您必须了解MIPS程序集。如果我写一个寄存器,只需将其视为32位值的占位符。例如,$ 0是零寄存器,它总是存储一个32位0.其他寄存器用于临时存储程序中使用的值。您使用的说明是:

  • la rd,label(“加载地址”)
    (rd =标签的地址;存储目的地寄存器rd中“label”指定的字的地址)
  • lw rd,label(“加载字”)

    lw rd,offset(rs)
    (将标签指定的数据或地址rs + offset的数据加载到目标寄存器rd)
  • 添加 rd,rs,rt
    (rd = rs + rt;添加源寄存器rs和rt并将结果存储在目标寄存器rd中)
  • addi rd,rs,imm(“立即添加”)
    (rd = rs + imm;添加源寄存器rs和立即(16位常量)值并将结果存储在目标寄存器rd中)
  • sub rd,rs,rt(“减去”)
    (rd = rs - rt;从源寄存器rs中减去源寄存器rt并将结果存储在目标寄存器rd中)
  • beq rs,rt,label(“branch if equal”)
    (如果rs中的值等于rt中的值,则跳转到标签)
  • sll rd,rs,shamt(“shift logic left”)
    (rd = rs&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;
  • slt rd,rs,rt(“设置小于”)
    (rd =(rs&lt; rt)?1:0;如果rs中的值小于rt中的值,则将rd设置为32位1,否则设置为32位0)
  • j 标签(“跳转”)
    (跳转到标签)

.text部分

main:
la $s0, A
lw $s1, l
add $t0, $0, $0
addi $v0, $0, 1
sub $s1, $s1, $v0

for:
beq $t0, $s1, done
sll $t1, $t0, 2 #byte offset
add $t1, $t1, $s0
lw $t1, 0($t1) #$t1 = A[j]
addi $t2, $t0, 1
sll $t2, $t2, 2
add $t2, $t2, $s0
lw $t2, 0($t2) #$t2 = A[j + 1]
sub $t3, $t2, $t1 #$s3 = A[j+1] - A[j]?
slt $t4, $t3, $0
addi $t3, $0, 1
beq $t3, $t4 unsort #A isn’t sorted if A[j+1] - A[j] has a negative value
addi $t0, $t0, 1 #$t0 = $t0 + 1
j for

unsort:
add $v0, $0, $0 #set $v0 if array isn’t sorted

done:

这个汇编代码等同于伪代码(如果您不习惯伪代码或while循环,请在互联网上查找):

s0 <- address of first element in A
s1 <- l
t0 <- 0
v0 <- 1
s1 <- s1-1

while (t0 != s1) do
    t1 <- 4 * t0
    t1 <- t1 + s0
    t1 <- word at address t1
    t2 <- t0 + 1
    t2 <- 4 * t2
    t2 <- t2 + s0
    t2 <- word at address t2
    t3 <- t2 - t1
    if (t3 < 0) then t4 <- 1
    else t4 <- 0
    t3 <- 1
    if (t3 == t4) then
        v0 <- 0
        return
    else t0 <- t0 + 1

希望,这有帮助。如果您之前没有编码,我认为从汇编代码开始是非常雄心勃勃的。祝你好运!