Mips assembly language loop through array and isolates bits of interest - byte

I need to loop through this array of bytes
testCases: .byte 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
Im assuming I would do something like this, but not sure
ori $a1, $0, 0x0 # Initialize index with 0
LOOP:
lw $t1, testCases($a1)
...
...
addi $a1, $a1, 1 # Increment index by 1
j LOOP
and isolate the b6,b2,b1,b0 bits using a bitmask. I'm very new to mips and would appreciate any help. Thank you.

No, lw stands for load word. A word is 4 bytes. If you want to load a single byte you should use lb (if you want sign-extension) or lbu (if you want zero-extension).

Related

MIPS overflow logic

Good evening. I am trying to figure out how to determine if an integer qualifies 16 bit integer in MIPS.
I understand that 2^15-1 =32767 or 2^(16-1)-1=32767 and that we want 16 bit values for binary number. Anyway, I am trying to determine if an integer passes the test. I wrote this:
addi $s3, $zero, 32767
bgt $t2, $s3, else #branch to else if t2>s3
move $v0, $t2 #if no overflow; place t2 in v0
addi $v1, $zero, 0 #if no overflow; place zero in v1
else:
addi $v0, $zero, 0 #if overflow; place 0 in v0
addi $v1, $zero, -1 #if overflow; place -1 in v1
Anyway, There's a problem with my logic when I try and evaluate negative numbers. I have assignment due tomorrow. I am learning MIPS programming. I am not a programming snob so any helpful advice is appreciate. Thank you for your time.
This is too late for you assignment1.
It's a bit unclear whenever you want to test a) if a number N encoded as a 32-bit two's complement number can be also encoded as a 16-bit two's complement number or if you want to test b) if a 32-bit number can be encoded as a 16-bit number.
In the case of b) you just need to test if any bit higher than the 16th is set:
#Assume $t0 is the number to test
lui $t1, 0xffff #$t1 = 0xffff0000
and $t1, $t1, $t0 #$t1 is zero if all higher bits of $t0 are zero
beq $t1, $0 fits16bits #Jump to label if fits
#Here the number doesn't fit 16 bits
For the case a) the key is to understand that just like the number 0x00f1 and the number 0x0000000f1 are the same, the leading zeros are not significant, the number 0xffff and the number 0xffffffff are the same number in two's complement (the number -1).
To extend a 16-bit two's complement number to 32-bit we need to perform a sign extension, i.e. replicate the most significant bit (the sign bit) of the original number in the upper 16 bits.
So 0x7fff becomes 0x00007fff, 0xc000 becomes 0xffffc0000.
A simple way to test that all the upper 17 bits are equal is to shift them right arithmetically so that if they actually are equal we end up with 0x00000000 or 0xffffffff.
sra $t1, $t0, 15 #Shift right 16 bits duplicanting the MSb
beqz $t1, $0, fits16bits #Jump to label if fits (All zero)
addiu $t1, 1 #Add 1
beqz $t1, $0, fits16bits #Jump to label if fits (Before +1 was all ones)
#Here the numbers doesn't fit
1 Maybe it's better this way.

MIPS and Assembly finding the sections of a parameter block

In a function, the arguments given contains a parameter block. In that parameter block the first two sections contain separate strings, and the third section will store the combined string. How do determine the address locations of the sections of the parameter block?
Perform Indexing or Indirect Addressing.
Here's an example:
.data
.align 2
problem1:
.word str_a1 # First number
.word str_a2 # Second number
.word buf_a # Place to store the result
.word 1 # Length of both numbers and result buf
.word out_a # Where to start printing the answer
.text
...
la $a0,problem # Address of parameters for
jal print_label # problem 1, and do it.
print_label:
...
move $s0, $a0 # copy the loc of the parm block to s0
li $v0, 4 # print 1st number
lw $a0, 0($s0)
syscall
li $v0, 4 # print 2nd number
lw $a0, 4($s0) # Indexing!
syscall
li $v0, 4 # print newline at end
la $a0, result3
syscall
The label representations are irrelevant. In essence the contents of $a0 are copied into $s0 and are accessed with indexing. If you were to increment its 'pointer' then that would be indirect displacement.
Perform whatever operations and they can be saved at a displaced location in the parameter block $a0 then read out as shown in the label problem1.

How to improve cache performance on this MIPS code

