home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
memory
/
himem
/
src
/
xm386.asm
< prev
Wrap
Assembly Source File
|
1988-08-09
|
12KB
|
463 lines
;**************************************************************************
;* * * * 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 <0FFFFh,0,0,09Fh,0,0> ; Conforming CS
descRealBig equ byte ptr ($+MEM3_Offset)
DESC386 <0FFFFh,0,0,093h,0cfh,0> ; Page Granularity
; 4Gb Limit
GDTLen EQU ($+MEM3_Offset-OurGDT)
GDTPtr equ qword ptr ($+MEM3_Offset)
GDT386 <GDTLen,0,0>
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 <0FFFFh,0,0,93h,0,0> ; Source Segment Descriptor
descDest equ byte ptr ($+MEM3_Offset)
DESC386 <0FFFFh,0,0,93h,0,0> ; 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 registers
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 OVERRIDE
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 OVERRIDE
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 code
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 instruction
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 bother
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 chunk
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