home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xmm12.zip / XMS20.ZIP / OEMSRC.ZIP / XM286.ASM < prev    next >
Assembly Source File  |  1989-02-07  |  11KB  |  472 lines

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