You are not logged in.

#1 2008-09-10 13:39:58

MMBosstones86
Member
Registered: 2008-09-10
Posts: 2

need help with assembly and mips architecture

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

#2 2008-09-11 00:30:06

MMBosstones86
Member
Registered: 2008-09-10
Posts: 2

Re: need help with assembly and mips architecture

anything guys?

Offline

#3 2008-09-11 08:20:05

e_tank
Member
Registered: 2006-12-21
Posts: 80

Re: need help with assembly and mips architecture

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 smile .
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

Board footer

Powered by FluxBB