Category : C Source Code
Archive   : WINSRC17.ZIP
Filename : WGENERAL.ASM

 
Output of file : WGENERAL.ASM contained in archive : WINSRC17.ZIP
; 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


  3 Responses to “Category : C Source Code
Archive   : WINSRC17.ZIP
Filename : WGENERAL.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/