home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
WINFRSRC.ZIP
/
WGENERAL.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-12-17
|
13KB
|
509 lines
; 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
.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
.CODE
; =======================================================
;
; 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.
.MODEL medium,c
.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
.FARDATA
.CODE
extrn temp_array:far
; *************** 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