Category : C Source Code
Archive   : WININT86.ZIP
Filename : INT86Y.ASM

 
Output of file : INT86Y.ASM contained in archive : WININT86.ZIP
title 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 **



  3 Responses to “Category : C Source Code
Archive   : WININT86.ZIP
Filename : INT86Y.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/