简体   繁体   English

为什么这个 Risc-V 二叉树检查器不起作用?

[英]Why is this Risc-V Binary tree checker not working?

I'm trying to write a Risc-V tree checker: every tree's node is composed of three words:我正在尝试编写一个 Risc-V 树检查器:每棵树的节点都由三个单词组成:

1)Either 0 or 1 1) 0 或 1

2)Left node's address 2) 左节点地址

3)Right node's address 3) 右节点地址

My program should explore the tree and return how deep into the tree is the first node with a 1 as the first word, here's the code:我的程序应该探索树并返回第一个节点以 1 作为第一个单词的深度,这是代码:

.data
tree:   .word n01
n01:    .word 0, n02, n03
n02:    .word 0, n04, n05
n03:    .word 0, n06, n07
n04:    .word 0, 0, 0
n05:    .word 0, 0, 0
n06:    .word 1, 0, 0
n07:    .word 0, 0, 0
.text
    lw a0, tree
    jal altezza
    addi a0, a0, -1
    li a7, 1
    ecall
    li a7, 10
    ecall

altezza:
    bne a0, zero, altezza_ric  
    jalr zero, ra, 0    

altezza_ric:
    addi sp, sp, -12  
    lw t1, 0(a0)
    sw ra, 0(sp)    
    bne t1, zero, skip_numb

    sw a0, 4(sp)    
    lw a0, 4(a0)    
    jal altezza
    sw a0, 8(sp)    
    lw a0, 4(sp)    
    lw a0, 8(a0)    
    jal altezza

    lw t0, 8(sp)    
    bne a0, zero, scelta
    mv a0, t0
    bne a0, zero, scelta
    jal skip
scelta:
    ble a0,t0,skip_add
    mv a0, t0


skip_add:  
    addi a0, a0, 1  #ad a0 inremento 1
skip:   lw ra, 0(sp)
    addi sp, sp, 12 
    jalr zero, ra, 0    

skip_numb:
    add a0, zero, zero
    jal skip_add

Try single stepping in the debugger to see if each instruction has the effect you want.尝试在调试器中单步执行,以查看每条指令是否具有您想要的效果。

Make your initial test cases as small as possible, because debugging recursive functions can be very confusing.使您的初始测试用例尽可能小,因为调试递归函数可能会非常混乱。 So try it with just one node, for example;因此,例如,仅使用一个节点尝试一下; then just two nodes (eg a root node with a left; a root node with a right).然后只有两个节点(例如,左边的根节点;右边的根节点)。

Eventually you'll see this:最终你会看到:

lw a0, 4(sp)    <------- the result of this load is discarded
lw a0, 8(a0)    

Here the first load is meaningless, because the a0 value it obtains is (immediately) overwritten by the second load.这里第一次加载没有意义,因为它获得的a0值(立即)被第二次加载覆盖。


    bne a0, zero, scelta
    jal skip
scelta:
    ble a0,t0,skip_add
    mv a0, t0
skip_add:

Don't use jal for simple branching, use j instead.不要使用jal进行简单的分支,而是使用j While here it doesn't hurt, it does update ra , which you don't want in the context of a simple if-then-else.虽然在这里它没有伤害,但它确实更新了ra ,在简单的 if-then-else 的上下文中你不想要它。 If you had a leaf function that doesn't save ra in the stack, this would be bad.如果您有一个叶子 function 不能将ra保存在堆栈中,那就太糟糕了。

As this sequence has a conditional branch that jumps around an unconditional branch, this can be simplified to eliminate the unconditional branch and a label ( scelta: ) as follows:由于这个序列有一个条件分支,它会在一个无条件分支周围跳转,因此可以将其简化为消除无条件分支和一个 label ( scelta: ),如下所示:

    beq a0, zero, skip  <--- reverse the condition and branch to the other target
                        <--- eliminate/omit the unconditional branch and other label
    ble a0,t0,skip_add
    mv a0, t0
skip_add:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM