TIP: Click on subject to list as thread! ANSI
echo: 80xxx
to: DARRYL GREGORASH
from: SERGUEI SHTYLIOV
date: 1997-12-18 10:39:00
subject: XM386.ASM

Hail!
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
;**************************************************************************
;*      * * * 386 PROTECT info * * *
;**************************************************************************
;*      * 386 Descriptor template
DESC386 STRUC
limDesc386      dw      0               ; limit bits (0..15)
LO_apDesc386    dw      0               ; base bits (0..15)
MID_apDesc386   db      0               ; base bits (16..23)
accessDesc386   db      0               ; accessDesc386 byte
granDesc386     db      0               ; granularity byte
HI_apDesc386    db      0               ; base bits (24..31)
DESC386 ENDS
GDT386  STRUC
limitGdt        dw      ?
LO_apBaseGdt    dw      ?
HI_apBaseGdt    dw      ?
GDT386  ENDS
Zero segment use32 at 0
        org     13*4
Int13Vector     label   dword
Zero    ends
;MEM3_Code segment       use16 para public 'CODE'
;MEM3_Code ends
;codeg   group   code, MEM3_Code
;MEM3_Code segment
        assume  cs:code, ds:code, es:nothing
MEM3_Start      label   byte    ; Start of relocatable code
;MEM3_Data       label   byte    ; Start of our data
MEM3_Offset     =       offset code:MEM3_Data-offset code:MEM3_Start
OurGDT  equ     byte ptr ($+MEM3_Offset)                ; Simple GDT
                DESC386 
descCS  equ     byte ptr ($+MEM3_Offset)
                DESC386            ; Conforming CS
descRealBig     equ     byte ptr ($+MEM3_Offset)
                DESC386         ; Page Granularity
                                                        ; 4Gb Limit
GDTLen  EQU ($+MEM3_Offset-OurGDT)
GDTPtr  equ     qword ptr ($+MEM3_Offset)
                GDT386 
OldInt13        equ     dword ptr ($+MEM3_Offset)
                dd      0                       ; Old contents of int 13 
vector
GDTMoveBlock    equ byte ptr ($+MEM3_Offset)
                                                ; 386 Template OK for Move 
Block
                DESC386                       ; Nul Descriptor
                DESC386                       ; GDT Descriptor
descSource      equ byte ptr ($+MEM3_Offset)
                DESC386     ; Source Segment Descriptor
descDest        equ byte ptr ($+MEM3_Offset)
                DESC386     ; Destination Segment 
Descriptor
                DESC386                       ; BIOS use
                DESC386                       ; BIOS use
;*****************************************************************************
* *
;
; MoveExtended386
;       XMM Move Extended Memory Block for the 80386
;
; Entry:
;       ES:BX   Points to structure containing:
;               bCount          dd      ?       ; Length of block to move
;               SourceHandle    dw      ?       ; Handle for souce
;               SourceOffset    dd      ?       ; Offset into source
;               DestHandle      dw      ?       ; Handle for destination
;               DestOffset      dd      ?       ; Offset into destination
;
; Return:
;       AX = 1  Success
;       AX = 0  Failure
;               Error code in BL
;
; Registers Destroyed:
;       Flags
;
;-----------------------------------------------------------------------------
- -
MoveExtended386 proc    near
        sti                                     ; Be nice
        push    bp                              ; Set up stack frame so we
        mov     bp, sp                          ; can have local variables
        sub     sp, 18
Count   = -4                                    ; Local DWORD for byte count
Return  = -6                                    ; Local WORD for return code
SrcHandle = -8
DstHandle = -10
SrcLinear = -14
DstLinear = -18
        push    eax                             ; Save upper word of 
egisters
        push    ecx
        push    esi
        push    edi
        push    bx
        xor     ax, ax
        mov     [bp.Return], ax                 ; Assume success
        mov     [bp.SrcHandle], ax
        mov     [bp.DstHandle], ax
        mov     ecx, es:[si.bCount]
        mov     [bp.Count], ecx
        shr     dword ptr [bp.Count], 1         ; No odd byte counts
        jc      MEM3_InvCount
        jz      MEM3_Exit                       ; Exit immediately if zero
        lea     bx, [si.SourceHandle]           ; Normalize Source
        call    GetLinear386                    ; Linear address in edi
        jc      MEM3_SrcError                   ; Have Dest Error Code
        xchg    esi, edi                        ; Save source address in ESI
        mov     [bp.SrcHandle], bx              ; Save Handle for Unlock
        lea     bx, [di.DestHandle]
        call    GetLinear386                    ; Normalize Destination
        jc      MEM3_Error
        mov     [bp.DstHandle], bx              ; Save Handle for Unlock
        smsw    ax
        shr     ax, 1                           ; Protected mode?
        jc      MEM3_MoveBlock                  ;   if so, use int 15h
                                                ; Must preserve DS
        call    word ptr ControlJumpTable[5*2]  ; Call LocalEnableA20()
        cmp     ax, 1
        jne     MEM3_Error
        xor     cx, cx
        mov     es, cx
assume  es:Zero
        mov     ax, cs
        shl     eax, 16
        mov     ax, offset code:Int13Handler+MEM3_Offset
        cli
        push    [OldInt13]                      ; For reentrancy
        xchg    eax, [Int13Vector]              ; Install our int 13 handler
        mov     [OldInt13], eax
        sti
        push    ds
        mov     ds, cx
assume  ds:Zero
        mov     ecx, [bp.Count]
        shr     ecx, 1                          ; Now DWORD count
                                                ; Odd word count in carry
                ; Now we have:
                ;       ESI = 32 bit Source Linear Address
                ;       EDI = 32 bit Destination Linear Address
                ;       DS = ES = 0
                ; If the limit of DS or ES is still the Real Mode
                ; default of 64k and ESI or EDI is greater than 64k,
                ; these instructions will fault with an int 13.
                ; In this case, our int 13 handler will set up
                ; the descriptors to have 4Gb limits (real big mode)
                ; and will iret to the faulting instruction.
                ; The following persuades masm to output
                ; both a 66h and 67h prefix
Fault0:
        rep movs dword ptr [esi], dword ptr [edi]       ; DWORDS first
                        ; THE NEXT INSTRUCTION MUST HAVE ADDRESS SIZE 
VERRIDE
        db      67h             ; CHIP BUG - DO NOT REMOVE
        nop                     ; CHIP BUG - DO NOT REMOVE
        rcl     ecx, 1
Fault1:
        rep movs word ptr [esi], word ptr [edi]         ; Now the odd word
                        ; THE NEXT INSTRUCTION MUST HAVE ADDRESS SIZE 
VERRIDE
        db      67h             ; CHIP BUG - DO NOT REMOVE
        nop                     ; CHIP BUG - DO NOT REMOVE
        pop     ds
assume  ds:code
        pop     eax                             ; saved [OldInt13]
        cli                                     ; NECESSARY
        xchg    eax, [OldInt13] ; OldInt13 potentially INVALID
        mov     [Int13Vector], eax              ; Deinstall our handler
        sti
        call    word ptr ControlJumpTable[6*2]  ; Call LocalDisableA20()
        cmp     ax, 1
        jne     short MEM3_Error
MEM3_Exit:
        mov     bx, [bp.SrcHandle]              ; Unlock Handles if necessary
        or      bx, bx
        jz      short MEM3_NoSrcHandle
        dec     [bx.cLock]                      ; Unlock Source
MEM3_NoSrcHandle:
        mov     bx, [bp.DstHandle]
        or      bx, bx
        jz      short MEM3_NoDstHandle
        dec     [bx.cLock]                      ; Unlock Destination
MEM3_NoDstHandle:
        pop     bx                              ; Restore original registers
        pop     edi
        pop     esi
        pop     ecx
        pop     eax
        mov     ax, 1
        cmp     word ptr [bp.Return], 0
        je      short MEM3_Success
        dec     ax                              ; AX = 0 for error
        mov     bl, byte ptr [bp.Return]
