Expand variable number of arguments in memory to argument space - mips

I have a function that takes a memory address as $a0 and I access the (variable) number of words by using x($a0), where x is multiples of 8. I need to store these in the $sp register so I can use the $a0 register for passing arguments to other functions. Completely new to MIPS assembly, so any pointers here would help!

Multiples of 8 i assume you are using mips-64
first u make a loop and increment a0 by 8 each time:
loop: lw $t0, 0($a0) ;fetch data and store in t0
addi $sp,$sp,-8 ;increase stack
sw $t0, 0($sp) ;store data fetched
addi $a0,$a0,8 ;increment a0 to go to next entry
;here you check that you haven't reached x yet
;let's say 8*x+$a0(initial) is stored in $t1 (this is easy to do just use sll by 3 to multiply by 8 then add a0 before loop)
bne $a0,$t1,loop
;now you can use $a0

Related

Write into next byte of a register

I understand that registers in memory are 32 bits. I also understand that lb will load contents from memory into the lower 8 bits of a register, and that if I did
lb $t1, $a3
lb $t1, 4($a3)
The second lb command will overwrite the contents loaded in the first. However, is there a way to write into the second byte of a register (loading from a different part in memory, so not two bytes right next to each other) and preserve the information of the first byte?
I am assuming what you want to use here is lbu (load byte unsigned) and not lb because you don't want the register to be sign extended (e.g. copying the byte AA in the register will result in 000000AA, and not FFFFFFAA).
If you want to write to the second byte of a register you can first use lbu to load the byte from memory to another register, then shift left 8 bits, and addu it to the original register.
For example:
lbu $t1, $a3 # 0x000000AA
lbu $t2, 4($a3) # 0x000000BB
sll $t2, $t2, 8 # 0x000000BB -> 0x0000BB00
addu $t1, $t1, $t2 # 0x000000AA + 0x0000BB00 = 0x0000BBAA

Replacing left logical shifts with other instructions in MIPS

So let's say that we have two registers $s0 and $s1. Register $s0 can take values from 0 to 31 and is used to show how many bits register $s1 will be shifted left. How can i do this without using sll or srl. I know that left logical shift by n bits is the same as multiplying with 2^n. This exercise gives a hint that this can be done with 4 instructions only. Both registers are 32-bit.
You can add $s1 to itself $s0 times (each time it will multiply its value by 2 which shifts its bits left once).
The code would look like this:
beqz $s0, end
loop:
add $s1, $s1, $s1
subu $s0, $s0, 1
bnez $s0, loop
end:
The first conditional branch is to ensure no action is taken to $s1 when $s0 holds value zero.

What happens when I give an offset to a "temporary register" in MIPS

For example:
$t0 = A
$t1 = B
$t2 = C
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
As long as your temporary registers are next to each other in memory.
i.e.
Reference: $t1 $t2
Mem Blocks: [byte][byte][byte][byte][byte][byte][byte][byte]...
Programs like Logisim should have the registers packed tightly.
Helpful page here from UC Berkeley.
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
No, it would not. The lw instruction is used to load data from memory, not to copy the value of one register into another register. To quote from the MIPS manual:
LW rt, offset(base) MIPS32 (MIPS I)
Purpose:
To load a word from memory as a signed value
Description: rt ← memory[base+offset]
The contents of the 32-bit word at the memory location specified by the aligned effective address are fetched,
sign-extended to the GPR register length if necessary, and placed in GPR rt. The 16-bit signed offset is added to the
contents of GPR base to form the effective address.
In other words, what lw $t1, 4($t0) does is form an effective address by adding the value of $t0 with the value 4, and load a word (four bytes) from that address into register $t1.

Printing out value in loop

Hey guys Im new to ComArch. Im writing a homework assignment. My question is i have this loop in my program that divides a users int input by 10 and my loop will go through the and divide until the quotient is at 0 . Currently it prints out 0 for my quotient but doest print out each value of the remainder. So how would i modify my code to print out every single remainder that is left over after dividing.
loop:
li $s0, 10 #divisor
div $t0,$s0 #divide input by 10
mflo $t0 #quotiant
mfhi $t3 #remainder
sw $t3, ($t1) #stores emainder into address of int_a
addi $t1,$t1,4 #increases the pointer
bne $t0,0,loop
You will find in the MIPS Architecture and Assembly Language Overview the section "System Calls and I/O (SPIM Simulator)" which details how to print a value.
In your case, within the loop, you would have to print $t3.
li $v0, 1 # load appropriate system call code into register $v0;
# code for printing integer is 1
move $a0, $t3 # move integer to be printed into $a0: $a0 = $t3
syscall # call operating system to perform operation

MIPS How to branch to a 32-bit address?

I am trying to branch to an address:
bne $t0, $0, 0x7813a21c
However, this is incorrect because bne only allocates 16-bits to the immediate
How can I branch to a direct 32-bit address? Is there a way to branch from a value in a register?
You have to use JR to jump to an address stored in a register.
To preform this type of operation you will need a jump statement. You have to tell the code to jump control context to the exact line you wish to specify. This is example syntax: j offset Where in your address is the offset.
Here is a link that better reviews what you have to do. Check out the section on jump. These are the types of jump available. One of them is what you need: j offset, jal offset, jr $rs, jalr $rs
Here is the link:
http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/jump.html
Good luck
We can load 32-bit addresss to the register (e.g. $t1) in 2 steps:
Load the upper 16 bits by lui (Load Upper Immediate).
Load the lower 16 bits by ori (Or Immediate).
NOTE: It is work because lui fills the lower 16 bits with 0s, so bitwise OR load the lower 16 bits (n | 0 = n);
In code below if $t0 is equal to 0 we do skip jr instruction.
Or if $t0 is not equal to 0 we do not skip jr instruction (or we do jump).
beq $t0, $0, SKIP
# load 0x7813a21c to $t0
lui $t1, 0x7813 # load the upper 16 bits
# Now $t1 = 0x78130000
ori $t1, $1, 0xa21c # load the lower 16 bits
# Now $t1 = 0x7813A21C
jr $t1 # as #Matt Eckert said
SKIP: