MIPS:不使用伪代码的 la 指令的等价物?

发布于 2024-08-07 05:54:44 字数 286 浏览 2 评论 0原文

该参考文献说 la(加载地址)的伪代码被翻译为:

Pseudo : la $1, Label   

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

但是当我尝试在 MARS 中汇编代码时,我收到错误:

“无效的语言元素:16]

并且如果我删除[31:16] 我得到的部分

“标签”:操作数类型不正确

什么想法吗?

The reference says the pseudo code for la (load address) is translated to:

Pseudo : la $1, Label   

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

but when I try to assemble the code in MARS I get the error:

"Invalid language element: 16]

and if I remove the [31:16] part I get

"Label": operand is of incorrect type

Any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉生梦死 2024-08-14 05:54:44

这意味着标签的 16 个最高有效位设置为 $1。然后,16 个较低有效位与 16 个最高有效位进行或运算。

此处您可以找到 lui 指令的说明。它将标签地址的 16 msb 位加载到寄存器上,并将 16 lsb 归零。

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

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

编辑:
为了响应您的评论,您必须知道要使用 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

That means that the 16 most significant bits of label are set in $1. Then, 16 less significant bits are or'ed with the 16 most significant bits.

Here you can find the description of the lui instruction. It loads 16 msb bits of the label address on the register and zeroes 16 lsb.

This way, you can load 32 bit address (in mips32) with 32 bit instructions.

Its in no way intended to be "real code". The [31:16] / [15:0] part is not valid mips, and is only there for you to understand bit movements.

Edit:
In response to your comment, you would have to know the address you want to load using the lui instruction. To do this, you could use a label to indicate the desired address.
For example

.data 
my_var: .asciiz "This is a nul terminated string"

.text
        andi $a0,$a0,0x0000ffff
        lui $a0,my_var
        ori $a0,$a0,my_var
雪若未夕 2024-08-14 05:54:44

这是一个非常好的问题,我自己找到了一个可能的解决方案。上面的答案并不是无条件有效的。

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

一个例子:

.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!这种方法在内存中创建一个指针。我建议将指针放在其他可变长度数据的前面,以便您可以轻松计算指针的偏移量。

That's a really good question, where I came myself to a possible solution. The answer above doesn't work unconditionally.

Actually, it should be possible to say, where you want your data segment to be located (SPIM for example allows you to do that). The .data directive takes one optional argument, the 32-bit address where this data segment should be located. This way exception handlers are written (only using .kdata instead of .data).

An example:

.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

I'm actually not sure, if this is the best solution but it is the only solution I can think of (even without using virtual addressing modes i.e. labels for load or store instruction) and this idea should work (whether my code example works, I don't know, I haven't tested it).

EDIT:
I just have played around and discovered a really awesome trick which allows us to also load the label in registers without any pseudo instruction and with natural addressing mode. My example:

.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

In SPIM it assembles fine! A look at the memory at 0x10001000 shows, 0x10001004 is stored! This approach creates a pointer in memory. I'd recommend to place the pointers in front of other variable length data so that you can calculate easily the offset of the pointers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文