【发布时间】:2018-04-01 16:20:20
【问题描述】:
我想编写一个使用 mips 的俄罗斯农夫乘法的程序,但我遇到了一些问题
/ A method to multiply two numbers using Russian Peasant method
unsigned int russianPeasant(unsigned int a, unsigned int b)
{
int res = 0; // initialize result
// While second number doesn't become 1
while (b > 0)
{
// If second number becomes odd, add the first number to result
if (b & 1)
res = res + a;
// Double the first number and halve the second number
a = a << 1;
b = b >> 1;
}
return res;
}
我用 MARS 环境翻译成 mips
.data
msg1: .asciiz "give your first number"
msg2: .asciiz "give the second number"
.text
#a = $t1
#b = $t2
li $t3,0 #p
li $s1,1
li $s2,2
#display msg1
li $v0,4
la $a0,msg1
syscall
#read first number
li $v0,5
syscall
move $t1,$v0
#display msg2
li $v0,4
la $a0,msg2
syscall
#read second number
li $v0,5
syscall
move $t2,$v0
WHILE:
bgt $t2,$zero,DO
move $a0,$t3
li $v0,1
syscall
li $v0,10
syscall
DO:
div $t2,$s2
mfhi $s0 #r $s0 = $t2 / $s2
beq $s0,$s1,INC # IF b MOD 2 = 1 I jump to INC
#a = 2xa
mul $t1,$t1,$s2
div $t2,$s2
mflo $t2 # b = $t2/$s2
j WHILE
# i = i+ 1
INC:
add $t3,$t3,$t1
jr $ra
拜托,有人可以帮助我吗? 修复“错误:无效的程序计数器值:0x00000000” 我搜索了如何解决它,但我遇到了 $ra 的问题 如何在 $ra 中正确保存返回地址?
【问题讨论】:
-
最后一行的
jr $ra应该实现什么?看起来像 MARS/SPIM 环境(从syscall使用情况猜测),其中$ra在程序启动时为零,我看不到任何jal或move/add/...会改变$ra,所以它看起来您面临的问题是在代码中添加随机指令,而不是弄清楚您到底想做什么,并且只做那个。 -
是的,我知道但不知道如何在我的代码中使用 jal,它可能会破坏我的代码。是的,我使用 MARS 环境
-
jal是跳转,它还设置了$ra的地址为后面的指令(或下一条,甚至不确定是哪一条,因为 MIPS CPU 的延迟分支槽,这使得所有跳转更多复杂..您的代码看起来期望该功能已关闭,因此您的 MARS 正在模拟没有分支延迟槽的虚拟简化 MIPS CPU)。那么最后一条指令应该实现什么?你为什么把jr $ra放在那里?要结束代码执行,请使用带有终止功能的syscall。要跳回您的代码,请使用普通跳转到标签。要使用“子程序”,请学习如何使用jal+jr $ra。 -
我只是编辑我的帖子,我希望你明白我现在在寻找什么
-
我明白你想要编写什么代码,我不明白你是如何想出你的代码的 - 好吧,我确实明白如何,因为你只是学习汇编,你没有花足够的时间+练习 CPU 指令集,你还不了解一些常见的习语是如何在汇编中完成某些事情的,但是结果对于长时间看你写的所有东西是有好处的,交叉-检查你的讲座和可用的说明,并试图找出看起来合理的东西,以及从 C 源代码转移的令人费解的混乱太多。然后删除它,重新开始。
标签: algorithm math assembly mips