home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------------
- ;
- ; This routine interfaces between Turbo Pascal programs and Btrieve
- ; assembly routines. This is a modified version for use with
- ; Mulkey.PAS which passes the key buffer length to Btrieve. To use
- ; without this feature, remove references to KeyLen in the stack
- ; structure below, force 255 in each call to Btrieve and rewrite the
- ; parameter list to Btrv.
- ;
- ; Copyright 1988 by Mark R. Boler - All Rights Reserved
- ;
- ;-----------------------------------------------------------------------------
- ;
- ; This module is optimized primarily for the 80386 processor,
- ; secondary to that, the 80286 processor. The 8088/8086 processors
- ; would benefit from a different algorithm for loading the parameters
- ; to the Btrieve data buffer. The format used here is:
- ;
- ; push [bp + xx]
- ;
- ; This executes in about 5 clocks on the 80286 and 80386 processors
- ; and about 25 clocks on the 8086 and about 33 clocks on the 8088 with
- ; the added benefit of not having to explicitly subtract sp plus the
- ; fact that the push opcodes take less code space.
- ;
- ; The 8088/8086 processors should use:
- ;
- ; mov ax, [bp + xx]
- ; mov [bp - xx], ax
- ;
- ; This executes in about 20 clocks on the 8086 and 28 clocks on the
- ; 8088 because when loading to/from the ax register, no EA calculation
- ; is needed. The reason this was not used on the 80286/80386 is because
- ; on these procesors, this takes about 8 and 6 clocks respectively and
- ; I liked the 5 and 5 clocks of the push mem16 method better. This may
- ; make it harder to read but the Btrieve interface is called quite
- ; repetitively in database applications and this was a good place to
- ; do some major optimizing.
- ;
- ;-----------------------------------------------------------------------------
-
- TITLE BTRIEVE ; modified for Mulkey
-
- DATA SEGMENT WORD PUBLIC
-
- ASSUME DS:DATA
-
- ProcID DW ? ; process Id for BMulti
- Version DW ? ; single/multi ProcID/No ProcID
-
- DATA ENDS
-
- CODE SEGMENT WORD PUBLIC
-
- ASSUME CS:CODE
-
- PUBLIC Btrv, InitBtrv
-
- ; FUNCTION Btrv(Op: WORD; MODIFIED FOR KEY LENGTH PASSING
- ; VAR PosBlock;
- ; VAR Data;
- ; VAR DataLen: WORD;
- ; VAR KBuf;
- ; Key: BYTE;
- ; KeyLen: BYTE): WORD; EXTERNAL;
-
- StackRec STRUC ; stack structure
- ;
- ; These are the local variables passed to Btrieve as a data block
- ; ---------------------------------------------------------------------
- DBuf DD ? ; address of data buffer
- BufLen DW ? ; data buffer length
- PosInfo DD ? ; address of positioning info
- FCB DD ? ; address of FCB
- OpCode DW ? ; operation code
- KBuf DD ? ; address of key buffer
- KeyLength DB ? ; length of key buffer
- KeyNumber DB ? ; key number
- StatusAddr DD ? ; address of status word
- XFaceID DW ? ; interface id 'va' for variable
- ;
- ; This is the Status word that Btrieve uses to return the status info
- ; ---------------------------------------------------------------------
- Status DW ? ; Status word
- ;
- ; This is the return address
- ; ---------------------------------------------------------------------
- RetAddr DD ? ; procedure far return address
- ;
- ; These are the parameters passed to this function
- ; ---------------------------------------------------------------------
- KeyLen DB ? ; key buffer length (byte)
- KeyLenFill DB ? ; byte filler
- KeyNum DB ? ; key number (byte)
- KeyNumFill DB ? ; byte filler
- KeyBufOfs DW ? ; offset address of key buffer
- KeyBufSeg DW ? ; segment address of key buffer
- DataLen DD ? ; address of data length word
- DataBufOfs DW ? ; offset address of data buffer
- DataBufSeg DW ? ; segment address of data buffer
- PosBlock DD ? ; address of position block
- Function DW ? ; Btrieve function number
- StackRec ENDS
-
- StackF EQU [bp - RetAddr] ; reference to stack frame [bp]
- MinDosVer EQU 3 ; minimum DOS version for multi-user
- PosOfs EQU 38 ; positioning info offset in PosBlock
- VarID EQU 6176H ; variable data buffer ID ('va')
- BtrErr EQU 20 ; Return value when Btrieve not loaded
- MultiF EQU 0ABH ; Code for multi function Btrieve
- BtrOffset EQU 033H ; offset of vector if Btrieve loaded
- VersionL EQU BYTE PTR es:Version ; low byte of Version with es segment
- BtrInt EQU 07BH ; Interrupt vectors
- Btr2Int EQU 02FH ; " "
- ZInt EQU 07FH ; " "
-
- Btrv PROC FAR ; the Btrv function
- mov si, bp ; save bp in si
- mov bp, sp ; set up stack frame
- mov cx, Version ; get version into cx
- or cl, cl ; see if Btrieve was found during init
- jz SHORT NotLoaded ; jump if not loaded
-
- ; allocate space for the Status word
-
- sub sp, SIZE Status ; allocate the stack space
- mov bx, sp ; save the offset in bx
-
- ; store the interface ID
-
- mov ax, VarID ; get variable records interface ID
- push ax ; store it
-
- ; store the address of the status word
-
- push ss ; store the segment
- push bx ; and the offset
-
- ; store the key number and key buffer size
-
- mov al, StackF.KeyLen ; get length of key buffer
- mov ah, StackF.KeyNum ; get key number
- push ax ; and store them
-
- ; store the address of the key buffer
-
- push StackF.KeyBufSeg ; store segment of key buffer
- push StackF.KeyBufOfs ; store offset of key buffer
-
- ; store the Btrieve operation code
-
- push StackF.Function ; store the op code
-
- ; calculate and store positioning and FCB addresses
-
- les ax, StackF.PosBlock ; es:ax => pos block
- push es ; store FCB segment
- push ax ; store FCB offset
- push es ; store positioning info segment
- add ax, PosOfs ; adjust positioning info offset
- push ax ; store positioning info offset
-
- ; store data buffer length
-
- les bx, StackF.DataLen ; es:[bx] = data buffer length word
- push es:[bx] ; store the length
-
- ; store data buffer address
-
- push StackF.DataBufSeg ; store data buffer segment
- push StackF.DataBufOfs ; store data buffer offset
-
- ; set up call to Btrieve, make ds:[dx] = data block for Btrieve
-
- mov di, ds ; save ds in di for now
- mov dx, sp ; stack pointer is data block offset
- mov ax, ss ; make ds = stack segment
- mov ds, ax
-
- ; see which version to call and do it
-
- or ch, ch ; see if it is single or multi-user
- je SHORT NotMulti ; then jump around multi code if single
-
- ; make the call to multi-user btrieve
-
- MakeCall:
- mov es, di ; copy our saved ds into es for now
- mov ax, cx ; set up ax with Version word from cx
- mov bx, es:ProcID ; set Process ID for BMulti
- int Btr2Int ; call it
- or al, al ; see if it is zero
- jz SHORT DoneCall ; if so then jump ahead
- mov ax, 0200H
- int ZInt ; make the interrupt
- jmp SHORT MakeCall ; then loop
- DoneCall:
- test cl, 00000010B ; should we set the process ID
- jnz SHORT SetDBuf ; if not then jump
- mov es:ProcID, bx ; otherwise store the new process ID
- inc cx ; we have process ID
- mov VersionL, cl ; set version for next time around
- jmp SHORT SetDBuf ; then jump around single-user code
- NotLoaded:
- mov ax, BtrErr ; set error code
- jmp SHORT Done ; and return
- NotMulti:
- int BtrInt ; process request for single-user
- SetDBuf:
- mov ds, di ; get our data segment back from di
- mov bx, sp ; ss:[bx] = data block
- mov ax, ss:[bx].BufLen ; load data buffer length into ax
- les bx, StackF.DataLen ; es:[bx] = data length word
- mov es:[bx], ax ; store the data buffer length
- mov ax, StackF.Status ; set function return code
- Done:
- mov sp, bp ; de-allocate local data (pushed)
- mov bp, si ; restore bp from si
- ret 22 ; clean up and return to caller
- Btrv ENDP
-
- InitBtrv PROC NEAR
- mov ax, 3500H + BtrInt ; DOS get interrupt vector function
- int 21H ; offset comes back in bx
- xor dx, dx ; clear out dx
- cmp bx, BtrOffset ; is Btrieve resident
- jne SHORT IDone ; jump if not and set Version
- inc dx ; make dx = 1
- mov ah, 30H ; check the DOS version number
- int 21H ; call DOS
- cmp al, MinDosVer ; DOS major version number
- jb SHORT IDone ; if < DOS 3.xx then set Version
- mov al, dh ; clear out al
- mov ah, MultiF ; see if it is multi-user version
- int Btr2Int ; see what Btrieve tells us it is
- cmp al, 'M' ; is it a multi-user version
- jne SHORT IDone ; jump if it is
- mov dh, ah ; set to multi-user
- IDone:
- mov ds:Version, dx ; store dx into version
- ret ; return to caller
- InitBtrv ENDP
-
- CODE ENDS
-
- END