1
votes

Sorry about this really stupid question. But I have been reading my textbook the entire day and its getting really confusing.

I would like to clarify some syntax related questions with MIPS I-type instructions.

I understand that instructions like

addi $21, $22, -50

are possible and the immediate value is interpreted as a decimal (2s complement).

But can I write addi $21, $22, 0xF1DF? such that the immediate value is in hexadecimal?

That brings me to my next question with andi $10, $11, 0xFFFF and ori $8, $0, 0x0FA5. I understand that these 2 codes are correct.

But can I write andi $10, $11, 120 and ori $8, $0, -16such that the immediate values are in decimal? If it is possible, does it interpret 120 as hexadecimal or does it convert decimal 120 to hexadecimal which equates to 78 in hexadecimal.

I am very confused.

2
This is really a question about the assembler, not the processor. What assembler are you using?Raymond Chen
@RaymondChen just normal QTSpim. I am also questioning if it is applicable in written examsdeviljones
Then read the documentation for that assembler. Page A-47, "Assembler syntax." ("Just normal QTSpim" makes it sound like "Well certainly everybody uses QTSpim as their assembler, right?" I don't think that's true. For education, MARS is also popular. And for professional use, people are going to use something other than a simulator.)Raymond Chen
I have read the documentation, they do not explicitly say whether the immediate value is in decimal or hexadecimal form or could it be both?deviljones
Quoting page A-47: "Numbers are base 10 by default. If they are preceded by 0x, they are interpreted as hexadecimal. Hence, 256 and 0x100 denote the same value."Raymond Chen

2 Answers

1
votes

You can express immediates in both base 10 or hexadecimal. To express an hedacimal value you need to use the 0x prefix before the numeral (e.g. 0x10, which is 16 in base 10). If you don't use the prefix 0x before the numeral, the assembler will assume the numeral is in decimal notation.

Using your example, if you want to add 120 (base 10) you should encode the instruction like so addi $10, $11, 120 or like so addi $10, $11, 0x78. The assembler will produce the same binary instruction 0x20000000. You can try it for yourself here with this online assembler.

0
votes

MIPS addi / addiu sign-extend the 16-bit immediate to 32 bits (2's complement):
Values from -32768 (0xFFFF8000) to 32767 (0x00007FFFF) are encodeable.

MIPS andi / ori zero-extend the 16-bit immediate to 32 bits,
Values from 0 (0x00000000) to 65535 (0x0000FFFFF) are encodeable.

So no, you can't write ori $8, $0, -16, you'll have to use addiu.
(Or inefficiently, lui $8, 0xFFFF / ori $8, $8, 0xfff0).

Usually you can leave this decision-making to the assembler, and let it choose how to create a constant with li $8, 0xFFFFFFF0 or li $8, -16. Those will assemble identically.

But if you're not just creating a constant, you do have to know what's encodeable. For example, on the Godbolt compiler explorer, gcc5.4 compiles these functions as follows for MIPS:

unsigned mask(unsigned a) {
    return a & -16UL;
}

      # not encodeable as an immediate for andi
    li      $2,-16                  # 0xfffffffffffffff0
    j       $31
    and     $2,$4,$2



unsigned mask_positive(unsigned a) {
    return a & 0xFF;
}

    j       $31
    andi    $2,$4,0x00ff   # encodeable as an immediate

The representation in the source is totally irrelevant; hex and decimal are 2 different serialization formats for numbers. 0x10 and 16 are literally the same thing. In the MIPS machine code, they're stored in 16-bit binary, not hex or decimal

-32768 and 0xFFFF8000 are also the same thing (in 32-bit 2's complement). It's also 0x8000 in 16-bit 2's complement. And it's not representable as a 16-bit unsigned number, because 0x8000 zero-extends to 0x00008000 (+32768).