Assembly MIPS程序在嵌套函数上卡住
在Ch的jal指令之后,我的程序似乎卡在了框1上。我认为这与$ra被覆盖有关。我该如何解决这个问题 该计划应该是一个简单的比特币矿工。图如下: 我用的是冠词 我认为解决这个问题的方法可能是在堆栈上节省$ra,但这似乎有点不切实际和低效?很可能我做错了什么Assembly MIPS程序在嵌套函数上卡住,assembly,mips,Assembly,Mips,在Ch的jal指令之后,我的程序似乎卡在了框1上。我认为这与$ra被覆盖有关。我该如何解决这个问题 该计划应该是一个简单的比特币矿工。图如下: 我用的是冠词 我认为解决这个问题的方法可能是在堆栈上节省$ra,但这似乎有点不切实际和低效?很可能我做错了什么 .data A: .word 0x87564C0C B: .word 0xF1369725 C: .word 0x82E6D493 D: .word
.data
A: .word 0x87564C0C
B: .word 0xF1369725
C: .word 0x82E6D493
D: .word 0x63A6B509
E: .word 0xDD9EFF54
F: .word 0xE07C2655
G: .word 0xA41F32E7
H: .word 0xC7D25631
W: .word 0x6534EA14
K: .word 0xC67178F2
.text
.globl main
main:
li $s0,0 #loop counter
li $s1,64 #loop limit
main_loop:
bge $s0,$s1,end_main_loop
jal box_0
move $a0,$v0 #save return value in $a0 to be used as argument by box_1
jal box_1
move $a0,$v0 #
jal box_2
move $a0,$v0 #
move $s2,$a0 #will be necessary for the input of box_4 later
jal box_3
move $s3,$v0 #Will be assigned to E later
jal box_4
move $a0,$v0 #
jal box_5
###Assignments
lw $a0,G
la $a1,H
sw $a0,($a1) #Old G goes into new H
lw $a0,F
la $a1,G
sw $a0,($a1) #Old F goes into new G
lw $a0,E
la $a1,F
sw $a0,($a1) #Old E goes into new F
#
la $a1,E
sw $s3,($a1) #Output of box_3 goes into new E
#
lw $a0,C
la $a1,D
sw $a0,($a1) #Old C goes into new D
lw $a0,B
la $a1,C
sw $a0,($a1) #Old B goes into new C
lw $a0,A
la $a1,B
sw $a0,($a1) #Old A goes into new B
#
la $a0,A
sw $v0,($a0) #Output of box_5 goes into new A
addi $s0,$s0,1 #increment loop counter
end_main_loop:
li $v0, 10 # terminate program
syscall
.text
.globl red_boxes
red_boxes:
box_0:
lw $t0,W
lw $t1,K
addu $t0,$t0,$t1 #Wt + Kt
move $v0,$t1
jr $ra
box_1:
move $t0,$a0 #output of box_0
jal Ch
move $t1,$v0
lw $t3,H
addu $t0,$t0,$t1
addu $t3,$t0,$t3
move $v0,$t3
jr $ra
box_2:
move $t0,$a0 #output of box_1
#move $t1,$a1 #output of Sigma1
jal Sigma1
move $t1,$v0
addu $t0,$t0,$t1
move $v0,$t0
jr $ra
box_3:
move $t0,$a0 #output of box_2
lw $t1,D
addu $t0,$t0,$t1
move $v0,$t0
jr $ra
box_4:
move $t0,$a0 #output of box_2 <----!!
#move $t1,$a1 #output of Ma
jal Ma
move $t1,$v0
addu $t0,$t0,$t1
move $v0,$t0
jr $ra
box_5:
move $t0,$a0 #output of box_4
#move $t1,$a1 #output of Sigma0
jal Sigma0
move $t1,$v0
addu $t0,$t0,$t1
move $v0,$t0
jr $ra
.text
.globl op_boxes
op_boxes:
Ch:
# (G&!E) || (F&E)
lw $t0,E
lw $t1,F
lw $t2,G
and $t1,$t1,$t0 #(F&E)
not $t0,$t0 #!E
and $t2,$t2,$t0 #(G&!E)
or $t0,$t1,$t2 #(G&!E) || (F&E)
move $v0,$t0
jr $ra
Sigma1:
lw $t0,E
ror $t1,$t0,6 #rotates E to the right by 6 bits
ror $t2,$t0,11 # ''' by 11 bits
ror $t3,$t0,25 # ''' by 25 bits
addu $t2,$t2,$t1 # A->6 + A->11
addu $t3,$t3,$t2 # (A->6 + A->11) + A->25
li $t1,1
and $t1,$t3,$t1
move $v0,$t1
jr $ra
Ma:
# majority = (A&B) | (B&C)
lw $t0,A
lw $t1,B
lw $t2,C
or $t3, $t0, $t2
and $t1, $t1, $t3
and $v0, $t0, $t2
or $v0, $t1, $v0
jr $ra
Sigma0:
#Same as Sigma0 but shifted by different values
lw $t0,A
ror $t1,$t0,2
ror $t2,$t0,13
ror $t3,$t0,22
add $t2,$t2,$t1
add $t3,$t3,$t2
li $t1,1
and $t1,$t3,$t1
move $v0,$t1
jr $ra
.data
A:.字0x87564C0C
B:.字0xF1369725
C:.字0x82E6D493
D:.字0x63A6B509
E:字0xDD9EFF54
F:.字0xE07C2655
G:.字0xA41F32E7
H:.字0xC7D25631
W:.字0x6534EA14
K:.字0xC67178F2
.文本
格洛博梅因酒店
主要内容:
li$s0,0#循环计数器
li$s1,64#循环限制
主回路:
bge$s0$s1,结束主回路
日本航空公司信箱0
移动$a0,$v0#将返回值保存在$a0中,作为框1的参数
日本航空公司1号信箱
移动$a0,$v0#
日本航空公司信箱2
移动$a0,$v0#
移动$s2,$a0#对于稍后输入方框4是必需的
日本航空公司信箱3
移动$s3,$v0#将稍后分配给E
日本航空公司信箱4
移动$a0,$v0#
日本航空公司信箱5
###任务
lw$a0,克
洛杉矶1美元,小时
sw$a0,($a1)#旧G进入新H
lw$a0,F
洛杉矶1美元,克
sw$a0,($a1)#旧F变成新G
lw$a0,E
洛杉矶$a1,F
sw$a0,($a1)#旧E变为新F
#
洛杉矶$a1,E
sw$s3,($a1)#框3的输出进入新的E
#
lw$a0,C
洛杉矶1美元,D
sw$a0,($a1)#旧C变为新D
lw$a0,B
洛杉矶1美元,C
sw$a0,($a1)#旧B变为新C
lw$a0,A
洛杉矶$a1,B
sw$a0,($a1)#旧A变成新B
#
洛杉矶$a0,A
sw$v0,($a0)#方框5的输出进入新A
addi$s0,$s0,1#递增循环计数器
结束主循环:
li$v0,10#终止程序
系统调用
.文本
.全球红盒
红盒:
方框0:
lw$t0,W
lw$t1,K
加上$t0,$t0,$t1#Wt+Kt
移动$v0,$t1
jr$ra
方框1:
移动$t0,$a0#框0的输出
日航
移动$t1,$v0
lw$t3,小时
加成$t0,$t0,$t1
加成$t3、$t0、$t3
移动$v0,$t3
jr$ra
方框2:
移动方框1的$t0、$a0#输出
#移动$t1,$a1#Sigma1的输出
日航Sigma1
移动$t1,$v0
加成$t0,$t0,$t1
移动$v0,$t0
jr$ra
方框3:
移动方框2的$t0、$a0#输出
lw$t1,D
加成$t0,$t0,$t1
移动$v0,$t0
jr$ra
方框4:
移动$t0、$a0#方框2 6+A的输出->11
加上$t3、$t3、$t2(A->6+A->11)+A->25
李$t1,1
和$t1、$t3、$t1
移动$v0,$t1
jr$ra
妈妈:
#多数=(A&B)|(B&C)
lw$t0,A
lw$t1,B
lw$t2,C
或$t3、$t0、$t2
和$t1、$t1、$t3
和$v0、$t0、$t2
或$v0、$t1、$v0
jr$ra
Sigma0:
#与Sigma0相同,但移动了不同的值
lw$t0,A
ror$t1,$t0,2
ror$t2,$t0,13
ror$t3,$t0,22
添加$t2、$t2、$t1
加上$t3、$t3、$t2
李$t1,1
和$t1、$t3、$t1
移动$v0,$t1
jr$ra
此外,我使用addu而不是add,因为有时会出现溢出。这是正确的吗?这篇文章没有说任何关于溢出的内容
在堆栈上节省$ra,但这似乎有点不切实际和低效
如果您确切地知道什么是寄存器Ch(以及它的所有被调用方,这里没有),那么您可以将$ra
保存在其中一个寄存器中,而不是在堆栈上,以便在这里和那里保存一个循环
如果您使用的是RISC V,您可以在调用Ch
时使用一个备用寄存器作为返回地址,然后通过在此处避免$ra
,根本不需要保留$ra
如果您真的想优化代码,有两种方法: 一种是开发程序范围的寄存器分配,这样您就不必一直加载和存储这些全局变量,而只需操作寄存器 (如果程序变得非常大,或者您还想混合使用编译器生成的C代码的调用,这可能很难做到,因为编译器不一定知道程序范围内的寄存器分配。但是,如果您将其编写为C调用的子例程,但不回叫C,则只返回C,您仍然可以返回整个程序。)(常规寄存器分配。) 另一种方法是内联所有方法——快速浏览一下,调用似乎没有太多的重用,因此这种内联似乎是必要的 这两种方法可以结合使用
是的,
addu
在我们不关心溢出时是合适的。它产生与add
相同的位模式,但只是放弃溢出检查
在堆栈上节省$ra,但这似乎有点不切实际和低效
如果您确切地知道什么是寄存器Ch(以及它的所有被调用方,这里没有),那么您可以将$ra
保存在其中一个寄存器中,而不是在堆栈上,以便在这里和那里保存一个循环
如果您使用的是RISC V,您可以在调用Ch
时使用一个备用寄存器作为返回地址,然后通过在此处避免$ra
,根本不需要保留$ra
如果你真的想优化,有几种方法