Using a simulator called MARS 4.5 I am trying to improve the cache performance of this code. This is a sub section of an assembly program that computes prime numbers using the Sieve of Eratosthenes algorithm.
For some reason the sw (store word) has a cache hit rate of 25% where the rest of the program is averaging at about 50% in it's current state. I've tried rearranging some things but I can't figure out what is causing this bottleneck. What needs to be done in order to improve this cache hit rate?
inner: add $t2, $s2, 0 # save the bottom of stack address to $t2
mul $t3, $t1, 4 # calculate the number of bytes to jump over
sub $t2, $t2, $t3 # subtract them from bottom of stack address
add $t2, $t2, 8 # add 2 words - we started counting at 2!
sw $s0, ($t2) # store 1's -> it's not a prime number!
add $t1, $t1, $t0 # do this for every multiple of $t0
bgt $t1, $t9, outer # every multiple done? go back to outer loop
j inner # some multiples left? go back to inner loop
I was able to fix this issue by modifying the program to store bytes instead of words. This increased the number of storage blocks in the cache and thus increased the hit rate.
inner: add $t2, $s2, 0 # save the bottom of stack address to $t2
addi $t3, $t1, 1 # add one byte
sub $t2, $t2, $t3 # subtract them from bottom of stack address
add $t2, $t2, 2 # add 2 bytes - we started counting at 2!
sb $s0, ($t2) # store 1's -> it's not a prime number!
add $t1, $t1, $t0 # do this for every multiple of $t0
bgt $t1, $t9, outer # every multiple done? go back to outer loop
j inner # some multiples left? go back to inner loop

Using a random number generator in MIPS?

So I was reading a few threads on this site and I found one on how to make one..
But I can't really find a link that explains more about how to code it..
My textbook for the course didn't provide any information about RNG at all so no help there.
The code was
li $a1, 4
li $v0, 42
add $a0, $a0, 1
is this correct for asking for a range between 1-3?
I tried outputting what random number it was but it gave me the same number constantly.
#sw $a0, 0($s0)
li $a1, 4
li $v0, 42
add $a0, $a0, 1
#syscall
li $v0, 4
la $a0, Checking
syscall
li $v0, 1
move $t0, $a0
syscall
I saw the sw $a0, 0($s0) but I'm not sure what that does -- is it needed to output? (I took it out because after I pushed a key to go to the RNG, it said the program crashed)
I keep getting the output of 268501267 which I'm not sure what that means
edit: now it started giving me 268500992 all the time
Can anyone help explain this a little more in depth?
Logically speaking -- I understand the where the 42 comes from and why I need to add +1 (This is so I won't get the value of 0)
From there, I have no clue on why the code won't output a number in the range I gave.
As stated by MARS documentation (in the GUI Help > Syscalls):
random int 41 $a0 = i.d. of pseudorandom number generator (any int).
$a0 contains the next pseudorandom, uniformly distributed int value
from this random number generator's sequence
So
li $v0, 41 ; Service 41, random int
li $a0, 0 ; Select random generator 0
syscall ; Generate random int (returns in $a0)
li $v0, 1 ; Service 1, print int
syscall ; Print previously generated random int
Works fine for me, every time a different number is printed.
You don't need to initialize or seed a random stream before using it, you can just use stream 0.

How to use system call 9 (sbrk) for dynamic memory allocation in MIPS

I have an assignment which is to write comb sort in MIPS. The user is going to enter the array and of course its size. When searching for heap allocation, I found the system call 9. However, I couldn't find the way to use it. I wrote this:
li $v0, 4
la $a0, message1 # prints the first message
syscall
li $v0, 5 # reads the size for the array
syscall
mul $t0, $v0, 4 # because array contains integer, I change them into bytes
la $a0, $t0 # allocate the size of the array in the heap
li $v0, 9 # now, $v0 has the address of allocated memory
syscall
move $v1, $v0 # Because systemcall uses $vo register, I move it to $v1 keep it safe.
create_array:
la $a0, message2 # prints the first message
li $v0, 4
syscall
li $s0, 0 # $s1 is the index, and loop induction variable
li $s1, 5 # $s1 is the sentinel value for the loop
Loop1:
bge $s0, $s1, End_Loop1
li $v0, 5 # Read integer values
syscall
mul $t3, $s0, 4 # $t3 is the offset
add $t4, $t3, $t0 # $t4 is the address of desired index
sw $v0, ($t4) # store the value in the array
addi $s0, $s0, 1 # increment the index
j Loop1
End_Loop1:
And I get this error:
la": Too few or incorrectly formatted operands. Expected: la $t1,($t2)
How can I use it? and Is this the right way to create an array?
Replace
la $a0, $t0 # allocate the size of the array in the heap
with
move $a0, $t0
The la instruction's purpose is to [L]oad the [A]ddress of a symbol into a register. For example:
la $a0, message1 # prints the first message
would load the address of message1 into register $a0. la is actually a pseudo-instruction which in this case translates into:
lui $a0, message1/0x10000 # load the upper halfword of the address
ori $a0, $a0, message1%0x10000 # OR in the lower halfword of the address
As you can imagine it doesn't make sense to try to load the address of another register, since registers don't have addresses.
While we're on the subject of MIPS pseudo-instructions: move is also one of them, and the above move $a0, $t0 instruction translates into something like add $a0, $0, $t0.
Also, replace $t0 with $v1. $t0 just holds the total byte allocated in the heap but you need $v1 which is the beginning addres of the array in the heap.
It should be like:
add $t4, $t3, $v1 # $t4 is the address of desired index

Resources