DaniWeb IT Discussion Community

DaniWeb IT Discussion Community (http://www.daniweb.com/forums/index.php)
-   Assembly (http://www.daniweb.com/forums/forum125.html)
-   -   Arithmetic Overflow - MIPS (http://www.daniweb.com/forums/thread200615.html)

pokerstar Jun 30th, 2009 3:38 am
Arithmetic Overflow - MIPS
 
I am converting an MASM procedure to MIPS.
Here's the MASM:
; --------------------------------------------------------
;  Find basic list stats - minimum, median, and maximum.

;  Arguments passed:
;        list, addr (4)
;        length, value (6)
;        minimum, addr (8)
;        maximum, addr (10)
;        median, addr (12)

stats1        proc        near
       
        pop        bp
        mov        bp, sp

        push        ax
        push        bx
        push        cx
        push        dx

; -----
; Find max.

        mov        bx, word ptr 4[bp]
        mov        ax, word ptr [bx]
        push        bx
        mov        bx, word ptr 10[bp]
        mov        word ptr [bx], ax

; -----
; Find min.

        mov        ax, word ptr 6[bp]
        dec        ax
        add        ax, ax
        pop        bx

        add        bx, ax
        mov        ax, word ptr [bx]
        mov        bx, word ptr 8[bp]
        mov        word ptr [si], ax

; -----
; Find median.

        mov          bx, word ptr 4[bp]
        mov          cx, word ptr 6[bp] 
        mov          si, cx

        mov        ax, si
        and        ax, 1
        cmp        ax, 0
        je        even_lp

        dec        si
        mov        ax, word ptr [bx][si]
        jmp        odd_lp
; -----
; Length is even.

even_lp:
        mov        ax, word ptr [bx][si]
        sub        si, 2
        add        ax, word ptr [bx][si]
        mov        dx, 0
        div wtwo

; -----
; Length is odd.

odd_lp:
        mov          bx, word ptr 12[bp]
        mov        word ptr [bx], ax

        pop        dx
        pop        cx
        pop        bx
        pop        ax
        pop        bp

        ret        10

stats1        endp

Now here's my conversion to MIPS:
# -----
#    Arguments:
#        $a0 - starting address of the list
#        $a1 - list length
#        $a2 - addr of minimum
#        $a3 - addr of median
#        ($fp) - addr of maximum
#        4($fp) - addr of sum
#        8($fp) - addr of average
.globl stats
.ent stats
stats:

        subu        $sp, $sp, 12
        sw        $s0, 0($sp)
        sw        $fp, 4($sp)
        sw        $ra, 8($sp)
        addu        $fp, $sp, 12       
# -----
# Find min.

        lw        $t0, ($a0)
        sw        $t0, ($a2)                        #minimum, first element of array
# -----
#Find max.

        subu        $t0, $a1, 1
        mul        $t0, $t0, 4
        addu        $t0, $t0, $a0
        lw        $t1, ($t0)
        sw        $t1, ($fp)                        #maximum, last element of array

# -----
# Find median.

        lw        $t0, ($a0)
        move        $t1, $a1
        andi        $t2, $t1, 1
        beq        $t2, $zero, even_lp

        subu        $t1, $a1, 1
        mul        $t1, $t1, 4
        addu        $t1, $t1, $a0
        lw        $t2, ($t1)
        b        odd_lp

even_lp:
        mul        $t3, $t1, 4
        addu        $t3, $t3, $a0
        lw        $t4, ($t3)
        subu        $t1, $t1, 1
        mul        $t5, $t1, 4
        addu        $t5, $t5, $a0
        lw        $t6, ($t5)
        addu        $t6, $t6, $t4
        div        $t6, $t6, 2

odd_lp:
        sw        $t2, ($a2)                        #median

sw        $ra, 8($sp)
        sw        $fp, 4($fp)
        sw        $s0, 0($sp)
        addu        $sp, $sp, 12
        jr        $ra

.end stats

Now I don't know why the console displays arithmetic overflow.
What am I doing wrong?

wildgoose Jun 30th, 2009 2:51 pm
Re: Arithmetic Overflow - MIPS
 
And why are you storing your return address into your address of average?

Also in odd_lp you're storing the list entry to the minimum $a2 not the median $a3 as your comment says


        sw        $t2, ($a2)                   Save minimum           #median

        sw        $ra, 8($sp)        Save return address?


        sw        $fp, 4($fp)
        sw        $s0, 0($sp)
        addu        $sp, $sp, 12
        jr        $ra

You know the 80x86 code has a bug?

You should have displayed the C equivalent function. Finding someone knowing both 80x86 and MIPS can be difficult.


OH, this is assembly language. Almost every line of code needs documentation. At a minimum every sub block. Detailing what data is being accessed!

On the PC you are using an array of 16-bit numbers?
And on the MIPS an array of 32-bit numbers?

If int list[] was used on both platforms then the memory access is correct. If not then a problem as the following discusses.

If the data on the MIPS is 16-bit then you need to manipulate the load. That is load 32-bit and shift the number into position (high/Low) Load, or you'll get an alignment error.

If the data on MIPS is 16-bit then you are running off the end of the list, thus bad data.

Since the 80x86 version didn't overflow I'm assuming your numbers are small values. But on the MIPS if 16-bit then you're reading pairs of numbers which appear to be a very large number thus easy to overflow. You are using lw meaning load word and a word is 32-bit.
         80x86          MIPS
          byte            byte            8-bit
          word            half-word    16-bit
          dword          word            32-bit
          qword          dword          64-bit

You are scanning the list backwards which isn't memory efficient, however, you don't need to keep doing your pointer math. Merely set your pointer to your list[] entry, then either step backwards by (4 if 32-bit) until the pointer reaches the advancing pointerl. (Beginning of buffer). Or use your length count as a down count by two, and step the two pointers toward each other. When count reaches one or zero you've finish parsing the list. Better yet, pre-subtract one so when the count reaches zero or negative then you're done.

Also why are you dividing by two, when you merely need to do a logical shift right by 1.



I'll keep looking for your problem! But that should be something to double-check, as well as comment in your code!

BTW - In the 80x86 code they could have used a scalar with the register for the memory access and saved some operands.



And where is your loop for all list elements? It seems to only be looking at the last two!


All times are GMT -4. The time now is 10:22 pm.

Forum system based on vBulletin Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
©2003 - 2009 DaniWeb® LLC