Assembly MIPS程序在嵌套函数上卡住

Assembly MIPS程序在嵌套函数上卡住,assembly,mips,Assembly,Mips,在Ch的jal指令之后,我的程序似乎卡在了框1上。我认为这与$ra被覆盖有关。我该如何解决这个问题 该计划应该是一个简单的比特币矿工。图如下: 我用的是冠词 我认为解决这个问题的方法可能是在堆栈上节省$ra,但这似乎有点不切实际和低效?很可能我做错了什么 .data A: .word 0x87564C0C B: .word 0xF1369725 C: .word 0x82E6D493 D: .word

在Ch的jal指令之后,我的程序似乎卡在了框1上。我认为这与$ra被覆盖有关。我该如何解决这个问题

该计划应该是一个简单的比特币矿工。图如下:

我用的是冠词

我认为解决这个问题的方法可能是在堆栈上节省$ra,但这似乎有点不切实际和低效?很可能我做错了什么

    .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


如果你真的想优化,有几种方法