代码之家  ›  专栏  ›  技术社区  ›  Mehran ShankarSangoli

MIPS:相当于不使用伪码的LA指令?

  •  3
  • Mehran ShankarSangoli  · 技术社区  · 15 年前

    参考文件说,LA(加载地址)的伪代码被翻译为:

    Pseudo : la $1, Label   
    
    lui $1, Label[31:16]
    ori $1,$1, label[15:0]
    

    但是当我试图在火星上组装代码时,我得到了错误:

    “无效的语言元素:16]

    如果我去掉[31:16]部分,我会得到

    “label”:操作数类型不正确

    有什么想法吗?

    2 回复  |  直到 9 年前
        1
  •  5
  •   Tom    15 年前

    这意味着标签的16个最重要的位被设置为$1。然后,16个低有效位与16个最高有效位一起使用。

    Here 您可以找到LUI指令的描述。它在寄存器上加载标签地址的16个msb位,并将16个lsb归零。

    这样,您可以使用32位指令加载32位地址(在mips32中)。

    它绝不是“真正的代码”。[31:16]/[15:0]部分不是有效的MIP,仅用于您了解位移动。

    编辑: 作为对您的评论的回应,您必须知道要使用lui指令加载的地址。为此,您可以使用一个标签来指示所需的地址。 例如

    .data 
    my_var: .asciiz "This is a nul terminated string"
    
    .text
            andi $a0,$a0,0x0000ffff
            lui $a0,my_var
            ori $a0,$a0,my_var
    
        2
  •  2
  •   Fellow MIPSer    9 年前

    这是一个很好的问题,我在哪里找到了一个可能的解决方案。上述答案并非无条件工作。

    实际上,应该可以说,您希望数据段位于何处(例如,SPIM允许您这样做)。这个 .data 指令接受一个可选参数,即该数据段应位于的32位地址。以这种方式编写异常处理程序(仅使用 .kdata 而不是 数据 )

    一个例子:

    .data 0x10001000                 #remember this location
        .align 0
        .asciiz "MIPS IS GREAT!"     #this is at offset 0
    
    .text
        .align 2
        .globl main
    main:                            #let's assume we've got no arguments
        addiu $sp, $sp, -24          #subroutine prolog
        sw $ra, 16($sp)
        sw $fp, 10($sp)
        addiu $fp, $sp, 20
    
        ori $v0, $0, 4
        lui $a0, 0x1000              #sole argument must be str pointer
        ori $a0, $a0, 0x1000
        syscall                      #print STR out on console
    
        lw $ra, 16($sp)              #subroutine epilog
        lw $fp, 10($sp)
        addiu $sp, $sp, 24
        jal
    

    实际上,我不确定这是否是最好的解决方案,但它是我能想到的唯一解决方案(即使不使用虚拟寻址模式,即加载或存储指令的标签),这个想法应该有效(我的代码示例是否有效,我不知道,我还没有测试过)。

    编辑: 我只是随便玩玩,发现了一个非常棒的技巧,它允许我们在寄存器中加载标签,而不需要任何伪指令和自然寻址模式。我的例子:

    .data 0x10001000
            .word LABEL
    LABEL:  .asciiz "Get LABEL to print this C string."
    
    .text
        .align 2
        .globl main
    #test if it loads LABEL
    main:
        lui $4, 0x1000
        ori $4, $4, 0x1000
        lw $4, 0($4)
        ori $2, $0, 4
        syscall
    

    在SPIM中,它组装得很好!看一下内存在0x10001000,显示存储了0x10001004!这种方法在内存中创建一个指针。我建议将指针放在其他可变长度数据前面,这样您就可以轻松地计算指针的偏移量。