MEM3_Success:
        mov     sp, bp                          ; Unwind stack
        pop     bp
        ret
MEM3_InvCount:
        mov     bl, ERR_LENINVALID
        jmp     short MEM3_Error
MEM3_SrcError:
        cmp     bl, ERR_LENINVALID              ; Invalid count
        je      short MEM3_Error                ;   yes, no fiddle
        sub     bl, 2                           ; Convert to Source error 
ode
MEM3_Error:
        mov     [bp.Return], bl
        jmp     short MEM3_Exit
;*****************************************************************************
* *
;
; GetLinear386
;       Convert Handle and Offset (or 0 and SEG:OFFSET) into Linear address
;       Locks Handle if necessary
;       Nested with MoveExtended386 to access local variables
;
; Entry:
;       ES:BX   Points to structure containing:
;               Handle  dw
;               Offset  dd
;       ECX     Count of bytes to move
;
; Return:
;       BX      Handle of block (0 if conventional)
;       EDI     Linear address
;       CARRY   => Error
;
; Registers Destroyed:
;       EAX
;
;-----------------------------------------------------------------------------
- -
GetLinear386    proc    near
        cli                                     ; NO INTERRUPTS
        mov     edi, dword ptr es:[bx+2]        ; Offset from start of handle
        mov     bx, word ptr es:[bx]            ; Handle in bx
        or      bx, bx
        jz      short GL3_Conventional
        cmp     [bx.Flags], USEDFLAG            ; Valid Handle?
        jne     short GL3_InvHandle
        movzx   eax, [bx.Len]                   ; Length of Block
        shl     eax, 10                         ; now in bytes
        sub     eax, edi                        ; EAX = max possible count
        jb      short GL3_InvOffset             ; Base past end of block
        cmp     eax, ecx
        jb      short GL3_InvCount              ; Count too big
        inc     [bx.cLock]                      ; Lock Handle
        movzx   eax, [bx.Base]
        shl     eax, 10                         ; Base byte address
        add     edi, eax                        ; Linear address
GL3_OKExit:
        clc
        sti
        ret
GL3_Conventional:
        movzx   eax, di                         ; Offset in EAX
        shr     edi, 16
        shl     edi, 4                          ; Segment*16 in EDI
        add     edi, eax                        ; Linear address in EDI
        mov     eax, edi
        add     eax, ecx
        cmp     eax, 10FFF0h                    ; Max addressable inc. HMA
        jbe     short GL3_OKExit
GL3_InvCount:
        mov     bl, ERR_LENINVALID
        jmp     short GL3_Error
GL3_InvHandle:
        mov     bl, ERR_DHINVALID               ; Dest handle invalid
        jmp     short GL3_Error
GL3_InvOffset:
        mov     bl, ERR_DOINVALID               ; Dest Offset invalid
GL3_Error:
        stc
        sti
        ret
GetLinear386    endp
;*****************************************************************************
* *
;
; Int13Handler
;       Handler for int 13 during our rep moves
;       If it is a real interrupt, jump to the old handler
;       If it is a fault, set Real Big Mode and return
;
; Entry:
;
; Return:
;
; Registers Destroyed:
;       BX, DS, ES if fault from one of our instructions, otherwise
;       NONE
;
;-----------------------------------------------------------------------------
- -
Int13Handler    proc    far
assume  cs:code, ds:nothing, es:nothing
        push    bp
        mov     bp, sp                  ; Base to look at faulting address
        push    ax
        mov     al, 0Bh                 ; Party on PIC to see if interrupt
        out     20h, al
        in      al, 20h                 ; ISR
        test    al, 20h                 ; IRQ5, int 13
        jnz     short NotOurInt13
        mov     ax, cs
        cmp     [bp+4], ax              ; Fault from our cs?
        jne     short NotOurInt13       ;   no, SOMETHING IS FUNNY!
        cmp     word ptr [bp+2], offset code:Fault0+MEM3_Offset
        je      short LoadDescriptorCache
        cmp     word ptr [bp+2], offset code:Fault1+MEM3_Offset
        jne     short NotOurInt13       ; Not one of our instructions ????
