home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microsft / xms20.arc / OEMSRC.ARC / XM286.ASM < prev    next >
Assembly Source File  |  1989-03-21  |  13KB  |  528 lines

  1. ;**************************************************************************
  2. ;*    * * * 286 LOADALL information * * *
  3. ;**************************************************************************
  4.  
  5. ;*    * Segment Descriptor Access Bytes
  6. DEF_ACCESS    EQU    92H
  7.  
  8. DEF_LIMIT    EQU    0FFFFH
  9.  
  10. SEGREG_DESCRIPTOR STRUC
  11. SEG_BASE_LO    DW    0
  12. SEG_BASE_HI    DB    0
  13. SEG_ACCESS    DB    DEF_ACCESS
  14. SEG_LIMIT    DW    DEF_LIMIT
  15. SEGREG_DESCRIPTOR ENDS
  16.  
  17. DTR_DESCRIPTOR STRUC
  18. DTR_BASE    DW    ?
  19.         DB    ?
  20.         DB    0
  21. DTR_LIMIT    DW    ?
  22. DTR_DESCRIPTOR ENDS
  23.  
  24. LODAL286    MACRO    
  25.     DW    050Fh
  26. ENDM
  27.  
  28. ;*******************************************************************************
  29. ;
  30. ; MoveExtended286
  31. ;    XMM Move Extended Memory Block for the 80286
  32. ;
  33. ;    Copyright (c) 1988, Microsoft Corporation
  34. ;
  35. ; Entry:
  36. ;    ES:BX    Points to a MoveExtendedStruc
  37. ;
  38. ; Return:
  39. ;    AX = 1    Success
  40. ;    AX = 0    Failure
  41. ;        Error Code in BL
  42. ;
  43. ; Registers Destroyed:
  44. ;    Flags, CX, SI, DI, ES
  45. ;
  46. ;            WARNING
  47. ;            =======
  48. ;
  49. ; This routine enables interrupts and can be re-entered
  50. ;
  51. ; Notes:
  52. ;    The case of copying from conventional to conventional memory
  53. ;    is not treated specially in this example.
  54. ;
  55. ; History:
  56. ;    Wed Jul 13 - AWG - Original version
  57. ;-------------------------------------------------------------------------------
  58. ifndef    XM286INCLUDED
  59. public    MoveExtended286
  60. endif
  61. MoveExtended286 proc    near
  62.  
  63. assume    cs:code, ds:code, es:nothing
  64.  
  65.     sti                    ; Be nice
  66.     push    bp                ; Set up stack frame so we
  67.     mov    bp, sp                ; can have local variables
  68.     sub    sp, 18                ; Space for local variables
  69. Count      = -4                    ; Local DWORD for byte count
  70. MEReturn  = -6                    ; Local WORD for return code
  71. SrcHandle = -8
  72. DstHandle = -10
  73. SrcLinear = -14
  74. DstLinear = -18
  75.     push    bx
  76.     push    dx
  77.  
  78.     xor    ax, ax
  79.     mov    [bp.MEReturn], ax            ; Assume success
  80.     mov    [bp.SrcHandle], ax
  81.     mov    [bp.DstHandle], ax
  82.     mov    ax, word ptr es:[si.bCount]    ; Pick up length specified
  83.     mov    word ptr [bp.Count], ax
  84.     mov    cx, word ptr es:[si.bCount+2]
  85.     mov    word ptr [bp.Count+2], cx
  86.     or    cx, ax
  87.     jcxz    MEM2_Exit            ; Exit immediately if zero
  88.  
  89.     lea    bx, [si.SourceHandle]        ; Normalize Source
  90.     call    GetLinear286            ; Linear address in DX:AX
  91.     jc    short MEM2_SrcError              ; Have Dest Error Code
  92.     mov    word ptr [bp.SrcLinear], ax    ; Save Linear address
  93.     mov    word ptr [bp.SrcLinear+2], dx
  94.     mov    [bp.SrcHandle], bx        ; Save Handle for Unlock
  95.  
  96.     lea    bx, [si.DestHandle]        ; Normalize Destination
  97.     call    GetLinear286
  98.     jc    short MEM2_Error
  99.     mov    word ptr [bp.DstLinear], ax    ; Save Linear address
  100.     mov    word ptr [bp.DstLinear+2], dx
  101.     mov    [bp.DstHandle], bx        ; Save Handle for Unlock
  102.  
  103.     shr    word ptr [bp.Count+2], 1    ; Make word count
  104.     rcr    word ptr [bp.Count], 1
  105.     jc    short MEM2_InvCount              ; Odd count not allowed
  106.  
  107.     call    LocalEnableA20            ; Enable A20 for LoadAll code
  108.     cmp    ax, 1
  109.     jne    short MEM2_Error
  110.  
  111.     call    DoLoadAll
  112.  
  113.     call    LocalDisableA20
  114.     cmp    ax, 1
  115.     jne    short MEM2_Error
  116.  
  117. MEM2_Exit:
  118.     mov    bx, [bp.SrcHandle]        ; Unlock Handles if necessary
  119.     or    bx, bx
  120.     jz    short NoSrcHandle
  121.     dec    [bx.cLock]            ; Unlock Source
  122. NoSrcHandle:
  123.     mov    bx, [bp.DstHandle]
  124.     or    bx, bx
  125.     jz    short NoDstHandle
  126.     dec    [bx.cLock]            ; Unlock Destination
  127. NoDstHandle:
  128.     pop    dx
  129.     pop    bx
  130.     mov    ax, 1
  131.     cmp    word ptr [bp.MEReturn], 0
  132.     jz    short MEM2_Success
  133.     dec    ax
  134.     mov    bl, byte ptr [bp.MEReturn]
  135. MEM2_Success:
  136.     mov    sp, bp                ; Unwind stack
  137.     pop    bp
  138.     ret
  139.  
  140. MEM2_SrcError:
  141.     cmp    bl, ERR_LENINVALID        ; Invalid count
  142.     je    short MEM2_Error              ;   yes, no fiddle
  143.     sub    bl, 2                ; Convert to Source error code
  144.     jmp    short MEM2_Error
  145. MEM2_InvCount:
  146.     mov    bl, ERR_LENINVALID
  147. MEM2_Error:
  148.     mov    byte ptr [bp.MEReturn], bl    ; Pass error code through
  149.     jmp    short MEM2_Exit
  150.  
  151. ;*******************************************************************************
  152. ;
  153. ; GetLinear286
  154. ;    Convert Handle and Offset (or 0 and SEG:OFFSET) into Linear address
  155. ;    Locks Handle if necessary
  156. ;    Nested with MoveExtended286 to access local variables
  157. ;
  158. ; Entry:
  159. ;    ES:BX    Points to structure containing:
  160. ;            Handle    dw
  161. ;            Offset    dd
  162. ;    [BP.Count]    Count of bytes to move
  163. ;
  164. ; Return:
  165. ;    BX    Handle of block (0 if conventional)
  166. ;    AX:DX    Linear address
  167. ;    CARRY    => Error
  168. ;        Error code in BL
  169. ;
  170. ; Registers Destroyed:
  171. ;    Flags, CX, DI
  172. ;
  173. ;-------------------------------------------------------------------------------
  174.  
  175. GetLinear286    proc    near
  176.     push    si
  177.     cli                    ; NO INTERRUPTS
  178.     mov    si, word ptr es:[bx+2]        ; Offset from start of handle
  179.     mov    di, word ptr es:[bx+4]        ; in DI:SI
  180.     mov    bx, word ptr es:[bx]        ; Handle in bx
  181.     or    bx, bx
  182.     jz    short GL2_Conventional
  183.  
  184.     test    [bx.Flags], USEDFLAG        ; Valid Handle?
  185.     jz    short GL2_InvHandle
  186.  
  187.     mov    ax, [bx.Len]            ; Length of Block
  188.     mov    cx, 1024
  189.     mul    cx                ; mul is faster on the 286
  190.     sub    ax, si
  191.     sbb    dx, di                ; DX:AX = max possible count
  192.     jc    short GL2_InvOffset              ; Base past end of block
  193.     sub    ax, word ptr [bp.Count]
  194.     sbb    dx, word ptr [bp.Count+2]
  195.     jc    short GL2_InvCount              ; Count too big
  196.  
  197.     inc    [bx.cLock]            ; Lock the Handle
  198.     mov    ax, [bx.Base]
  199.     mul    cx
  200.     add    ax, si                ; Linear address
  201.     adc    dx, di                ; in DX:AX
  202.  
  203. GL2_OKExit:
  204.     clc
  205. GL2_Exit:
  206.     sti
  207.     pop    si
  208.     ret
  209.  
  210. GL2_Conventional:
  211.     mov    ax, di                ; Convert SEG:OFFSET into
  212.     mov    dx, 16                ; 24 bit address
  213.     mul    dx
  214.     add    ax, si
  215.     adc    dx, 0                ; DX:AX has base address
  216.     mov    di, dx
  217.     mov    si, ax
  218.     add    si, word ptr [bp.Count]        ; Get End of Block + 1 in DI:SI
  219.     adc    di, word ptr [bp.Count+2]
  220.     cmp    di, 010h            ; 32-bit cmp
  221.     ja    short GL2_InvCount
  222.     jb    short GL2_OKExit
  223.     cmp    si, 0FFF0h
  224.     jbe    GL2_OKExit            ; Must be < 10FFEFh + 2
  225. GL2_InvCount:
  226.     mov    bl, ERR_LENINVALID
  227.     jmp    short GL2_Error
  228. GL2_InvHandle:
  229.     mov    bl, ERR_DHINVALID        ; Dest handle invalid
  230.     jmp    short GL2_Error
  231. GL2_InvOffset:
  232.     mov    bl, ERR_DOINVALID        ; Dest Offset invalid
  233. GL2_Error:
  234.     stc
  235.     jmp    short GL2_Exit
  236.     
  237. GetLinear286    endp
  238.  
  239. ;*******************************************************************************
  240. ;
  241. ; DoLoadAll
  242. ;    Use 286 LoadAll for copy - see warnings below
  243. ;    Nested within MoveExtended286
  244. ;
  245. ; Entry:
  246. ;    [BP.Count]    Word count for move
  247. ;    [BP.SrcLinear]    Linear address of the source
  248. ;    [BP.DstLinear]    Linear address of the destination
  249. ;
  250. ;    Interrupts are ON
  251. ;
  252. ; Return:
  253. ;    CARRY    => Error
  254. ;        Error code in BL
  255. ;
  256. ; Registers Destroyed:
  257. ;    Flags, AX, BX, CX, DX, SI, DI
  258. ;
  259. ;-------------------------------------------------------------------------------
  260.  
  261.     EVEN        ;* WORD alignment for data
  262.  
  263. ; Swap buffer for contents of 80:0
  264. cwBuffer  EQU    51
  265. rgwSwap80 DW    cwBuffer DUP (?)
  266.  
  267. ; LOADALL data buffer placed at 80:0
  268. ;
  269. LOADALL_TBL    LABEL    BYTE
  270.     DB    6 DUP(0)
  271. LDSW    DW    ?
  272.     DB    14 DUP (0)
  273. TR    DW    0
  274. LFLAGS    DW    0        ; High 4 bits 0, Int off, Direction clear
  275.                 ;   Trace clear. Rest don't care.
  276. LIP    DW    OFFSET    AFTER_LOADALL
  277. LDT    DW    0
  278. LDSS    DW    8000H
  279. LSSS    DW    80H
  280. LCSS    DW    ?
  281. LESS    DW    8000H
  282. LDI    DW    0
  283. LSI    DW    Offset rgwSwap80
  284. LBP    DW    0
  285. LSP    DW    ?
  286. LBX    DW    ?
  287. LDX    DW    ?
  288. LCX    DW    cwBuffer
  289. LAX    DW    80H
  290. ESDES    SEGREG_DESCRIPTOR <>
  291. CSDES    SEGREG_DESCRIPTOR <>
  292. SSDES    SEGREG_DESCRIPTOR <800H,0>
  293. DSDES    SEGREG_DESCRIPTOR <>
  294. GDTDES    DTR_DESCRIPTOR <>
  295. LDTDES    DTR_DESCRIPTOR <0D000H,0,0FFH,0088H>
  296. IDTDES    DTR_DESCRIPTOR <>
  297. TSSDES    DTR_DESCRIPTOR <0C000H,0,0FFH,0800H>
  298.  
  299. DescSaved    dw    -1        ; Flag for reentrancy
  300.  
  301. SaveDesc    macro    reg
  302.     push    word ptr [reg]        ; Save 3 word descriptor
  303.     push    word ptr [reg+2]    ; pointed to by reg
  304.     push    word ptr [reg+4]
  305.     endm
  306.  
  307. RestoreDesc    macro    reg
  308.     pop    word ptr [reg+4]    ; Restore 3 word descriptor
  309.     pop    word ptr [reg+2]    ; pointed to by reg
  310.     pop    word ptr [reg]
  311.     endm
  312.  
  313. NOP4    macro
  314.     sti                ; Faster than nop
  315.     sti
  316.     sti
  317.     sti
  318.     endm
  319.  
  320. DoLoadAll    proc    near
  321.  
  322. assume    cs:code, ds:code, es:nothing
  323.  
  324.     cld                    ;* just to be sure
  325.  
  326.     mov    ax, word ptr [bp.SrcLinear]    ; Create descriptors for source
  327.     mov    dl, byte ptr [bp.SrcLinear+2]    ; and destination of transfer
  328.     mov    cx, word ptr [bp.DstLinear]
  329.     mov    dh, byte ptr [bp.DstLinear+2]
  330.     xchg    [DSDES].SEG_BASE_LO,ax        ; Fill in table and pick up
  331.     xchg    [DSDES].SEG_BASE_HI,dl        ; old values
  332.     xchg    [ESDES].SEG_BASE_LO,cx
  333.     xchg    [ESDES].SEG_BASE_HI,dh
  334.  
  335.     mov    bx,Offset IDTDES
  336.     mov    si,Offset GDTDES
  337.  
  338.     inc    [DescSaved]
  339.     jz    short DLA_NoSave          ; Don't save old values first time
  340.     push    ax            ; Save these so we can be re-entrant
  341.     push    cx
  342.     push    dx
  343.     push    [LDSW]
  344.     SaveDesc    bx        ; Save IDTDES on stack
  345.     SaveDesc    si        ; Save GDTDES on stack
  346. DLA_NoSave:
  347.  
  348.     smsw    [LDSW]            ; Fill in MSW, GDT and IDT in buffer
  349.     ;* NOW The damn SXXX instructions store the desriptors in a
  350.     ;*      different order than LOADALL wants
  351.     sidt    qword ptr [bx]
  352.     call    FixDescriptor
  353.     mov    bx, si
  354.     sgdt    qword ptr [bx]
  355.     call    FixDescriptor
  356.  
  357. DLA_MoveLoop:                ; Want byte count to fit in one word
  358.     mov    cx, 7FFFh            ; Must be < 8000h
  359.     cmp    word ptr [bp.Count+2], 0    ; Lots to do?
  360.     ja    short DLA_DoMove
  361.     cmp    word ptr [bp.Count], cx
  362.     jae    short DLA_DoMove
  363.     mov    cx, word ptr [bp.Count]        ; Just what is left
  364.  
  365. DLA_DoMove:
  366.     push    ds
  367.     push    bp            ;* gets trashed later
  368.     mov    ax, 80H            ; Set up for first copy - can do before
  369.     mov    bx, cs            ; disabling interrupts
  370.     mov    dx, cwBuffer
  371.     xor    si, si
  372.     mov    es, bx
  373.     mov    di, Offset rgwSwap80    ;* ES:DI = CS:rgwSwap80 = save address
  374.  
  375.     CLI                ; Un interruptable
  376.     MOV    [LSP], sp        ;* the real stack limit
  377.     mov    [LBX], ss
  378.     mov    [LDX], cx        ;* the actual count of words to move
  379.                     ;* will be in DX
  380.     mov    ds, ax            ;* DS:SI = 80:0 = source address
  381. assume    ds:nothing
  382.     mov    cx, dx            ; cwBuffer
  383.  
  384.     rep movsw            ; Save contents of 80:0
  385. ;*    * now move info from LOADALL_TBL buffer into 80:0 
  386.     xor    di, di
  387.     mov    es, ax            ;* ES:DI = 80:0 (dest)
  388.     mov    si, Offset LOADALL_TBL
  389.     mov    ds, bx            ;* DS:SI = CS:LOADALL_TBL (src)
  390.     mov    cx, dx            ; cwBuffer
  391.     rep movsw            ; Transfer in LOADALL info
  392.     LODAL286            ;* LOADALL INSTRUCTION (set AX = 80H)
  393. ; now set up stack for moving 80:0 info back again
  394. ; LOADALL will set the following registers:
  395. ;    AX = 80H
  396. ;    BX = old SS
  397. ;    CX = cwBufer
  398. ;    DX = word count to move
  399. ;    SI = OFFSET rgwSwap80
  400. ;    DI = 0
  401. ;    BP = 0, SS = 80H  (SS:BP => loadall area to restore)
  402. ;    DS:0 = source address (DS may be outside real mode), do not rely
  403. ;        on the DS register.
  404. ;    ES:0 = destination address (ES may be outside real mode), do not
  405. ;        rely on the ES register unless reading.
  406. AFTER_LOADALL:
  407. move_loop:
  408.     lods    word ptr cs:[si]
  409.     mov    ss:[bp],ax        ;* can't override ES
  410.     inc    bp
  411.     inc    bp
  412.     loop    move_loop
  413.  
  414. ;*    * now actually move the data
  415.     mov    ss, bx             ;* restore SS
  416.     mov    cx, dx            ;* actual word count
  417.     mov    si, di            ;* source and destination 0
  418.     STI
  419. ;* * * ** End Interrupt Off Code
  420. ;* * * ** Begin Interrupt Protected Code
  421.     rep movsw            ;* Move data
  422.  
  423.     db    0EAh                ; jmp far move_stopped
  424.     dw    Offset move_stopped        ;    fixes up CS
  425. cs0    dw    0
  426. ;* * * ** End Interrupt Protected Code
  427. ;*    * if this ever gets interrupted, we will jump 16 bytes
  428. ;*    *  CS will be bogus CS+1 value
  429. ;        CX WILL INDICATE IF THE MOVE WAS COMPLETED
  430.     NOP4
  431.     NOP4
  432.     NOP4
  433.     NOP4
  434.  
  435.     db    0EAh                ; jmp far move_stopped
  436.     dw    Offset move_stopped        ;    fixes up CS
  437. cs1    dw    0
  438.  
  439. move_stopped:                    ;* resume after move stops
  440.     pop    bp
  441.     pop    ds                ; Get our DS back
  442. assume ds:code
  443.     mov    cx, si
  444.     shr    cx, 1                ; # words moved
  445.     sub    word ptr [bp.Count], cx        ; Subtract what we just did
  446.     jz    short DLA_TestDone
  447.     sbb    word ptr [bp.Count+2], 0    ; Not zero, more to do
  448. DLA_KeepGoing:
  449.     add    [DSDES].SEG_BASE_LO, si        ; Update base of segments to end
  450.     adc    [DSDES].SEG_BASE_HI, 0        ; of transfer done so far.  Our
  451.     add    [ESDES].SEG_BASE_LO, di        ; LoadAll buffer always puts 0
  452.     adc    [ESDES].SEG_BASE_HI, 0        ; in SI and DI
  453.     jmp    DLA_MoveLoop
  454.  
  455. DLA_TestDone:
  456.     sbb    word ptr [bp.Count+2], 0
  457.     jnz    short DLA_KeepGoing              ; High word not zero, more to do
  458.  
  459. DLA_done:
  460.     cmp    [DescSaved], 0        ; Did we save registers?
  461.     jz    short DLA_NoRestore
  462.  
  463.     mov    bx, offset GDTDES
  464.     RestoreDesc    bx
  465.     mov    bx, offset IDTDES
  466.     RestoreDesc    bx
  467.     pop    [LDSW]
  468.     pop    dx            ; Restore original Segment bases
  469.     pop    bx            ; in our LoadAll buffer
  470.     pop    ax
  471.     mov    [DSDES].SEG_BASE_LO, ax
  472.     mov    [DSDES].SEG_BASE_HI, dl
  473.     mov    [ESDES].SEG_BASE_LO, bx
  474.     mov    [ESDES].SEG_BASE_HI, dh
  475. DLA_NoRestore:
  476.     dec    [DescSaved]
  477.     ret
  478.  
  479. ;**    FixDescriptor - Shuffle GTD IDT descriptors
  480. ;*
  481. ;*    The segment descriptors for the IDT and GDT are stored
  482. ;*    by the SIDT instruction in a slightly different format
  483. ;*    than the LOADALL instruction wants them. This routine
  484. ;*    performs the transformation.
  485. ;*
  486. ;*    ENTRY:
  487. ;*        DS:BX points to IDT or GDT descriptor in SIDT form
  488. ;*    EXIT:
  489. ;*        DS:BX points to IDT or GDT descriptor in LOADALL form
  490. ;*    USES: AX,CX,DX
  491. ;*
  492. ;*    NOTE: The transformation is reversable, so this routine
  493. ;*        will also work to transform a descriptor in LOADALL
  494. ;*        format to one in SIDT format.
  495. ;*
  496. FixDescriptor    proc    near
  497.     mov    ax,ds:[bx+4]
  498.     mov    cx,ds:[bx+2]
  499.     mov    dx,ds:[bx]
  500.     mov    ds:[bx+4],dx
  501.     mov    ds:[bx],cx
  502.     mov    ds:[bx+2],ax
  503.     ret
  504. FixDescriptor    endp
  505.  
  506. DoLoadAll    endp
  507.  
  508. MoveExtended286    endp
  509.  
  510.  
  511. EndMoveBlock286:
  512.  
  513.  
  514. InitMoveExtended286    proc    near
  515. assume cs:code, ds:code
  516.     mov    ax, cs
  517.     mov    [cs0], ax            ; Patch far jumps to restore
  518.     mov    [cs1], ax            ; Patch far jumps to restore
  519.     inc    ax                    ;* Trick 3
  520.     mov    [LCSS], ax
  521.     dec    ax
  522.     mov    dx, 16
  523.     mul    dx    ; Believe or not, this is faster than a 32 bit SHIFT
  524.     mov    [CSDES].seg_base_lo, ax
  525.     mov    [CSDES].seg_base_hi, dl
  526.     ret
  527. InitMoveExtended286    endp
  528.