home *** CD-ROM | disk | FTP | other *** search
- ; Generic assembler routines that have very little at all
- ; to do with fractals.
- ;
- ;
- ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
- ;
- ; multiply()
- ; divide()
- ;
-
- .MODEL medium,c
-
- ; I don't know why this has to be here, but BC++ won't create public
- ; symbols without it.
-
- public multiply, divide, toextra, fromextra, cmpextra
-
-
- .8086
-
- .DATA
-
-
- ; ************************ Public variables *****************************
-
- public overflow ; Mul, Div overflow flag: 0 means none
-
- ; arrays declared here, used elsewhere
- ; arrays not used simultaneously are deliberately overlapped
-
- public prefix, suffix, dstack, decoderline ; for the Decoder
- public strlocn, teststring, block ; used by the Encoder
- public boxx, boxy, boxvalues ; zoom-box arrays
- public olddacbox ; temporary DAC saves
- public rlebuf ; Used ty the TARGA En/Decoder
-
- ; ************************* "Shared" array areas **************************
-
- ; Short forms used in subsequent comments:
- ; name........duration of use......................modules....................
- ; encoder "s"aving an image encoder.c
- ; decoder "r"estoring an image decoder.c, gifview.c
- ; zoom zoom box is visible zoom.c, video.asm
- ; vidswitch temp during video mode setting video.asm
- ; vidreset temp during video reset prompts.c, fractint.c, rotate.c, cmdfiles.c
- ; tgaview restore of tga image tgaview.c
- ; solidguess image gen with "g", not to disk calcfrac.c
- ; btm image gen with "b", not to disk calcfrac.c
-
- block label byte ; encoder(266)
- suffix dw 2048 dup(0) ; decoder(4k), vidswitch(256)
-
- teststring label byte ; encoder(100)
- dstack dw 2048 dup(0) ; decoder(4k), solidguess(4k), btm(2k)
- ; zoom(2k)
-
- strlocn label word ; encoder(10k)
- prefix label word ; decoder(8k), solidguess(6k)
- olddacbox label byte ; vidreset(768)
- boxx dw 2048 dup(0) ; zoom(4k), tgaview(4k)
- boxy dw 2048 dup(0) ; zoom(4k)
- boxvalues label byte ; zoom(2k)
- decoderline db 2050 dup(0) ; decoder(2049), btm(2k)
-
- rlebuf db 258 dup(0) ; f16.c(258) .tga save/restore?
-
- ; Internal Overflow flag
-
- overflow dw 0 ; overflow flag
-
-
- ; =======================================================
- ;
- ; 32-bit integer multiply routine with an 'n'-bit shift.
- ; Overflow condition returns 0x7fffh with overflow = 1;
- ;
- ; long x, y, z, multiply();
- ; int n;
- ;
- ; z = multiply(x,y,n)
- ;
- ; requires the presence of an external variable, 'cpu'.
- ; 'cpu' == 386 if a 386 is present.
-
- .8086
-
- .DATA
-
- extrn cpu:word ; cpu flag: 88 = 8088/8086
- ; 186 = 80188/186
- ; 286 = 80286
- ; 386 = 80386/486
- extrn fpu:word ; fpu flag: 0 = none
- ; 87 = 8087
- ; 287 = 80287
- ; 387 = 80387/(487)
-
- temp dw 5 dup(0) ; temporary 64-bit result goes here
- sign db 0 ; sign flag goes here
-
- .CODE
-
- multiply proc x:dword, y:dword, n:word
-
- cmp cpu,386 ; go-fast time?
- jne slowmultiply ; no. yawn...
-
- .386 ; 386-specific code starts here
-
- mov eax,x ; load X into EAX
- imul y ; do the multiply
- mov cx,n ; set up the shift
- cmp cx,32 ; ugly klooge: check for 32-bit shift
- jb short fastm1 ; < 32 bits: no problem
- mov eax,edx ; >= 32 bits: manual shift
- mov edx,0 ; ...
- sub cx,32 ; ...
- fastm1: shrd eax,edx,cl ; shift down 'n' bits
- js fastm3
- sar edx,cl
- jne overmf
- shld edx,eax,16
- ret
- fastm3: sar edx,cl
- inc edx
- jne overmf
- shld edx,eax,16
- ret
- overmf:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
- ret
-
- .8086 ; 386-specific code ends here
-
- slowmultiply: ; (sigh) time to do it the hard way...
- push di
- push si
-
- mov ax,0
- mov temp+4,ax ; first, zero out the (temporary)
- mov temp+6,ax ; result
- mov temp+8,ax
-
- mov bx,word ptr x ; move X to SI:BX
- mov si,word ptr x+2 ; ...
- mov cx,word ptr y ; move Y to DI:CX
- mov di,word ptr y+2 ; ...
-
- mov sign,0 ; clear out the sign flag
- cmp si,0 ; is X negative?
- jge mults1 ; nope
- not sign ; yup. flip signs
- not bx ; ...
- not si ; ...
- stc ; ...
- adc bx,ax ; ...
- adc si,ax ; ...
- mults1: cmp di,0 ; is DI:CX negative?
- jge mults2 ; nope
- not sign ; yup. flip signs
- not cx ; ...
- not di ; ...
- stc ; ...
- adc cx,ax ; ...
- adc di,ax ; ...
- mults2:
-
- mov ax,bx ; perform BX x CX
- mul cx ; ...
- mov temp,ax ; results in lowest 32 bits
- mov temp+2,dx ; ...
-
- mov ax,bx ; perform BX x DI
- mul di ; ...
- add temp+2,ax ; results in middle 32 bits
- adc temp+4,dx ; ...
- jnc mults3 ; carry bit set?
- inc word ptr temp+6 ; yup. overflow
- mults3:
-
- mov ax,si ; perform SI * CX
- mul cx ; ...
- add temp+2,ax ; results in middle 32 bits
- adc temp+4,dx ; ...
- jnc mults4 ; carry bit set?
- inc word ptr temp+6 ; yup. overflow
- mults4:
-
- mov ax,si ; perform SI * DI
- mul di ; ...
- add temp+4,ax ; results in highest 32 bits
- adc temp+6,dx ; ...
-
- mov cx,n ; set up for the shift loop
- cmp cx,24 ; shifting by three bytes or more?
- jl multc1 ; nope. check for something else
- sub cx,24 ; quick-shift 24 bits
- mov ax,temp+3 ; load up the registers
- mov dx,temp+5 ; ...
- mov si,temp+7 ; ...
- mov bx,0 ; ...
- jmp short multc4 ; branch to common code
- multc1: cmp cx,16 ; shifting by two bytes or more?
- jl multc2 ; nope. check for something else
- sub cx,16 ; quick-shift 16 bits
- mov ax,temp+2 ; load up the registers
- mov dx,temp+4 ; ...
- mov si,temp+6 ; ...
- mov bx,0 ; ...
- jmp short multc4 ; branch to common code
- multc2: cmp cx,8 ; shifting by one byte or more?
- jl multc3 ; nope. check for something else
- sub cx,8 ; quick-shift 8 bits
- mov ax,temp+1 ; load up the registers
- mov dx,temp+3 ; ...
- mov si,temp+5 ; ...
- mov bx,temp+7 ; ...
- jmp short multc4 ; branch to common code
- multc3: mov ax,temp ; load up the regs
- mov dx,temp+2 ; ...
- mov si,temp+4 ; ...
- mov bx,temp+6 ; ...
- multc4: cmp cx,0 ; done shifting?
- je multc5 ; yup. bail out
-
- multloop:
- shr bx,1 ; shift down 1 bit, cascading
- rcr si,1 ; ...
- rcr dx,1 ; ...
- rcr ax,1 ; ...
- loop multloop ; try the next bit, if any
- multc5:
- cmp si,0 ; overflow time?
- jne overm1 ; yup. Bail out.
- cmp bx,0 ; overflow time?
- jne overm1 ; yup. Bail out.
- cmp dx,0 ; overflow time?
- jl overm1 ; yup. Bail out.
-
- cmp sign,0 ; should we negate the result?
- je mults5 ; nope.
- not ax ; yup. flip signs.
- not dx ; ...
- mov bx,0 ; ...
- stc ; ...
- adc ax,bx ; ...
- adc dx,bx ; ...
- mults5:
- jmp multiplyreturn
-
- overm1:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
-
- multiplyreturn: ; that's all, folks!
- pop si
- pop di
- ret
- multiply endp
-
-
- ; =======================================================
- ;
- ; 32-bit integer divide routine with an 'n'-bit shift.
- ; Overflow condition returns 0x7fffh with overflow = 1;
- ;
- ; long x, y, z, divide();
- ; int n;
- ;
- ; z = divide(x,y,n); /* z = x / y; */
- ;
- ; requires the presence of an external variable, 'cpu'.
- ; 'cpu' == 386 if a 386 is present.
-
-
- .8086
-
- divide proc x:dword, y:dword, n:word
-
- push di
- push si
-
- cmp cpu,386 ; go-fast time?
- jne slowdivide ; no. yawn...
-
- .386 ; 386-specific code starts here
-
- mov edx,x ; load X into EDX (shifts to EDX:EAX)
- mov ebx,y ; load Y into EBX
-
- mov sign,0 ; clear out the sign flag
- cmp edx,0 ; is X negative?
- jge short divides1 ; nope
- not sign ; yup. flip signs
- neg edx ; ...
- divides1:
- cmp ebx,0 ; is Y negative?
- jge short divides2 ; nope
- not sign ; yup. flip signs
- neg ebx ; ...
- divides2:
-
- mov eax,0 ; clear out the low-order bits
- mov cx,32 ; set up the shift
- sub cx,n ; (for large shift counts - faster)
- fastd1: cmp cx,0 ; done shifting?
- je fastd2 ; yup.
- shr edx,1 ; shift one bit
- rcr eax,1 ; ...
- loop fastd1 ; and try again
- fastd2:
- cmp edx,ebx ; umm, will the divide blow out?
- jae overd1 ; yup. better skip it.
- div ebx ; do the divide
- cmp eax,0 ; did the sign flip?
- jl overd1 ; then we overflowed
- cmp sign,0 ; is the sign reversed?
- je short divides3 ; nope
- neg eax ; flip the sign
- divides3:
- push eax ; save the 64-bit result
- pop ax ; low-order 16 bits
- pop dx ; high-order 16 bits
- jmp dividereturn ; back to common code
-
- .8086 ; 386-specific code ends here
-
- slowdivide: ; (sigh) time to do it the hard way...
-
- mov ax,word ptr x ; move X to DX:AX
- mov dx,word ptr x+2 ; ...
-
- mov sign,0 ; clear out the sign flag
- cmp dx,0 ; is X negative?
- jge divides4 ; nope
- not sign ; yup. flip signs
- not ax ; ...
- not dx ; ...
- stc ; ...
- adc ax,0 ; ...
- adc dx,0 ; ...
- divides4:
-
- mov cx,32 ; get ready to shift the bits
- sub cx,n ; (shift down rather than up)
- mov byte ptr temp+4,cl ; ...
-
- mov cx,0 ; clear out low bits of DX:AX:CX:BX
- mov bx,0 ; ...
-
- cmp byte ptr temp+4,16 ; >= 16 bits to shift?
- jl dividex0 ; nope
- mov bx,cx ; yup. Take a short-cut
- mov cx,ax ; ...
- mov ax,dx ; ...
- mov dx,0 ; ...
- sub byte ptr temp+4,16 ; ...
- dividex0:
- cmp byte ptr temp+4,8 ; >= 8 bits to shift?
- jl dividex1 ; nope
- mov bl,bh ; yup. Take a short-cut
- mov bh,cl ; ...
- mov cl,ch ; ...
- mov ch,al ; ...
- mov al,ah ; ...
- mov ah,dl ; ...
- mov dl,dh ; ...
- mov dh,0 ; ...
- sub byte ptr temp+4,8 ; ...
- dividex1:
- cmp byte ptr temp+4,0 ; are we done yet?
- je dividex2 ; yup
- shr dx,1 ; shift all 64 bits
- rcr ax,1 ; ...
- rcr cx,1 ; ...
- rcr bx,1 ; ...
- dec byte ptr temp+4 ; decrement the shift counter
- jmp short dividex1 ; and try again
- dividex2:
-
- mov di,word ptr y ; move Y to SI:DI
- mov si,word ptr y+2 ; ...
-
- cmp si,0 ; is Y negative?
- jge divides5 ; nope
- not sign ; yup. flip signs
- not di ; ...
- not si ; ...
- stc ; ...
- adc di,0 ; ...
- adc si,0 ; ...
- divides5:
-
- mov byte ptr temp+4,33 ; main loop counter
- mov temp,0 ; results in temp
- mov word ptr temp+2,0 ; ...
-
- dividel1:
- shl temp,1 ; shift the result up 1
- rcl word ptr temp+2,1 ; ...
- cmp dx,si ; is DX:AX >= Y?
- jb dividel3 ; nope
- ja dividel2 ; yup
- cmp ax,di ; maybe
- jb dividel3 ; nope
- dividel2:
- cmp byte ptr temp+4,32 ; overflow city?
- jge overd1 ; yup.
- sub ax,di ; subtract Y
- sbb dx,si ; ...
- inc temp ; add 1 to the result
- adc word ptr temp+2,0 ; ...
- dividel3:
- shl bx,1 ; shift all 64 bits
- rcl cx,1 ; ...
- rcl ax,1 ; ...
- rcl dx,1 ; ...
- dec byte ptr temp+4 ; time to quit?
- jnz dividel1 ; nope. try again.
-
- mov ax,temp ; copy the result to DX:AX
- mov dx,word ptr temp+2 ; ...
- cmp sign,0 ; should we negate the result?
- je divides6 ; nope.
- not ax ; yup. flip signs.
- not dx ; ...
- mov bx,0 ; ...
- stc ; ...
- adc ax,0 ; ...
- adc dx,0 ; ...
- divides6:
- jmp short dividereturn
-
- overd1:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
-
- dividereturn: ; that's all, folks!
- pop si
- pop di
- ret
- divide endp
-
- .MODEL medium,c
-
- .8086
-
- .DATA
-
- extrn temp_array:DWORD
-
- .CODE
-
- ; *************** Function toextra(tooffset,fromaddr, fromcount) *********
-
- toextra proc uses es di si, tooffset:word, fromaddr:word, fromcount:word
- cld ; move forward
- les di, temp_array
- add di,tooffset ; load to here
- mov si,fromaddr ; load from here
- mov cx,fromcount ; this many bytes
- rep movsb ; do it.
- tobad:
- ret ; we done.
- toextra endp
-
-
- ; *************** Function fromextra(fromoffset, toaddr, tocount) *********
-
- fromextra proc uses es di si, fromoffset:word, toaddr:word, tocount:word
- push ds ; save DS for a tad
- pop es ; restore it to ES
- cld ; move forward
- mov di,toaddr ; load to here
- mov cx,tocount ; this many bytes
- lds si, temp_array
- add si,fromoffset ; ..
- rep movsb ; do it.
- frombad:
- push es ; save ES again.
- pop ds ; restore DS
- ret ; we done.
- fromextra endp
-
-
- ; *************** Function cmpextra(cmpoffset,cmpaddr, cmpcount) *********
-
- cmpextra proc uses es di si, cmpoffset:word, cmpaddr:word, cmpcount:word
- cld ; move forward
- les di, temp_array
- add di,cmpoffset ; load to here
- mov si,cmpaddr ; load from here
- mov cx,cmpcount ; this many bytes
- rep cmpsb ; do it.
- jnz cmpbad ; failed.
- mov ax,0 ; 0 == true
- jmp cmpend
- cmpbad:
- mov ax,1 ; 1 == false
- cmpend:
- ret ; we done.
- cmpextra endp
-
- end
-