Say I have this instruction in MIPS
lw $t0, 21($s0)
$s0 contains the decimal 2022 (not a multiple of four)
Here, The exception will arise just on looking at the address at $s0 or after the computation of the address 21+$s0 ?
The exception will be caused by trying to load from address 21($s0), or 2022+21 = 2043 decimal. EPC will contain the address of the load instruction when the exception happened, and the BadVaddr register should contain decimal 2043.
Related
How does MIPS's assembler labels and J type instruction work?
I am currently making a MIPS simulator using C++ and came into a big question. How exactly does MIPS assembler manage label's and their address while on a J type instruction?
Let's assume that we have a following code. Also let's assume that start: starts at 0x00400000. Comments after code represent where the machine codes will be stored in memory.
start:
andi $t0, $t0, 0 # 0x0040 0000
andi $t1, $t1, 0 # 0x0040 0004
andi $t2, $t2, 0 # 0x0040 0008
addi $t3, $t3, 4 # 0x0040 000C
loop:
addi $t2, $t2, 1 # 0x0040 0010
beq $t2, $t3, exit # 0x0040 0014
j loop # 0x0040 0018
exit:
addi $t0, $t0, 1000 # 0x0040 002C
As I am understanding right at the moment, j loop expression will set PC as 0x0040 0010.
When J type instruction uses 32 bits and with MSB 6 bits as its opcode, it only has 26 bits left to represent address of instruction. Then how is it possible to represent 32 bit address system using only 26 bits?
With the example above, it can represent 0x00400010 with only 24bits. However, in references, text segment is located from 0x00400000 to 0x10000000 which needs 32bit to represent.
I have tried to understand this using MARS simulator, however it just represents j loop as j 0x00400010 which seems nonsense to me since 0x00400010 is 32 bits.
My current guess
One of my current guesses is following.
Assembler saves the loop: label's address into some memory address that is reachable by 26 bits. Then when expression j loop is called, label loop is translated to the memory address that contains 0x00400010 For example, 0x00400010 is saved in some address like 0x00300000 and when j loop is called, loop is translated into 0x00300000 and it is able to get value from 0x00300000 and reach out 0x00400010. (This is just one of my guess)
You have a number of questions here.
First, let's try to differentiate between the assembler's operation and the MIPS machine code that it generates and the processor executes.
The assembler manages labels and address in two ways. First, it has a symbol table, which is like a dictionary, a data structure of key-value pairs where the names are keys and the addresses (that those names will refer to when the program is running) are the values in the pairs.
Second, the assembler manages the code and data sections with a location counter. That location counter advances each time the program provides some code or data. When new label is defined, the current location counter is then used as the address value in a new key-value pair.
The processor never sees the labels: they do not execute and they do not occupy any space in the code or data. The processor sees only machine code instructions, which on MIPS are all 32-bits wide. Each machine code instruction is divided into fields. There are instruction types or formats, which on MIPS are straightforward: I-Type, J-Type, and R-Type. These formats then define the instruction fields, and the assembler follows these encodings. All the instruction formats share the 6-bit opcode field, and this opcode field tells the processor what format the instruction is, which fields it therefore has, and thus how to interpret and execute the rest of the instruction.
The assembler removes labels from the assembly — labels and their names do not exist in the program binary. The label definitions themselves (label:) are omitted from the program binary but usages of labels are translated into numbers, so a machine code instruction that uses a label will have some instruction field that is numeric, and the assembler will provide a proper value for that numeric field so that the effect of the reaching or otherwise accessing what the label referred to is accomplished. (The label is no longer in the program binary, but the code or data memory that the label referred does remain).
The assembler sets up branch instructions, j instructions, and la/lw instructions, using numbers that tell the processor how far forward or backward to move the program counter, or, what address some data of interest is at. The lw/la instructions access data, and these use 2 x 32-bit instructions each holding 16 bits of the address of interest. Between the two instructions, they put together a full 32-bit address for data access. For branches to fully reach any 32-bit address, they would have to put together the 32-bit address in a similar manner (two instruction pair) and use an indirect/register branch.
I am new to MIPS and I have a given MIPS recursive code which I have to apply it to a specific number (ex. number 3)
Bellow is the given MIPS code and I am supposed to write if I were to pass ex. number 3 in the function what would be the changes in the registries and cache for the recursion for said number 3?
I have tried to do it step by step on a piece of paper but got nowhere.
fact:
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
slti $t0,$a0,1
beq $t0,$zero,L1
addi $v0,$zero,1
addi $sp,$sp,8
jr $ra
Ll:addi $a0,$a0,-1
jal fact
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mul $v0,$a0,$v0
jr $ra
Always test your code with the smallest possible input first. If you try with 0, and single step some 8 instructions worth, you can observe that your code doesn't return to its caller with the proper stack pointer value — an important part of functions is to preserve the registers that must be preserved for the caller, and that includes the stack pointer. Usually, the way to restore the stack pointer is to deallocate any allocated space, and as long as this is balanced, the preservation rule for $sp is honored.
As a result of an improper stack pointer, the caller is messed up. Where this bites you, then is when the caller tries to return to its caller. Likely this is not a problem for main b/c on MARS, for example, we usually exit main via the exit syscall. However, if you do fact(2), you'll see that the first return it executes works ok, but after that the caller (fact itself, recursive caller) doesn't work — it is unable to return to its caller, because it cannot properly restore its previously preserved $ra, because the stack pointer has been unbalanced by the terminal case.
We need to balance prologue with epilogue: not just statically but dynamically.
Your code is allocating stack space in all cases, though in the terminal case, your code is omitting the deallocation of the stack, so it becomes unbalanced.
Either add stack adjustment (deallocation) to the terminal case, or, test for the terminal case before even allocating stack space (so you don't have to either allocate or deallocate in that terminal case).
What is the use of a $zero register in MIPS?
What does it mean?
lw $t0, myInteger($zero)
The zero register always holds the constant 0. There's not really anything special about it except for the fact that 0 happens to be a very useful constant. So useful that the MIPS designers dedicated a register to holding its value. (This way you don't have to waste another register, or any memory, holding the value.)
EDIT:
As for the question of what that line of code means, it loads the word from MEMORY[myInteger + 0] into the $t0 register. The lw command takes both a constant (myInteger) and a register ($zero). Not sure why that is, but that's just how the instructions work. Since myInteger was used as the constant, a register had to be provided, so $zero was used.
I am just started learning exception handler of MIPS instruction.
I need to make my program to have Arithmetic overflow exception so that i can test my exception handler.
I have two array A and B. Array A has hex number and Array B has integers.
How to make overflow by adding hex number and integer ?
The addition of which hex number and integer can cause overflow?
According to the MIPS instruction reference, the only addition operations which can produce overflow exceptions are the signed addition instructions:
ADD
ADDI
MIPS integers are 32-bit, and since you'll be using signed integers, the maximum value is 231-1 (aka 2147483647 or hex 7FFFFFFF). Thus any addition which results in a number larger than this should throw an exception, e.g if you try to add 1 to 2147483647:
# Load 2147483647 into $s1
LUI $s0, 32767
ORI $s1, $s0, 65535
# Add 1 to $s1 and store in $s2. This should produce an overflow exception
ADDI $s2, $s1, 1
Is this statement a valid one?
lw $t0, 21($s0)
$s0 contains the decimal 2022.
In my opinion this is invalid, because based on what I know, The address specified by the offset + the register should always be a multiple of 4. Is this correct or not?
An extension to this question based on the answer provided, The exception will arise just on looking at the address at $s0 or after the computation of the address 21+$s0 ?
The execution of that instruction when $s0 contains the decimal 2022 will raise an exception, due to the effective address (2041=2022+21) is not aligned properly.