我的问题是MIPS中的程序和使用参数。
我试图将这个小C函数转换为MIPS,但我不确定我是否在正确的轨道上。这是C函数:
0 int countNegatives(int table[] , int n) {
1 int count = 0;
2 int i;
3
4 for (i=0; i<n; i++) {
5 if (table[i] <0) {
6 count++;
7 }
8 }
9
10 return count;
11 }
这就是我对MIPS的看法
main:
jal countNegatives
countNegatives:
li $t0, 0 #count = 0
li $t1, 0 #i = 0
loop:
bge $t1, $a1, endloop
sll $t2, $t1, 2 #$t2 = 4*i
add $t2, $a0, $t2 #$t2 = &table[i]
lw $t3, 0($t2) #temp = table[i]
bge $t3, $zero, endif
addi $t0, $t0, 1 #counter++
endif:
addi $t1, $t1, 1 #i++
endloop:
jr $ra
我的代码并不真正在QTSpim上运行,所以我也试图知道我是否缺少任何MIPS约定,如果我在程序中使用了参数以正确的方式。
如果有人可以检查代码并查看是否有问题,请提前致谢。
答案 0 :(得分:2)
除了一些遗漏的样板,你非常接近。这是一个用错误注释的版本:
main:
# NOTE/BUG: a0/a1 are _not_ set up for the call
jal countNegatives
# NOTE/BUG: we just fall through into countNegatives again [which is bad]
countNegatives:
li $t0,0 # count = 0
li $t1,0 # i = 0
loop:
bge $t1,$a1,endloop
sll $t2,$t1,2 # $t2 = 4*i
add $t2,$a0,$t2 # $t2 = &table[i]
lw $t3,0($t2) # temp = table[i]
bge $t3,$zero,endif
addi $t0,$t0,1 # counter++
endif:
addi $t1,$t1,1 # i++
# NOTE/BUG: we need to loop here
endloop:
jr $ra
这是一个工作版本[带有添加的样板]:
.data
arr: .word 10 20 -5 7 -6 0 1 -1 37
.text
.globl main
main:
la $a0,arr # point to array
li $a1,9 # array count
jal countNegatives
move $a0,$v0
li $v0,1
syscall
li $v0,10
syscall
# countNegatives -- count number of negatives
#
# RETURNS:
# v0 -- number of negative numbers found
#
# arguments:
# a0 -- pointer to array
# a1 -- array count
#
# temporaries:
# t1 -- index variable "i"
# t2 -- array offset / &table[i]
# t3 -- temp (value of table[i])
countNegatives:
li $v0,0 # count = 0
li $t1,0 # i = 0
loop:
bge $t1,$a1,endloop # i >= count? if yes, fly
sll $t2,$t1,2 # $t2 = 4*i
addu $t2,$a0,$t2 # $t2 = &table[i]
lw $t3,0($t2) # temp = table[i]
bge $t3,$zero,endif
addi $v0,$v0,1 # counter++
endif:
addi $t1,$t1,1 # i++
j loop
endloop:
jr $ra
这是一个有趣的版本,使用slt
代替条件分支[并消除了循环中的额外跳转]:
.data
arr: .word 10 20 -5 7 -6 0 1 -1 37
.text
.globl main
main:
la $a0,arr # point to array
li $a1,9 # array count
jal countNegatives
move $a0,$v0
li $v0,1
syscall
li $v0,10
syscall
# countNegatives -- count number of negatives
#
# RETURNS:
# v0 -- number of negative numbers found
#
# arguments:
# a0 -- pointer to array
# a1 -- array count
#
# temporaries:
# t1 -- index variable "i"
# t2 -- array offset / &table[i]
# t3 -- temp (value of table[i])
countNegatives:
li $v0,0 # count = 0
li $t1,0 # i = 0
j loop_start # start the loop
loop:
sll $t2,$t1,2 # $t2 = 4*i
addu $t2,$a0,$t2 # $t2 = &table[i]
lw $t3,0($t2) # temp = table[i]
slt $t3,$t3,$zero # temp = (temp < 0)
add $v0,$v0,$t3 # counter += temp
addi $t1,$t1,1 # i++
loop_start:
blt $t1,$a1,loop # i < count? if yes, fly
jr $ra
这是另一个使用指针算法而不是索引变量的版本。
请注意,在mip ABI下,被叫方只能保留s*
个注册表,因此a0
和a1
会被用作临时工具。
另请注意,添加地址/指针时,我们希望使用add
指令的无符号版本(即addu
和addiu
)来防止[不太可能]溢出异常的可能性。
.data
arr: .word 10 20 -5 7 -6 0 1 -1 37
.text
.globl main
main:
la $a0,arr # point to array
li $a1,9 # array count
jal countNegatives
move $a0,$v0
li $v0,1
syscall
li $v0,10
syscall
# countNegatives -- count number of negatives
#
# RETURNS:
# v0 -- number of negative numbers found
#
# arguments:
# a0 -- pointer to array (ptr)
# a1 -- array count
#
# temporaries:
# a1 -- array limit (endp)
# t3 -- temp (value of table[i])
countNegatives:
li $v0,0 # count = 0
sll $a1,$a1,2 # get byte offset
addu $a1,$a0,$a1 # endp = &arr[count]
j loop_start # start the loop
loop:
lw $t3,0($a0) # temp = *ptr
slt $t3,$t3,$zero # temp = (temp < 0)
add $v0,$v0,$t3 # counter += temp
addiu $a0,$a0,4 # ptr += 4
loop_start:
bne $a0,$a1,loop # ptr != endp? if yes, fly
jr $ra
因此,最终的asm版本,转换回C看起来像这样:
int
countNegatives(int *table, int n)
{
int *endp;
int count = 0;
endp = &table[n];
for (; table != endp; ++table)
count += (*table < 0);
return count;
}
答案 1 :(得分:0)
我认为看到合适的编译器做的事情并不太难:
你将拥有所有的呼叫约定和另外一些东西。
#include <stdio.h>
int __attribute__((noinline)) countNegatives(int table[] , int n) {
int count = 0;
int i;
for (i=0; i<n; i++) {
if (table[i] <0) {
count++;
}
}
return count;
}
volatile int x[] = {454,-3,-5343,-3434,4534};
int main(void)
{
printf("%d\n",countNegatives((int *)x, sizeof(x)/sizeof(x[0])));
}
countNegatives:
blez $5,$L6
sll $5,$5,2
addu $5,$4,$5
move $2,$0
$L5:
lw $3,0($4)
addiu $4,$4,4
slt $3,$3,0
bne $4,$5,$L5
addu $2,$2,$3
j $31
nop
$L6:
j $31
move $2,$0
$LC0:
.ascii "%d\012\000"
main:
lui $4,%hi(x)
addiu $sp,$sp,-32
li $5,5 # 0x5
sw $31,28($sp)
jal countNegatives
addiu $4,$4,%lo(x)
lui $4,%hi($LC0)
move $5,$2
jal printf
addiu $4,$4,%lo($LC0)
lw $31,28($sp)
move $2,$0
j $31
addiu $sp,$sp,32
x:
.word 454
.word -3
.word -5343
.word -3434
.word 4534