home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
microcrn
/
issue_49.arc
/
PS-FR386.ARC
/
MAND.A
next >
Wrap
Text File
|
1989-07-11
|
12KB
|
278 lines
; Micro Cornucopia Magazine Issue #49
; PostScriptals article code
;
; This is a pruned version of Harlan Stockman's 386 specific code originally
; run in Micro Cornucopia Issue #43. I used it for the PostScriptal article
; in Issue #49. The code that's left has not been altered - I just removed
; the stuff I didn't need and reassembled with DeSmet.
; Larry Fogg - June 28, 1989
; This file is mand.a ... DeSmet asm88 functions for fr386.c,
; a fixed-pt 386 version of Mandelbrot ...
; mandwhile.a replaces inner "while" loop of mandelbrot calculation...
;==============386-SPECIFIC FUNCTIONS===================================
; int mandwhile(long P, long Q, int nmax)
; Performs all calculations for "while" loop in L.Fogg's mandel()
; function, using fixed pt math with binary pt between bits 23 and 24...
;
; FOR: DeSmet C/asm88 small case...
;
; In REAL MODE; uses 32-bit overrides on register length and addressing to
; gain performance of 32-bit regs and instructions...
; Returns # iterations before divergence (16-bit int returned in ax).
; Note 1/3 rd of instructions are for rounding, to get small amount extra
; accuracy; if you aren't that picky, dump these instructions for 10% or more
; extra speed...
;
; REGISTERS: ebp ...ytemp at top of loop, modulus_sqrd
; at bottom of loop
; edx:eax ...multiplication and temporary storage
; edi ...P
; esi ...Q
; ebx ...x
; ecx ...y
;
; RETURNS stopping number of iterations in ax.
dseg
public counter
counter dw 0
cseg
public mandwhile_
mandwhile_:
db 66h, 55h ;push ebp
;---get P ...
db 67h, 66h, 8Bh, 7Ch, 24h, 06h ;mov edi,dword [esp+6]
;---get Q ...
db 67h, 66h, 8Bh, 74h, 24h, 0Ah ;mov esi,dword [esp+10]
;---get nmax...
db 67h, 8Bh, 44h, 24h, 0Eh ;mov ax,word [esp+14]
;---initialize counter ...
mov word counter,ax
;---zero out x and y storage ...
db 66h, 33h, 0DBh ;xor ebx,ebx
db 66h, 33h, 0C9h ;xor ecx,ecx
looper: ;---ytemp=x*y---
db 66h, 8Bh, 0C3h ;mov eax,ebx
db 66h, 0F7h, 0E9h ;imul ecx
db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H ;for rounding...
db 66h, 83h, 0D2h, 00h ;adc edx,0 ;for rounding...
db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8 ;div by 2**24...
db 66h, 8Bh, 0EAh ;mov ebp,edx
;---x=x*x - y*y + P------
db 66h, 8Bh, 0C3h ;mov eax,ebx
db 66h, 0F7h, 0EBh ;imul ebx
db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
db 66h, 83h, 0D2h, 00h ;adc edx,0
db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
db 66h, 8Bh, 0DAh ;mov ebx,edx
;---
db 66h, 8Bh, 0C1h ;mov eax,ecx
db 66h, 0F7h, 0E9h ;imul ecx
db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
db 66h, 83h, 0D2h, 00h ;adc edx,0
db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
db 66h, 2Bh, 0DAh ;sub ebx,edx
db 66h, 03h, 0DFh ;add ebx,edi ;add P...
;---y=(ytemp<<1) + Q----
db 66h, 0D1h, 0E5h ;shl ebp,1
db 66h, 03h, 0EEh ;add ebp,esi ;add Q...
db 66h, 8Bh, 0CDh ;mov ecx,ebp
;---modsqrd = x*x + y*y---
db 66h, 8Bh, 0C3h ;mov eax,ebx
db 66h, 0F7h, 0EBh ;imul ebx
db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
db 66h, 83h, 0D2h, 00h ;adc edx,0
db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
db 66h, 8Bh, 0EAh ;mov ebp,edx
;---
db 66h, 8Bh, 0C1h ;mov eax,ecx
db 66h, 0F7h, 0E9h ;imul ecx
db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
db 66h, 83h, 0D2h, 00h ;adc edx,0
db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
db 66h, 03h, 0EAh ;add ebp,edx
;---test if modsqrd > "4"---(67108864 = 4*(1 << 24))---
db 66h, 81h, 0FDh, 00h,00h,00h,04h ;cmp ebp,67108864
jae home
dec word counter
jnz looper
home: mov ax,word counter
neg ax
db 67h, 03h, 44h, 24h, 0Eh ;add ax, word [esp+14]
db 66h, 5Dh ;pop ebp
ret
; long muldiv(long A, int b, int c)
; Multiplies 32-bit "a" by 16-bit "b", then divides by
; 16-bit "c" such that abs(c) >= abs(b)...NO CHECK FOR 0 DIVISOR...
;
; NOTE how DeSmet figures stack upon entry:
; 16-bit return address at sp, "A" at sp+2, b at sp+6, c at sp+8 ...
;
; REGISTERS: eax ...initially holds "A"
; ebx ...holds b
; ecx ...holds c
; edx:eax ...product A*b (before idiv)
;
; RETURNS long result in dx:ax.
cseg
public muldiv_
muldiv_:
db 67h,66h,8bh,44h,24h,02h ;mov eax,dword ptr [esp+2]
db 67h,66h,0fh,0bfh,5ch,24h,06h ;movsx ebx,word ptr [esp+6]
db 67h,66h,0fh,0bfh,4ch,24h,08h ;movsx ecx,word ptr [esp+8]
db 66h,0f7h,0ebh ;imul ebx
db 66h,0f7h,0f9h ;idiv ecx
db 66h,0fh,0a4h,0c2h,10h ;shld edx,eax,16
ret ;short return...
;==============TEST FOR 386===============================
; int is_386()
; 2-20-88 checks for presence of 386 -- returns 0 if not found, else
; returns non-zero ...
; note short return for DeSmet asm88 small case ...
; REF: Juan E. Jimenez, Turbo Technix Jan/Feb 88, p. 55 ...
cseg
public is_386_
is_386_: pop di ;return address ...
pushf
xor ax,ax
push ax
popf
pushf
pop ax
and ax,8000h
sub ax,8000h
jz home2
;------
mov ax,7000h ;if here, either 286 or 386 ...
push ax
popf
pushf
pop ax
and ax,7000h
home2: jmp di
;==============DESMET KEYBOARD POLLING ROUTINES===========
; int scr_ci() and int scr_csts()
; These functions read the keyboard; scr_ci() waits until
; a key is typed, and returns the key; scr_csts() does not wait and returns
; 0 if no key is available. Unlike DeSmet functions ci() and csts(), these
; functions can read and translate extended keyboard codes (e.g., cursors
; and function keys). NOTE these are slightly faster than scr_ci() and
; scr_csts() given in DeSmet's optional PCIO.a file .
;
; FOR TURBO C: replace with combination of kbhit() and getch()...
dseg
; TABLES to convert (scan_code - 59) to char code...
table1: db 210 ;F1 scan= 59
db 211 ;F2 60
db 212 ;F3 61
db 213 ;F4 62
db 214 ;F5 63
db 215 ;F6 64
db 216 ;F7 65
db 217 ;F8 66
db 218 ;F9 67
db 219 ;F10 68
db 0 ;NumLock 69 ...not used
db 0 ;ScrollL 70 ...not used
db 200 ;bol_char 71
db 30 ;up_arrow 72
db 202 ;page_up 73
db 0 ;grey(-) 74 ...not used
db 29 ;left_arrow 75
db 0 ;NumPad5 76 ...not used
db 28 ;right_arrow77
db 0 ; 78 ...not used
db 201 ;eol_char 79
db 31 ;down_arrow 80
db 203 ;page_down 81
db 206 ;Insert 82
db 207 ;Delete 83
public table2
table2: db 209 ;left_word 115
db 208 ;right_word 116
db 205 ;end_of_file117
db 0 ; 118 ..not used
db 204 ;begin_file 119
cseg
public scr_ci_
scr_ci_: push bp
mov ah,0
int 16H
cmp al,0
jne not_special
mov bl,ah
xor bh,bh
cmp bx,114
ja use_table2
sub bx,59
mov al,byte table1[bx]
jmp not_special
use_table2: sub bx,115
mov al,byte table2[bx]
not_special: xor ah,ah
pop bp
ret
public scr_csts_
scr_csts_: push bp
mov ah,1
int 16H
mov ax,0
jz csts_over
call scr_ci_
csts_over: pop bp
ret
;==============LOG COLOR TRANSFORM===================================
; 2-20-88 transform(int iter, int switchpt) ... DeSmet asm88 ...
; for frac386.c ...
; ...returns the "color" then anded with (maxcolors-1)...
; converts the iterations returned by mand() to a log scaling, starting at
; the switchpt. Equiv. to C coding:
; if(iter < switchpt) color = iter;
; else for(color=i=switchpt,inc=1; i<iter; i=switchpt+(inc<<=1),color++);
; ...However, 386 is so fast we need to translate to asm to get full benefit!
cseg
public transform_
transform_: pop di ;return address...
pop cx ;iter...
pop bx ;switchpt...
sub sp,4 ;required by DeSmet for short return...
cmp cx,bx
ja do_loop
mov ax,cx
jmp di ;short return...
;------
do_loop: mov ax,bx ;init color (ax) with switchpt...
mov si,2 ;si = inc... (originally = 1)
mov dx,bx ;init i (dx) with switchpt...
;------
loopit: cmp dx,cx ;compare i (dx) to iter (cx)...
jge done
shl si,1 ;inc <<= 1...
mov dx,bx
add dx,si ;i = switchpt + inc...
inc ax
jmp loopit
;------
done: jmp di ;short return, color in ax...