将以下C函数重写为具有相同行为的汇编语言子例程

时间:2017-03-02 12:33:50

标签: assembly mips delay

let a: IScreen
let b: IModal
let c: IModal = a // type '{}' ('IScreen') is compatible to type '{}' ('IModal')
let d = {}
let e: IModal = d // type '{}' is compatible to type '{}' ('IModal')

我已将此转换为以下内容,此子例程是更大的子例程。

void delay( int ms ) /* Wait a number of milliseconds, 
                     specified by the parameter value. */
{
    int i;
    while( ms > 0 )
   {
        ms = ms – 1;
          /* Executing the following for loop should take 1 ms */
   for( i = 0; i < 4711; i = i + 1 ) 
          /* The constant 4711 must be easy to change! */
   {
          /* Do nothing. */
   }
  }
}

使用MARS测试您的程序。调整for循环中的常量以获得1000 ms的延迟 当使用参数值1000调用延迟时,以及调用延迟时延迟3000 ms 参数值为3000。

Q1:所以我不确定我是否正确转换了它。

Q2:如何调整该常数以获得延迟量。

任何建议,提示都会很棒。谢谢。

1 个答案:

答案 0 :(得分:1)

我没有考虑关于空的可观察行为的所有大惊小怪,因为我认为这是一个错误的命令文本的装配练习。

因此,前面我假装代码不是C而是一种名为 C伪代码的新语言,其语法类似于C语法和语义,其中每个语句都有可观察到的副作用。

汇编代码不正确 我不会纠正你的错误或编写任何代码,我只是将的一些指出来。

for

的实施
# $s0 = i
# $t1 = 4711

for:
  beq     $s0,$t1,done
  addi    $s0,$s0,1
j       for

至少有两个问题:

  1. 退出时跳至done 这也对应于退出while循环,而C伪代码中的for在退出时执行while的另一次迭代。
  2. 注册表$s0永远不会重新初始化 计数器iwhile的每次迭代中初始化 - 您的实现,而不是在开始时执行一次。
  3. while条件的实施是

    # $s0 = i
    # $t0 = ms
    
    bgt $t0, $s0, done        #branch to done if ms > 0
    

    您可以在评论的帮助下看到自己与代码所在的ms > i对应。
    在MIPS中,您有一个始终为零的寄存器。

    一些提示:

    • 您可以避免使用任何$s注册。
      有足够的$t个寄存器 - 保存$s会立即让读者想到内部调用,而代码中没有。

    • 以简单的形式编写C伪代码。
      您可以将for重写为

      i = 0;
      for_begin:
         if (i >= 4711)
            goto for_end
      
            /* FOR BODY */
      
            i = i + 1;
      goto for_begin
      
      for_end:
      

      这应该更容易转化为装配。