Category : Pascal Source Code
Archive   : BMULKY.ZIP
Filename : BTRIEVE.ASM
;
; 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
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
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/