You are not logged in.
one of the labs for a class wants us to program some subroutines in assembly, and assembly and me don't get along at all.
the first one goes like this:
Since our ALU cannot perform multiplication, it would be useful to have a subroutine written in assembly for our processor to multiply two numbers. You must construct an algorithm that multiplies two unsigned words by using a shift-add loop to form a four byte product (This could overflow the product). Remember that shifting left by 1 equals multiplying the number by 2. You have add instructions, shift instructions, and branch instructions at your disposal.
To pass data to this routine, we will set up a simple stack. We will be using the stack pointer register ($29 or $sp). $sp will point to the top of the stack. Here is one way to use the stack, this is not the only way. To pop something off the stack, you must:
1. Load the data pointed to by register $sp (LW $t1, 0($sp));
2. Add 4 to $sp.
To push data onto the stack:
1. Subtract 4 from $sp
2. Store the data into the location pointed to by $sp (SW $t1, 0($sp))
You may need to initialize $sp to 0x3FFC. This way, when pushing the first data value, you store to 0x3FF8.
When you need the two values to multiply, you will pop them off the stack and into registers of your choice. When your value is computed, you will push it back onto the stack. For example, operands will be at addresses 0x3FF8 and 0x3FF4. $sp will be set at 0x3FF4. Load both operands, multiply them, then push the result back on the stack. $sp should end up with the value of 0x3FF8. You can check these values in your memdump.hex file.
heres what i've come up with so far
org 0x0000
ori $15, $zero, 0x3FFE # two spots lower
mult:
# < insert your code here >
# < notice that the stack has already been setup
# Load first word from stack and increment stack
lw $t0, 0($sp)
lw $t1, 4($sp)
xor $6, $6, $6
loop: beq $t0, $6, exit
andi $4, $t0, 1
sll $4, $4, 31
srl $4, $4, 31
and $4, $4, $1
add $5, $5, $4
sll $t1, $t1, 1
srl $t0, $t0, 1
j loop
exit: addi $t1, $5, 0
sw $t1, 4($sp)
halt
org 0x3FFE
cfw 5
cfw 10
but that doesn't seem to be working very well
anything anyone can provide would be great. thanks
Offline
anything guys?
Offline
i wrote a mips mult function for someone else on the forums over a year ago and there was a mistake i made on it that i never corrected. i knew about it a little while after i posted it but thought i'd leave it just to see if anyone would notice. anyway it looks like you made the same mistake as i did .
the problem is how we both generated the mask that we use to multiply a bit from one operand against the other, the result of which is added to the total. after you logical shift left the bit to place it in the msb of a register you need to arithmetic shift right it into the lsb to generate the mask (ie all bits set if 1, none if 0), not logical shift right which just gives you what you started with.
below is a fixed version of the routine i posted before, not that it matters much but i also changed it so the routine jumps into the multiplication loop which saves an instruction per iteration of the loop.
@ input
@ $1 = int op1
@ $2 = int op2
@ output
@ $1 = res
@ using regs
@ $3 = sign
@ $4 = temp
@ $5 = acc/current total
@ $6 = temp for 0 comparison, do i need todo this?
@ (pasting this from vim to here screwed up the tabs on the comments, sorry it looks like crap)
smult:
sra $3,$1,31 @ sign = asr op1,31
xor $1,$1,$3 @ invert op1's bits if < 0
sub $1,$1,$3 @ add 1 if < 0
sra $4,$2,31 @ same but for op2
xor $2,$2,$4
sub $2,$2,$4
xor $3,$3,$4 @ save the sign of mult
xor $5,$5,$5 @ init res acc mov $5,0
xor $6,$6,$6 @ used for 0 cmp
j lmult_start
lmult_loop:
andi $4,$2,1 @ get lsb of op2
sll $4,$4,31 @ if set add op1 to res acc
sra $4,$4,31
and $4,$4,$1
add $5,$5,$4
sll $1,$1,1 @ shift op1 left 1
srl $2,$2,1 @ and op2 right 1
lmult_start:
bne $2,$6,lmult_loop @ break when op2 is 0
addi $1,$5,0 @ put result in $1
xor $1,$1,$3 @ invert if sign is negative
sub $1,$1,$3
jr $31 @ return
edit:
forgot to mention that in my original post in a previous thread i had edited the routine to change something in the loop and it was then that i introduced the error. so tastyphox, the forum member who had looked over the code for me, did not miss the error as it wasn't there yet.
i also noticed on your routine that you popped two values from the stack, placed one back on, and then forgot to adjust the stack pointer for this. you stored your result in the correct place (ie address (sp+4)) so just add 4 to the sp after this to have it point to the value you just placed on it.
also the routine i posted a fix to was for a signed mult, so you can ignore the parts where i clear/set the sign bit of op1, op2, and the result.
Last edited by e_tank (2008-09-11 09:17:11)
Offline