MIPS分支寻址算法和操作码与指令二进制隔离?

时间:2016-10-03 16:07:02

标签: mips spim

我只是想检查一下我对这两个概念的理解是否正确,因为我一直在努力完成一个项目,虽然一切都符合我的期望,但它仍然严重地使测试用例失败并引入随机值... < / p>

基本上,该项目的目标是以这种形式写出一个分支指令到控制台:

BranchName $ S,[$ t,如果适用] 0xAbsoluteAddressOfBranchTargetInstruction

编辑:澄清:我是用MIPS写的。我的想法是通过我的讲师代码(我编写函数)获得一个$ a0的内存地址。该地址用于包含MIPS指令的字。我要做以下事情:

  1. 获取指示
  2. 隔离指令操作码并将其名称输出到寄存器(即:操作码5,输出BNE),如果不是分支指令则不执行任何操作。
  3. 根据需要隔离$ s,$ t和输出(即:bgez没有$ t)
  4. 在分支指令中使用offset来计算其绝对地址(分支后的目标指令的地址)并以十六进制输出。出于此计算的目的,分支指令的地址($ a0)假定为$ pc。
  5. IE:

    BEQ $ 6,$ 9,0x00100008

    首先,我对分支计算的理解是否正确?

    1. PC - &gt; PC + 4
    2. 低16位指令
    3. &LT;&LT; 2这些低位
    4. 添加PC + 4,左移低16位(仅低16位)。
    5. 其次,有人可以告诉我需要隔离哪些位来知道我正在处理哪种分支?我想我有他们(BEQ / BNE的前6名,其他16名的$ s掩盖了)但我想仔细检查。

      哦,最后......我是否应该期望SPIM在Intel x86 Windows系统和Intel x86 Linux系统上运行?我得到了一个愚蠢的故障,我似乎无法将其与我的手工地址计算隔离开来,但它只会在我运行我的教授在Linux上给我们的测试脚本时显示出来(.sh);在任何一个操作系统上直接运行直接运行似乎都有效......前提是我对如何进行手计算(如上所列)的理解是正确的。

2 个答案:

答案 0 :(得分:1)

16位立即值符号扩展为32位,然后移位。我不知道这是否会影响你的计划;但是,这是唯一的潜在错误&#34;我注意到了。

答案 1 :(得分:1)

这是我的各种评论的前言。

这是一个正确执行地址计算的示例程序。 执行分支指令类型解码,因此您必须将此部分和您的版本组合在一起。

请注意,它使用mars系统调用34以十六进制格式打印值。这在spim下不可用,因此您可能需要使用系统调用1以十进制输出或编写您自己的十六进制值输出函数[如果您还没有]

    .data
msg_best:   .asciiz     "correct target address: "
msg_tgt:    .asciiz     "current target address: "
msg_nl:     .asciiz     "\n"

    .text
    .globl  main
main:
    la      $s0,inst                # pointer to branch instruction
    la      $s1,einst               # get end of instructions
    subu    $s1,$s1,$s0             # get number of bytes
    srl     $s1,$s1,2               # get number of instruction words
    la      $s2,loop                # the correct target address

    la      $a0,msg_best
    move    $a1,$s2
    jal     printaddr

loop:
    move    $a0,$s0
    jal     showme                  # decode and print instruction
    addiu   $s0,$s0,4
    sub     $s1,$s1,1
    bnez    $s1,loop                # more to do? yes, loop

    li      $v0,10
    syscall

    # branch instructions to decode
inst:
    bne     $s0,$s1,loop
    beq     $s0,$s1,loop
    beqz    $s1,loop
    bnez    $s1,loop
    bgtz    $s1,loop
    bgez    $s1,loop
    bltz    $s1,loop
    blez    $s1,loop
einst:

# showme -- decode and print data about instruction
#
# NOTE: this does _not_ decode the instruction type
#
# arguments:
#   a0 -- instruction address
#
# registers:
#   t5 -- raw instruction word
#   t4 -- branch offset
#   t3 -- absolute address of branch target
showme:
    subu    $sp,$sp,4
    sw      $ra,0($sp)

    lw      $t5,0($a0)              # get inst word
    addiu   $t3,$a0,4               # get PC + 4

    sll     $t4,$t5,16              # shift offset left
    sra     $t4,$t4,16              # shift offset right (sign extend)
    sll     $t4,$t4,2               # get byte offset

    addu    $t3,$t3,$t4             # add in offset

    # NOTE: as a diagnostic, we could compare t3 against s2 -- it should
    # always match

    la      $a0,msg_tgt
    move    $a1,$t3
    jal     printaddr

    lw      $ra,0($sp)
    addu    $sp,$sp,4
    jr      $ra

# printaddr -- print address
#
# arguments:
#   a0 -- message
#   a1 -- address value
printaddr:
    li      $v0,4
    syscall

    # NOTE: only mars supports this syscall
    # to use spim, use a syscall number of 1, which outputs in decimal and
    # then hand convert
    # or write your own hex output function
    move    $a0,$a1
    li      $v0,34                  # output number in hex (mars _only_)
    syscall

    la      $a0,msg_nl
    li      $v0,4
    syscall

    jr      $ra