For example in this code :
#display message
li $v0, 4
la $a0, Message
#promt user to enter name
li $v0, 8
la $10, username
li $a1, 20
syscall
#display the name
li $v0, 4
la $a0, userName
syscall
I am very confused about what li (load immediate) and la(load address) really mean?
They're fairly similar, as both are (mostly) used for loading immediate values. Both of them are also pseudo-instructions, so it's really up to each assembler that supports them to determine exactly how they should function.
li
stands for Load Immediate and is a convenient way of loading an immediate up to 32 bits in size. Instructions like addi
and ori
can only encode 16-bit immediates, so the assembler may translate li
into multiple instructions.
For example, li $t0,0x12345678
might become:
lui $at, 0x1234
ori $t0, $at, 0x5678
So it's just a way to save you from writing those two instructions, and instead letting the assembler working that out for you.
There's really no reason why e.g. li $t0, Message
wouldn't be supported, since labels are also immediates, but some assemblers might not accept labels for li
.
la
stands for Load Address. It can be used to load integer constants just like li
, e.g. la $t0,0x1234678
. But it also works with labels: la $t0, Message # t0 = address of Message
.
Some assemblers may also allow you to do things like la $t0, 8($t1) # t0 = t1 + 8
.
When you'd use li
and when you'd use la
depends on the context. If the value you're loading is going to be used as an address you would typically use la
to load it, and otherwise you'd typically use li
. Since they are partially interchangable it's really up to you, but other people might find your code strange-looking if you use la
all the time to load integer constants.