在 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,然后按照其汇编语言模式翻译每个结构化语句(例如 if
、for
)。嵌套结构语句在汇编语言中也是嵌套的,先翻译内部语句还是先翻译外部语句都无所谓,只要准确观察嵌套即可。
为了将结构化语句翻译成汇编,我首先使用C中的中间形式,例如:
for ( int i = 0; i < n; i++ ) {
..body of for..
}
请注意,在上面的“for 主体”中,可以很容易地包含控制结构,例如另一个 for
或 if
。然后,这些是嵌套结构语句——只需一次翻译它们,每个结构化语句都遵循其完整的模式,并确保 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 代码语句中的表达式翻译成汇编语言。
假设我们有一个字符串表示给定基数中的一个整数,而且就是这个基数。 参数是存储字符串的起始地址(在 $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,然后按照其汇编语言模式翻译每个结构化语句(例如 if
、for
)。嵌套结构语句在汇编语言中也是嵌套的,先翻译内部语句还是先翻译外部语句都无所谓,只要准确观察嵌套即可。
为了将结构化语句翻译成汇编,我首先使用C中的中间形式,例如:
for ( int i = 0; i < n; i++ ) {
..body of for..
}
请注意,在上面的“for 主体”中,可以很容易地包含控制结构,例如另一个 for
或 if
。然后,这些是嵌套结构语句——只需一次翻译它们,每个结构化语句都遵循其完整的模式,并确保 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 代码语句中的表达式翻译成汇编语言。