在 MIPS 中编写一个函数,将表示整数(在给定基数中)的字符串转换为基数为 10 的相应数字

Writing in MIPS a function that converts a string representing an integer (in a given base), to the corresponding number in base 10

假设我们有一个字符串表示给定基数中的一个整数,而且就是这个基数。 参数是存储字符串的起始地址(在 $a0 中),以及 $a1 中的基数。

我应该把对应的数字转成10进制,存入$v0。在这种情况下,0 应该加载到 $v1.
如果相反,字符串不能正确表示给定基数中的整数,那么最后 $v0 应该包含 -1 而 $v1 应该包含 1.

此外,实际执行转换的函数应该是递归的。

我已经预先编写了一个 Python 程序(您会注意到各种 s0、s1 等),我可以将想法转移到 MIPS,但当我意识到时,它真的很混乱我可能应该根据上下文执行字符串字符的计数,调查字符串是否“在基数”,以及将数量逐渐求和到某个指定变量的实际转换——而不是像下面的程序那样单独执行.

我应该如何着手编写函数?

这是 Python 代码:

digitsDict = dict();

lowerCase = "abcdefghijklmnopqrstuvwxyz"
upperCase = lowerCase.upper();

for i in range(26):
    digitsDict.update({lowerCase[i]:i+10})
    digitsDict.update({upperCase[i]:i+10})

def isInBase(string, base):
    s1 = False; 
    for char in string:
        if (str(char).isdigit()):
            if (int(char) >= base):
                return s1
        else:
            if (char not in digitsDict.keys() or digitsDict[char] >= base):
                return s1
    s1 = True
    return s1

def convert(string, base, k=0):
    s2 = 0
    char = string[k]
    l = len(string) - 1
    if str(char).isdigit(): s2 += int(char)*(base**(l-k))
    else:   s2 += digitsDict[char]*(base**(l-k))
    
    if k == l: return s2;
    return s2 + convert(string, base, k+1)
    

def strToInt(string, base):
    return (convert(string, base, 0), 0)
    
def main(a0String, a1Integer):
    if isInBase(a0String, a1Integer):
        v0, v1 = strToInt(a0String, a1Integer)
    else: v0 = -1; v1 = 1;
    
    print(v0)
    if (v0 == -1): return 22 #MIPS error code for invalid argument
    return 0 #OK

首先,你有伪代码,太好了!


接下来,作为一般规则,请确保您的伪代码确实有效(因此对其进行测试),因为在汇编中调试设计问题非常困难,并且对设计(伪代码)的小改动可能需要大改动在汇编中(例如重写大量代码)。


您在 Python 中做一些涉及汇编语言的事情,因此您应该先用 C 编写伪代码,因为这将使您解决这些差异。

  • in — 表示 C 或汇编中的循环
  • 字符串上的
  • +=+ — 表示对全局缓冲区的一些简单操作,或者一些复杂的内存管理(提示:选择前者)
  • .isDigit() 是有条件的合取还是析取取决于你如何编码它
  • .update() 需要一些替代翻译
  • ** 也表示 C 或汇编中的循环

下一个复杂的问题是函数的调用。由于寄存器使用和堆栈处理的要求,MIPS 汇编语言中的函数调用可能是最复杂的主题

递归对于汇编语言来说有点转移注意力:它看起来很难,但实际上在汇编语言中并不难,甚至与不涉及递归的调用其他函数的函数没有什么不同(假设汇编指令集是正确的有一个用于函数调用的运行时堆栈,MIPS 有(但如果没有,你就必须模拟一个调用堆栈)。

这个你要好好研究一下,有点牵强。寻找其他示例,例如斐波那契。

将调用另一个函数的一个函数转换为 MIPS 时,我们需要分析“跨函数调用存在”的变量和值。这些变量需要特别考虑,因为调用另一个函数会清除一些寄存器。例如,您会在斐波那契中看到这一点。

递归 fib 的一部分,是 fib(n-1)+fib(n-2)。必须对第一次调用 fib 的 return 值进行特殊处理,因为它最终需要添加(+),因此它在第二次调用 [=20= 时有效],如果不进行特殊处理,将在第二次调用时丢失。此外,n 在第一次调用中仍然存在,但需要再次进行第二次调用,如果不进行一些特殊处理,第一次调用同样会被清除。

这是函数调用 MIPS 中函数的结果,其指令集不会自动堆叠事物,需要汇编语言程序员或编译器手动执行此操作。其他架构也需要其中的部分或全部。这不是递归的结果,因此 a(n)+b(n) 将涉及对变量和值的分析和特殊处理的相同要求。


当你有一个好的算法(例如在 C 中)并且它有效时,你就可以进行组装了。首先翻译您的数据:全局变量。接下来翻译函数,类似地:将局部变量翻译成 MIPS,然后按照其汇编语言模式翻译每个结构化语句(例如 iffor)。嵌套结构语句在汇编语言中也是嵌套的,先翻译内部语句还是先翻译外部语句都无所谓,只要准确观察嵌套即可。

为了将结构化语句翻译成汇编,我首先使用C中的中间形式,例如:

for ( int i = 0; i < n; i++ ) {
    ..body of for..
}

请注意,在上面的“for 主体”中,可以很容易地包含控制结构,例如另一个 forif。然后,这些是嵌套结构语句——只需一次翻译它们,每个结构化语句都遵循其完整的模式,并确保 C 中的嵌套在汇编中同样得到遵守。

for翻译成while

...
int i = 0;
while ( i <n ) {
    ..body of for..
    i++;
}
...

接下来,应用“if-goto-label”中间形式:

    ...
    int i = 0;
loop1:
    if ( i >= n ) goto endLoop1;
    ..body of for..
    i++;
    goto loop1;
endLoop1:
    ...

在应用模式时,您需要创建标签名称;每个模式应用的新标签名称。

然后这很容易转化为汇编。如果“for 的主体”也有控制结构,确保它们的整个翻译被嵌入并位于上述模式中的“for 的主体”部分。

注意汇编中的 i < n 有时如何转换为 i >= n — 这里是因为 if-goto-label 形式的控制流 make 是这样说的:在逻辑相反的条件下退出循环 while C 中的语句


最后,将 C 代码语句中的表达式翻译成汇编语言。