将覆盖功能从C转换为MIPS程序

时间:2018-03-27 15:58:36

标签: c assembly mips

我的问题是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约定,如果我在程序中使用了参数以正确的方式。

如果有人可以检查代码并查看是否有问题,请提前致谢。

2 个答案:

答案 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*个注册表,因此a0a1会被用作临时工具。

另请注意,添加地址/指针时,我们希望使用add指令的无符号版本(即adduaddiu)来防止[不太可能]溢出异常的可能性。

    .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)

我认为看到合适的编译器做的事情并不太难:

https://godbolt.org/g/PiR8Ds

你将拥有所有的呼叫约定和另外一些东西。

 #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