Category : C Source Code
Archive   : WININT86.ZIP
Filename : INT86Y.ASM
;** int86y.asm
;*
;* DESCRIPTION:
;* This is a replacement for the silly int86x() C runtime function
;* that does not accept FAR pointers. It works identically with
;* the exception that it takes far pointers and will work just
;* dandy in a .DLL.
;*
;* Two rules must be followed when using this code:
;*
;* 1. The CODE segment containing this code MUST
;* be FIXED!!! This is so our alias selector
;* will always be valid.
;*
;* 2. When your program exits (or .DLL), you need
;* to call zyzInt86yFreeSelector() to free up
;* the selector we used. It will NOT be freed
;* automatically.
;*
;* Also, this code is written for >= 286... Actually, the
;* only instructions that will not work on < 286 are the
;* pusha/popa. This could easily be changed if necessary.
;*
;* HISTORY:
;* 2/ 6/91 cjp wrote it
;*
;** cjp *
.286p ; don't be completely ridiculous
;; defines for cmacros.inc
?PLM = 1 ; support Pascal calling convention
?WIN = 1 ; Windows support, of course
.xlist
include cmacros.inc
.list
externFP
externFP
externFP
;; short-cuts
jmps EQU
bptr EQU
wptr EQU
dwptr EQU
;; offsets for REGS and SREGS structures
WORDREGS STRUC
regAX dw ?
regBX dw ?
regCX dw ?
regDX dw ?
regSI dw ?
regDI dw ?
regFL dw ?
WORDREGS ENDS
SREGS STRUC
selES dw ?
selCS dw ?
selSS dw ?
selDS dw ?
SREGS ENDS
sBegin DATA
staticW wReturn, 0 ; our return value
;; the following two locations MUST be contiguous
staticW wDataOffset, 0 ; our offset to ShapeShifter byte
staticW wDataSelector, 0 ; a place to store modifiable sel.
sEnd DATA
sBegin CODE
assumes cs, code
assumes ds, data
;** WORD FAR PASCAL zyzInt86y( int, REGS FAR *, REGS FAR *, SREGS FAR * )
;*
;* DESCRIPTION:
;* This function does exactly what 'int86x' does--only it takes
;* FAR pointers and will work just dandy in a .DLL!
;*
;* *****************************************************
;* *** CS and SS are NOT used in making the INT call ***
;* *** they ARE returned; for whatever good that is! ***
;* *****************************************************
;*
;* ARGUMENTS:
;* int wIntNum : Interrupt number.
;*
;* REGS FAR *lpInRegs : Register values on call.
;*
;* REGS FAR *lpOutRegs : Register values on return.
;*
;* SREGS FAR *lpSegRegs : Segment-register values on call
;* and return.
;*
;* RETURN (WORD):
;* The return value is the AX register as set by the software
;* interrupt wIntNum. If it can not AllocSelector on the *first*
;* invokation, then 01h is return; normally 'function not supported.'
;*
;* If 01h can be a valid return from the interrupt, have your
;* application use a different interrupt that will get this thing
;* kick-started before calling other interrupts. Get DOS Version
;* Number (INT 21h, AX = 3000h) would work.
;*
;* NOTES:
;* THIS CODE MUST BE FIXED! Alias selectors are not updated when
;* code and data move--this would kill us if our alias becomes
;* invalid!
;*
;** cjp *
cProc zyzInt86y, < PUBLIC, FAR, PASCAL >, < si, ds >
ParmW wIntNum
ParmD lpInRegs
ParmD lpOutRegs
ParmD lpSegRegs
cBegin
pusha ; save all of the regs we trash
push es
test wDataSelector, 0FFFFh ; have we created one yet?
jnz zyzInt86yDoIt ; yes! skip selector creation
;; This is our first invocation. We need to get another
;; selector to our 'dynamic interrupt caller' using AllocSelector
;; and then convert its attributes to be that of a data
;; selector so we can write the dreaded SELF MODIFYING CODE!
;; This attribute change should be done with CreateSelector(),
;; but it doesn't exist so we will use PrestoChangoSelector().
cCall AllocSelector, < cs > ; dup CS
test ax, ax ; did we get one?
jnz zyzAllocGood ; yes! continue...
mov wReturn, 01h ; I guess return 'unsupported func'
jmps zyzInt86yExit ; and get out
zyzAllocGood:
mov wDataSelector, ax ; save it and change to data rights
mov ax, offset zyzInt86yShapeShifter
mov wDataOffset, ax
cCall PrestoChangoSelector, < cs, wDataSelector >
zyzInt86yDoIt:
mov ax, wIntNum ; get int number
lds si, dwptr wDataOffset ; point to ShapeShifter
mov bptr [si + 1], al ; abracadabra!
lds si, lpInRegs ; ds:si -> lpInRegs
mov di, wptr [si + regDI] ; put DI in reg for call
mov dx, wptr [si + regDX] ; put DX in reg for call
mov cx, wptr [si + regCX] ; put CX in reg for call
mov bx, wptr [si + regBX] ; put BX in reg for call
mov ax, wptr [si + regSI] ; put SI on stack
push ax
mov ax, wptr [si + regAX] ; put AX on stack
push ax
lds si, lpSegRegs ; ds:si -> lpSegRegs
mov ax, wptr [si + selES] ; get ES
mov es, ax
assumes es, nothing
mov ax, wptr [si + selDS] ; get DS
mov ds, ax
assumes ds, nothing
pop ax ; prep these for call
pop si
zyzInt86yShapeShifter:
int 21h ; for padding only; dynamic!
push cs ; save cs first
push ds ; save ds next
push ax ; save ax
pushf ; save the flags
push si ; and si
lds si, lpOutRegs ; ds:si -> lpOutRegs
mov wptr [si + regDI], di ; save DI
mov wptr [si + regDX], dx ; save DX
mov wptr [si + regCX], cx ; save CX
mov wptr [si + regBX], bx ; save BX
pop ax
mov wptr [si + regSI], ax ; save SI
pop ax
mov wptr [si + regFL], ax ; save flags
pop ax
mov bx, ax ; save a copy
mov wptr [si + regAX], ax ; save AX
lds si, lpSegRegs ; ds:si -> lpSegRegs
mov wptr [si + selES], es ; save ES
pop ax ; grab DS
mov wptr [si + selDS], ax ; save DS
pop ax ; grab CS
mov wptr [si + selCS], ax ; save CS (why?)
mov ax, ss
mov wptr [si + selSS], ax ; save SS (why?)
mov ax, _DATA ; get our ds
mov ds, ax
assumes ds, data
mov wReturn, bx ; save our return value
zyzInt86yExit:
pop es ; restore all trashed regs
popa
mov ax, wReturn ; return AX from interrupt
cEnd zyzInt86y
;** WORD FAR PASCAL zyzInt86yFreeSelector( void )
;*
;* DESCRIPTION:
;* Used to free the selector that was allocated by zyzInt86y().
;* Should be ok to call at any time and SHOULD be called before
;* your program/.DLL exits.
;*
;* ARGUMENTS:
;* None.
;*
;* RETURN (WORD):
;* The return value is zero if successful. It is the selector
;* that we tried to free (non-zero) if failed.
;*
;* NOTES:
;* This code also zeros the wDataSelector for zyzInt86y() so
;* that it will know the selector is no longer valid.
;*
;** cjp *
cProc zyzInt86yFreeSelector, < PUBLIC, FAR, PASCAL >
cBegin
mov ax, wDataSelector ; verify we have a selector
test ax, ax
jz zyzInt86yFreeSelectorExit
cCall FreeSelector, < ax >
mov wDataSelector, ax ; hopefully zero selector
zyzInt86yFreeSelectorExit:
cEnd zyzInt86yFreeSelector
sEnd CODE
end
;** EOF: int86y.asm **
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/