home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
memory
/
himem
/
src
/
xm286.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-11
|
8KB
|
312 lines
;*******************************************************************************
;
; MoveExtended286
; XMM Move Extended Memory Block for the 80286
; Use Int 15h, Block Move
;
; Entry:
; ES:BX Points to a MoveExtendedStruc
;
; Return:
; AX = 1 Success
; AX = 0 Failure
; Error Code in BL
;
; Registers Destroyed:
; Flags
;
; WARNING
; =======
;
; This routine enables interrupts and can be re-entered
;
; Notes:
; The case of copying from conventional to conventional memory
; is not treated specially in this example.
;
; History:
; Wed Jul 13 - AWG - Original version
;-------------------------------------------------------------------------------
ifndef XM286INCLUDED
public MoveExtMemory
endif
MoveExtMemory proc near
sti ; Be nice
push bp ; Set up stack frame so we
mov bp, sp ; can have local variables
sub sp, 18+(6*8) ; Space for local variables
Count = -4 ; Local DWORD for byte count
MEReturn = -6 ; Local WORD for return code
SrcHandle = -8
DstHandle = -10
SrcLinear = -14
DstLinear = -18
GDT = -18-(6*8) ; Space for 6 GDT entries
pusha
push ds
push es
xor ax, ax
mov [bp.MEReturn], ax ; Assume success
mov [bp.SrcHandle], ax
mov [bp.DstHandle], ax
mov ax, word ptr es:[si.bCount] ; Pick up length specified
mov word ptr [bp.Count], ax
mov cx, word ptr es:[si.bCount+2]
mov word ptr [bp.Count+2], cx
or cx, ax
jcxz short MEM2_Exit ; Exit immediately if zero
lea bx, [si.SourceHandle] ; Normalize Source
call GetLinear286 ; Linear address in DX:AX
jc short MEM2_SrcError ; Have Dest Error Code
mov word ptr [bp.SrcLinear], ax ; Save Linear address
mov word ptr [bp.SrcLinear+2], dx
mov [bp.SrcHandle], bx ; Save Handle for Unlock
lea bx, [si.DestHandle] ; Normalize Destination
call GetLinear286
jc short MEM2_Error
mov word ptr [bp.DstLinear], ax ; Save Linear address
mov word ptr [bp.DstLinear+2], dx
mov [bp.DstHandle], bx ; Save Handle for Unlock
shr word ptr [bp.Count+2], 1 ; Make word count
rcr word ptr [bp.Count], 1
jc short MEM2_InvCount ; Odd count not allowed
;***********************************************;
; ;
; The XMS Spec states that a reasonable number ;
; of interrupt windows are guaranteed. This ;
; loop should be tuned to provide such. ;
; ;
;-----------------------------------------------;
MEM2_MoveLoop:
mov cx, 512 ; Must be less than 8000h
cmp word ptr [bp.Count+2], 0 ; Lots to do?
ja short MEM2_MaxSize
cmp word ptr [bp.Count], cx
jae short MEM2_MaxSize
mov cx, word ptr [bp.Count] ; Just what is left
jcxz short MEM2_Exit
MEM2_MaxSize:
push cx
call DoMoveBlock
pop cx
jc short MEM2_Error
sub word ptr [bp.Count], cx ; Subtract what we just did
sbb word ptr [bp.Count+2], 0
xor dx, dx ; Get byte count in DX:CX
shl cx, 1
rcl dx, 1
add word ptr [bp.SrcLinear], cx
adc word ptr [bp.SrcLinear+2], dx
add word ptr [bp.DstLinear], cx
adc word ptr [bp.DstLinear+2], dx
jmp short MEM2_MoveLoop
MEM2_Exit:
pop es
pop ds
mov bx, [bp.SrcHandle] ; Unlock Handles if necessary
or bx, bx
jz short NoSrcHandle
dec [bx.cLock] ; Unlock Source
NoSrcHandle:
mov bx, [bp.DstHandle]
or bx, bx
jz short NoDstHandle
dec [bx.cLock] ; Unlock Destination
NoDstHandle:
popa ; Restore original registers
mov ax, 1
cmp word ptr [bp.MEReturn], 0
jz short MEM2_Success
dec ax
mov bl, byte ptr [bp.MEReturn]
MEM2_Success:
mov sp, bp ; Unwind stack
pop bp
ret
MEM2_SrcError:
cmp bl, ERR_LENINVALID ; Invalid count
je short MEM2_Error ; yes, no fiddle
sub bl, 2 ; Convert to Source error code
jmp short MEM2_Error
MEM2_InvCount:
mov bl, ERR_LENINVALID
MEM2_Error:
mov byte ptr [bp.MEReturn], bl ; Pass error code through
jmp short MEM2_Exit
;*******************************************************************************
;
; GetLinear286
; Convert Handle and Offset (or 0 and SEG:OFFSET) into Linear address
; Locks Handle if necessary
; Nested with MoveExtended286 to access local variables
;
; Entry:
; ES:BX Points to structure containing:
; Handle dw
; Offset dd
; [BP.Count] Count of bytes to move
;
; Return:
; BX Handle of block (0 if conventional)
; AX:DX Linear address
; CARRY => Error
; Error code in BL
;
; Registers Destroyed:
; Flags, CX
;
;-------------------------------------------------------------------------------
GetLinear286 proc near
push si
push di
cli ; NO INTERRUPTS
mov si, word ptr es:[bx+2] ; Offset from start of handle
mov di, word ptr es:[bx+4] ; in DI:SI
mov bx, word ptr es:[bx] ; Handle in bx
or bx, bx
jz short GL2_Conventional
test [bx.Flags], USEDFLAG ; Valid Handle?
jz short GL2_InvHandle
mov ax, [bx.Len] ; Length of Block
mov cx, 1024
mul cx ; mul is faster on the 286
sub ax, si
sbb dx, di ; DX:AX = max possible count
jc short GL2_InvOffset ; Base past end of block
sub ax, word ptr [bp.Count]
sbb dx, word ptr [bp.Count+2]
jc short GL2_InvCount ; Count too big
inc [bx.cLock] ; Lock the Handle
mov ax, [bx.Base]
mul cx
add ax, si ; Linear address
adc dx, di ; in DX:AX
GL2_OKExit:
clc
GL2_Exit:
sti
pop di
pop si
ret
GL2_Conventional:
mov ax, di ; Convert SEG:OFFSET into
mov dx, 16 ; 24 bit address
mul dx
add ax, si
adc dx, 0 ; DX:AX has base address
mov di, dx
mov si, ax
add si, word ptr [bp.Count] ; Get End of Block + 1 in DI:SI
adc di, word ptr [bp.Count+2]
cmp di, 010h ; 32-bit cmp
ja short GL2_InvCount
jb short GL2_OKExit
cmp si, 0FFF0h
jbe short GL2_OKExit ; Must be < 10FFEFh + 2
GL2_InvCount:
mov bl, ERR_LENINVALID
jmp short GL2_Error
GL2_InvHandle:
mov bl, ERR_DHINVALID ; Dest handle invalid
jmp short GL2_Error
GL2_InvOffset:
mov bl, ERR_DOINVALID ; Dest Offset invalid
GL2_Error:
stc
jmp short GL2_Exit
GetLinear286 endp
;*******************************************************************************
;
; DoMoveBlock
; Set up GDT and call int 15h Move Block
; Nested within MoveExtended286
; See 80286 programmer's reference manual for GDT entry format
; See Int 15h documentation for Move Block function
;
; Entry:
; CX Word count for move
; [BP.SrcLinear] Linear address of the source
; [BP.DstLinear] Linear address of the destination
; [BP.GDT] GDT for Block Move
;
; Interrupts are ON
;
; Return:
; CARRY => Error
; Error code in BL
;
; Registers Destroyed:
; Flags, AX, CX
;
;-------------------------------------------------------------------------------
DoMoveBlock proc near
push ds
mov ax, ss
mov ds, ax
mov es, ax
lea di, [bp.GDT]
mov si, di ; Parameter to Block Move
push cx
mov cx, 6*8/2 ; Words in the GDT
xor ax, ax
rep stosw ; Clean it out
lea di, [bp.GDT+2*8] ; Source Descriptor
dec ax ; Limit FFFFh
stosw
mov ax, word ptr [bp.SrcLinear]
stosw
mov al, byte ptr [bp.SrcLinear+2]
mov ah, 93h ; Access rights
stosw ; Source Descriptor done
lea di, [bp.GDT+3*8] ; Destination Descriptor
mov ax, 0FFFFh ; Limit FFFFh
stosw
mov ax, word ptr [bp.DstLinear]
stosw
mov al, byte ptr [bp.DstLinear+2]
mov ah, 93h ; Access rights
stosw ; Destination Descriptor done
pop cx
mov ah, 87h
int 15h ; Block Move
jc short DMB286_Error
DMB_Exit:
pop ds
ret
DMB286_Error:
xor bh, bh
mov bl, al
mov bl, cs:Int15Err286[bx] ; Pick up correct error code
stc
jmp short DMB_Exit
Int15Err286 db 0, ERR_PARITY, ERR_LENINVALID, ERR_A20
DoMoveBlock endp
MoveExtMemory endp