Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   Assembly (http://www.programmingforums.org/forum20.html)
-   -   Divide Overflow? (http://www.programmingforums.org/showthread.php?t=1476)

saxman Dec 8th, 2004 10:45 PM

I'm not new to x86 ASM, but I am new to the square-root-related instructions that Intel has provided. I don't know what I'm doing wrong in my program, but I get a divide overflow. Perhaps someone could take a look at my code and see what is causing this.

This program isn't finished yet, but it's going to draw a sphere. I am doing it purely out of experimental interest. Right now I am just trying to get it to draw pixels to the screen, but I won't know if my algorithms and such are right or not if I can't see anything but an error. I wonder if it's the way I've used the square-root. This is the first time I've made use of it in ASM, so I don't even know if I did it right or not.

Anyway, any help would be appreciated.

BTW: If you find the below code to be hard to read due to the lack of 'tabs' on these forums, you can download the source file -- http://shadowsoft-games.com/saxman/3D.ASM


:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This program is designed to draw a sphere using the following:
;
; Ymax = (Ry/Rx) SQRT(Rx^2 - X^2)
; Zmax = (Rz/Ry) SQRT(Ry^2 - Y^2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

jmp        start



xpos* dw        ?*; X position (0-319)
ypos* db        ?*; Y position (0-199)
zpos* db        ?*; Z position (0-255)
xrad* db        64*; X radius (0-255)
yrad* db        64*; Y radius (0-255)
zrad* db        64*; Z radius (0-255)
store1        dd        ?*; Used to store a floating-point
ymax* db        ?*; Ymax = (Ry/Rx) SQRT(Rx^2 - X^2)
zmax* db        ?*; Zmax = (Rz/Ry) SQRT(Ry^2 - Y^2)
palette        db        00, 00, 00, 01, 01, 01, 02, 02, 02, 03, 03, 03
* db        04, 04, 04, 05, 05, 05, 06, 06, 06, 07, 07, 07
* db        08, 08, 08, 09, 09, 09, 10, 10, 10, 11, 11, 11
* db        12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15
* db        16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19
* db        20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23
* db        24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27
* db        28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31
* db        32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35
* db        36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39
* db        40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43
* db        44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47
* db        48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51
* db        52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55
* db        56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59
* db        60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63



start:
mov        ax, 13h* *; Setup 320x200 video mode
int        10h
mov        ax, 0a000h* *; Set the video address
mov        es, ax

write_palette:
mov        si, offset palette
mov        cl, 192* *; Read 192 color values (64 total colors)
mov        dx, 03c8h* *; Set the palette address
xor** al, al
out        dx, al
cld
inc        dx
rep        outsb

draw_setup:
mov        di, 16000* *; Start from the center of the screen
mov        dx, 63* *; DX is our color selection
call        calculate_ymax



draw_y:
;mov        dx, 63
mov        es:[di], dx
inc        ypos
sub        di, 320
mov        al, ymax
cmp        ypos, al
jl        draw_y

inc        xpos
mov        di, 16000
add        di, xpos
call        calculate_ymax
mov        ax, word xrad
cmp        xpos, ax
jl        draw_y



calculate_ymax:
; Ymax = (Ry/Rx) SQRT(Rx^2 - X^2);
push        ax
push        dx
mov        ax, word yrad
div        xrad
mov        bx, ax* *; BX acts as (Ry/Rx)
mov        ax, word xrad
mul        xrad
push        ax
mov        ax, xpos
mul        xrad
pop        dx
sub        ax, dx
mov        word store1, ax
; (Ry/Rx)
fld        store1* *; Load X
fld        st(0)* **; Duplicate X on TOS
fsqrt* * *; Computer SQRT(X**2 + Y**2)
fst        store1* *; Store away result in Z
mov        ax, word store1
mul        bx
mov        ymax, al
pop        dx
pop        ax
ret
;


kurifu Dec 9th, 2004 12:09 PM

When you divide with asm this is what happens.

You take usually a 32bit value (though it can be 16bit, or 8bit) perform the division and store both the result and the remainder (no decimal values here) into the same block of data we performed the operation on.

Which means dividing a 32bit value results in that 32bit value being broken into a 16bit result and a 16bit remainder. I am sure you can see where this goes wrong now...

What happens if you take a 32bit value, which requires all 32 bits and divide that value by 1? Well as you can imagine the result WILL NOT fit in the 16 bit register in which it is supposed to fit. One of your flags should be raised for this exception, probably OF, you will need to verify that and start checking that flag to make sure that the division occured without error and deal with the error when it occures appropriatly.


All times are GMT -5. The time now is 6:04 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC