Home > Net >  array[i]%2 and value from the user in assembly
array[i]%2 and value from the user in assembly

Time:12-17

i need to write this code in MIPS assenbly:

int i, size, result = 0;
int * array;
...
//size gets a value from the user
//array is allocated according to this value
...
for ( i=0;i<size;i   )
{
if (array[i] %2 ==0) // if array[i] is even
result  = array[i]; // add it to the result
}

and The registers used are $s1 for i, $s2 for size, $s3 for the starting address of the array, and $s4 for the result.

I wrote:

ori $s1,$0,0  // int i
ori $s3,array // int array *
add $s4,$zero,$zero  // int result = 0;

l1:
bge $s1,$s2,Done // for loop i<size
...
lw $5, 0($s3) // $5 = array[I]
addu $s4,$s4,$s5 // result  = array[I]
j UPDATE

UPDATE:
addi $s1, $s1, 1 // i  
addi $s4, $s4, 4 // move array pointer
j L1 // goto l1

DONE:
nop

I don't know how to write 2 things:

  1. if (array[i] %2 ==0)
  2. size gets a value from the user please help me with those things. Thank you

So i wrote now:

ori $s1,$0,0  // int i
li   $v0, 5 // scan int from user
la $s3,array // int array *
add $s4,$zero,$zero  // int result = 0;

l1:
bge $s1,$s2,Done // for loop i<size
lw $s5, 0($s3) // $s5 = array[I]
add $s6,$zero,$s5 // $s6 = $s5
mov $s6, 31 
and $s7,$s6,1
bne $s7, $zero, ADDING
j UPDATE

ADDING:
addu $s4,$s4,$s5 // result  = array[I]
j UPDATE

UPDATE:
addi $s1, $s1, 1 // i  
addi $s4, $s4, 4 // move array pointer
j L1 // goto l1

DONE:
nop

CodePudding user response:

Suggest you start with some working examples: lots of MIPS examples are out there.

However, you have C code and are following that in MIPS, which is a very good approach.


First, suggest you declare the array as a global, perhaps you already did, but it was not shown.


This instruction ori $s3,array // int array * needs to be an la opcode, standing for "load address" (for MARS or QtSpim).  These will load the address of the label into the register.


array[i] is accomplished by scaling i from an index into a byte offset, then adding that byte offset to the byte address of array, and finally dereferencing that pointer.  Since each element of the array occupies 4 bytes, and, on a byte addressable machine, each individual byte gets its own address, then the next array element is 4 addresses further along in memory.  Thus, index 0 is at address of array but index 1 is at array 4.  We don't see this scaling in C, because it knows types (it knows the element size is 4, so 1 means 4) and does the scaling automatically.

So, we scale (i.e. multiply) i by 4, which, because 4 is a power of 2, is normally done by shifting 2 bits to the left.  Shifting is like multiplying by 10 but in binary instead of decimal, so that really multiplies by 2.  Shifting twice multiplies by 100 binary so, by 4 decimal.  Of course, MIPS can shift 2 places in one instruction.

To do that shift, you'll need to pick an otherwise unused register to hold the intermediate result, the byte offset.  Suggest the $t registers for these kind of short-lived temporary values.

Then add that intermediate result to the byte address of the base of the array, here $s3 (perhaps also sending that result to another otherwise unused register).

That new intermediate value can now be dereferenced as you are doing with lw $5, 0($s3) // $5 = array[I] except with the indexing computation as the base address instead of $s3.


In the beginning before the loop, you also need to have initialized $s2 with the size.


The following construct is not harmful but also not useful:

j UPDATE

UPDATE:

You can leave the label if it helps you but there's no need to j from the immediately preceding instruction as the processor will do that naturally.

To be clear, labels are for assembly code but they are removed by the assembler and do not appear in the machine code.  The processor only does things in execution of machine code instructions.  Every instruction tells the processor what instruction to execute next, so the addu $s4,$s4,$s5 // result = array[I] can/will tell the processor to execute addi $s1, $s1, 1 // i without the need for the j.


Be careful of typos as in the following:

lw $5, 0($s3) // $5 = array[I]
addu $s4,$s4,$s5 // result  = array[I]

The first line should be designating $s5 not $5, which is allowed, but a different different register ($a1).  (I would have used a $t register for that intermediate result instead of an $s register, but no matter.)


You can do the % 2 by dividing or much simpler by checking the low bit.  The C expression would be & 1 as in array[i] & 1.  Since in binary the low bit position represents 20, then this is the way to check even/odd (the 0 bit position is the only odd power of 2).  MIPS can do that masking in one instruction.  The 1 as a mask says keep only the low bit from the other operand (array[i]).

The == 0, because it is part of a conditional operation would be done similar to the bge that you have for the for loop exit condition.


To get numbers from the user in MARS, use syscall # 5.  Follow instructions from the help or many examples online here or elsewhere.

  • Related