【问题标题】:Can this MIPS assembly code be simplified? [closed]这个 MIPS 汇编代码可以简化吗? [关闭]
【发布时间】:2020-07-02 15:02:39
【问题描述】:

我正在尝试编写一个函数,用最少的动态指令计算字符串的长度。这是我现在所拥有的:

strlen:
    li      $v0, 0                  # len = 0

top:  
    lbu $t0, 0($a0)             # get char
    addi    $v0, $v0, 1             # len++
    addiu   $a0, $a0, 1             # *s++
    bne $t0, $0, top        #if char != '\0', loop
ret:
    addiu   $v0, $v0, -1
    jr      $ra

我正在尝试将其减少为 10 个字符的字符串,因此将其变成递归函数不会是“改进”。有没有可能从这里减少指令的数量?

【问题讨论】:

  • 哪些指令是动态指令?
  • @ScottHunter:“动态指令计数”是实际执行的指令数量,而不是您在反汇编中看到的数量。这里的措辞很尴尬(“动态指令”不是一件事),但这就是意思。例如诸如循环展开之类的事情是可能的:更大的代码大小,但如果行程计数很高,则实际执行的指令更少。不过,这与简化相反。但是,如果您真的关心 strlen 性能,请参阅Why does glibc's strlen need to be so complicated? - MIPS 上使用了一个单词 C。
  • 把它变成一个递归函数不会是一个“改进” - 对于大或小问题,对于你可以做的事情,这基本上从来都不是 asm 的改进一个简单的循环!您必须保存一整堆返回地址。即使您需要手动实现堆栈数据结构,这通常也更高效,只是更难正确编写。 C 编译器甚至会尽可能将 C 递归转换为 asm 循环。

标签: string assembly mips micro-optimization simplify


【解决方案1】:

你不需要在循环中增加一个计数器,你可以减去end - start来得到长度。例如:

strlen:
    addiu  $v0, $a0, 1   # start + 1

top:  
    lbu    $t0, 0($a0)   # get char
    addiu  $a0, $a0, 1   # s++
    bne    $t0, $0, top  # if char != '\0', loop
ret:
    subu   $v0, $a0, $v0 # (end+1) - (start+1)
    jr     $ra
   

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    相关资源
    最近更新 更多