4

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mehran
  • 1,977
  • 1
  • 18
  • 33
  • 1
    See the answer to http://stackoverflow.com/questions/7264532/problem-loading-memory-address-only-using-real-instructions-in-mips-asm-on-mars/7264857#7264857 for how to do this in MIPS gnu assembler. – markgz Sep 27 '11 at 22:46

2 Answers2

6

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
Tom
  • 43,810
  • 29
  • 138
  • 169
  • Thanks but if I want to do the exact same thing without pseudo codes what should I write? – Mehran Oct 08 '09 at 17:24
  • 1
    this codes fails to assmble since my_var is a 32bit address and lui oprand should be 16bit. – Mehran Oct 09 '09 at 12:54
  • that's not working with qtspim it gives me syntax error – Robert Nov 27 '15 at 12:19
  • That sample code won't work because lui overwrites the lower 16 bits to all 0s and what did you have in $a0 that you're ANDint with? Moreover, your constant is 32 bits long, but the andi instruction is in I format and the largest constant it can take is 16 bits long. – Haggra Dec 16 '17 at 17:14
2

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.