LoadDescriptorCache:
        mov     bx, descRealBig - OurGDT        ; Special 4Gb selector
        lgdt    qword ptr cs:[GDTPtr]
        mov     eax, cr0
        or      al,1
        mov     cr0, eax                        ; Go into Protected Mode
                                                ; NOTE: NMIs will kill us!!!
        db      0eah                            ; jmp far flush_prot
        dw      offset code:flush_prot+MEM3_Offset     ; Clears the prefetch
        dw      descCS - OurGDT
flush_prot:
        mov     es, bx                          ; Set up the segments we want
        mov     ds, bx
        and     al, 0FEh
        mov     cr0, eax                        ; Return to Real Mode
        db      0EAH                    ; jmp far flush_real
        dw      offset code:flush_real+MEM3_Offset
patch3  equ word ptr ($+MEM3_Offset)
        dw      0
flush_real:
        xor     ax, ax
        mov     ds, ax
        mov     es, ax
        pop     ax
        pop     bp
        iret                                    ; Back to faulting 
struction
NotOurInt13:
        pop     ax
        pop     bp
        jmp     cs:[OldInt13]
Int13Handler    endp
;*****************************************************************************
* *
;
; MEM3_MoveBlock
;       Set up GDT and call int 15h Move Block
;       Nested within MoveExtended386
;       See 80286 programmer's reference manual for GDT entry format
;       See Int 15h documentation for Move Block function
;
; Entry:
;       [BP.Count]      Word count for move
;       ESI             Linear address of the source
;       EDI             Linear address of the destination
;
;       Interrupts are ON
;
; Return:
;       CARRY   => Error
;               Error code in BL
;
; Registers Destroyed:
;       Flags, EAX, ECX, ESI, EDI, ES
;
;-----------------------------------------------------------------------------
- -
MEM3_MoveBlock:
assume  ds:code
        mov     [bp.SrcLinear], esi
        mov     [bp.DstLinear], edi
        mov     ax, ds
        mov     es, ax
assume  es:code
DMB_loop:
        mov     ecx, 512                        ; Do max of # words left or
        cmp     ecx, [bp.Count]                 ; or max Move Block allows
        jbe     short DMB0
        mov     ecx, [bp.Count]
DMB0:
        push    ecx
        lea     si, [GDTMoveBlock]      ; Pointer to GDT for Block Move
        lea     di, [descSource.LO_apDesc386]   ; Source Descriptor
        mov     eax, dword ptr [bp.SrcLinear]
        CLI                                     ; No interrupts until int 15h
                                                ; Allows reentrancy
        stosw
        shr     eax, 16
        stosb                                   ; Source Descriptor done
        lea     di, [descDest.LO_apDesc386]     ; Destination Descriptor
        mov     eax, dword ptr [bp.DstLinear]
        stosw
        shr     eax, 16
        stosb                                   ; Destination Descriptor done
        clc                             ; MUST DO THIS, int 15h doesn't 
other
        mov     ah, 87h                 ; Block Move - Assumes protect
        int     15h                     ; mode code will allow interrupts
        STI
        pop     ecx
        jc      short DMB_Error
        sub     [bp.Count], ecx
        jz      MEM3_Exit                       ; All done
        shl     ecx, 1                          ; Back to byte count
        add     [bp.SrcLinear], ecx             ; Update source for next 
hunk
        add     [bp.DstLinear], ecx             ; Update destination
        jmp     short DMB_loop
DMB_Error:
        xor     bh, bh
        mov     bl, al
        mov     bl, cs:[Int15Err][bx]           ; Pick up correct error code
        jmp     MEM3_Error
Int15Err        equ     byte ptr ($+MEM3_Offset)
                db      0, ERR_PARITY, ERR_LENINVALID, ERR_A20
MoveExtended386 endp
MEM3_End        label   byte            ; End of relocatable code
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
Farewell!
--- GoldED 2.50+
---------------
* Origin: Drunken Boat (FidoNet 2:5020/157.59)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.