]> 4ch.mooo.com Git - 16.git/blob - src/lib/xmem/xmem.asm
3453e0805c77b31304b50af7424dc7addafb8296
[16.git] / src / lib / xmem / xmem.asm
1 ;-----------------------------------------------------------------------
2 ;Can't take credit for the ASM code here, found it on a local BBS.
3 ;The author has beem lost in the mists of time.
4
5 ;
6 .MODEL MEDIUM
7  
8  
9         EXTmemError     EQU     7
10         XMSmemError     EQU     8
11  
12  
13         ShortAdr        EQU     0
14         LongAdr         EQU     1
15  
16  
17 procname        MACRO  Pnam
18         PUBLIC  _&Pnam&
19 _&Pnam&  PROC    FAR
20 ENDM
21  
22 endproc         MACRO  Pnam
23  
24 _&Pnam&  ENDP
25  
26 ENDM
27  
28 pwrlolvl_TEXT   SEGMENT WORD PUBLIC 'CODE'
29  
30         ASSUME  CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT
31  
32 SUBTTL  (Local Procedure) XMS_setup - find a XMS driver.
33 PAGE+
34  
35                 EVEN
36 XMSwordByte     LABEL BYTE
37 XMSword         DW      0
38  
39 XMSmoveSTRUC    STRUC
40  
41 Length          DW      0
42 LengthX         DW      0
43 SrcHandle       DW      0
44 SrcOffset       DW      0
45 SrcOffsetX      DW      0
46 DestHandle      DW      0
47 DestOffset      DW      0
48 DestOffsetX     DW      0
49  
50 XMSmoveSTRUC    ENDS
51  
52 XMSmainGET      XMSmoveSTRUC  <>
53 XMSmainPUT      XMSmoveSTRUC  <>
54 XMSwordGET      XMSmoveSTRUC  <2,,,,,,OFFSET XMSword>
55 XMSwordPUT      XMSmoveSTRUC  <2,,,OFFSET XMSword>
56  
57 XMSfunctAdr     DW      0, 0
58  
59  
60 ; Don't try to call this from your programs
61  
62 XMS_setup               PROC NEAR
63  
64         PUSH    DS
65         PUSH    ES
66         PUSH    BX
67  
68         MOV     AX,CS                   ; Set Data segment to the code
69 segment.
70         MOV     DS,AX                   ;
71         MOV     [XMSwordGET.DestOffsetX],AX  ; Set up the move data
72 structures.
73         MOV     [XMSwordPUT.SrcOffsetX],AX   ;
74  
75         MOV     AX,4300H                ; See if a XMS Driver Exists.
76         INT     2FH                     ;
77         CMP     AL,80H                  ;
78         MOV     AX,0                    ;
79         JNE     XMS_setup01             ; Return 0 if not.
80  
81         MOV     AX,4310H                ; If so, set the driver's function
82         INT     2FH                     ;  address.
83         MOV     [XMSfunctAdr],BX        ;
84         MOV     [XMSfunctAdr+2],ES      ;
85  
86         MOV     AX,1                    ; Return 1.
87  
88   XMS_setup01:
89         POP     BX
90         POP     ES
91         POP     DS
92  
93         RET
94  
95 XMS_setup               ENDP
96  
97  
98 SUBTTL  LSHL - Shift an unsigned long left
99 PAGE+
100  
101  ;****************************************************************************
102  ;* 
103  ;* Shift an unsigned long integer left n number of bits.
104  ;*
105  ;****************************************************************************
106  
107  ;
108  ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n
109 );
110  ;
111  
112 LSHLparms STRUC
113  
114         DW      0, 0
115         DW      0
116 SHLadr   DD      ?
117 SHLn     DW      ?
118  
119 LSHLparms ENDS
120  
121 procname  LSHL
122  
123         PUSH    BP
124         MOV     BP,SP
125  
126         PUSH    BX
127         PUSH    CX
128         PUSH    DX
129  
130         PUSH    DS
131         LDS     BX,SHLadr[BP]
132         MOV     CX,SHLn[BP]
133  
134         MOV     AX,[BX]                 ; Get the long integer.
135         MOV     DX,[BX+2]               ; 
136  
137  LSHL_01:
138         SHL     AX,1                    ; Do the long shift.
139         RCL     DX,1                    ; 
140         LOOP    LSHL_01                 ; 
141  
142         MOV     [BX],AX                 ; Replace the addressed number.
143         MOV     [BX+2],DX               ; 
144  
145         POP     DS
146         POP     DX
147         POP     CX
148         POP     BX
149  
150         POP     BP
151         RET                             ; Exit
152  
153 endproc   LSHL
154  
155  
156 SUBTTL  Extended Memory - Stack template for EXTget, EXTput
157 PAGE+
158  
159 EXTgpparms STRUC
160  
161         DW      0, 0
162         DW      0
163 extgpBase    DW      ?
164 extgpblk     DW      ?
165 extgpblkAdr  DW      ?
166 extgpBytes   DW      ?
167 extgpmemAdr  DW      ?
168              DW      ?
169  
170 EXTgpparms ENDS
171  
172  
173  
174 SUBTTL  Extended Memory - XMS - Return total XMS memory.
175 PAGE+
176  
177  ; Use this function to detect wether or not XMS driver installed
178  ;
179  ; Stack frame definition for unsigned XMS_available( void );
180  ;
181  ;  The total XMS memory available (in 16k blocks) is returned.
182  ;
183 procname  XMS_available
184  
185         PUSH    BX
186         PUSH    CX
187         PUSH    DX
188  
189         CALL    XMS_setup               ; Ensure XMS memory is set.
190         TEST    AX,AX                   ;
191         JZ      XMS_available01         ; Return zero if not.
192  
193         MOV     AH,08H                  ; Set the size function code.
194         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
195         TEST    AX,AX                   ;
196         JZ      XMS_available01         ;
197  
198         MOV     AX,DX                   ; Set available Kbytes.
199         SUB     AX,64                   ; Subtract out the HMA (HIMEM.SYS
200 bug).
201         JNC     XMS_available01         ;
202         XOR     AX,AX                   ; Set zero if underflow.
203  
204   XMS_available01:
205         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
206         SHR     AX,CL                   ;
207  
208         POP     DX
209         POP     CX
210         POP     BX
211  
212         RET                             ; Exit
213  
214 endproc   XMS_available
215  
216 SUBTTL  Extended Memory - XMS - Return largest block XMS mem.
217 PAGE+
218  
219  ;
220  ; Stack frame definition for unsigned XMSblk_available( void );
221  ;
222  ;  The size of the largest block of XMS memory available,
223  ;  (in 16Kbyte blocks) is returned.
224  ;
225 procname  XMSblk_available
226  
227         PUSH    BX
228         PUSH    CX
229         PUSH    DX
230  
231         CALL    XMS_setup               ; Ensure XMS memory is set.
232         TEST    AX,AX                   ;
233         JZ      XMSblk_available01      ; Return zero if not.
234  
235         MOV     AH,08H                  ; Set the size function code.
236         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
237         TEST    AX,AX                   ;
238         JZ      XMSblk_available01      ;
239  
240         SUB     DX,64                   ; Subtract out the HMA (HIMEM.SYS
241 bug).
242         JNC     XMSblk_available0X      ;
243         XOR     DX,DX                   ; Set zero if underflow.
244  
245  XMSblk_available0X:
246         CMP     AX,DX                   ;
247         JBE     XMSblk_available01      ;
248         MOV     AX,DX                   ; Set available Kbytes.
249  
250   XMSblk_available01:
251         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
252         SHR     AX,CL                   ;
253  
254         POP     DX
255         POP     CX
256         POP     BX
257  
258         RET                             ; Exit
259  
260 endproc   XMSblk_available
261  
262 SUBTTL  Extended Memory - XMS De-allocate a memory block.
263 PAGE+
264  
265  ;
266  ; Stack frame definition for int XMS_dealloc( int Hdl );
267  ;
268  ; Zero is returned if the operation fails, non-zero if success.
269  ;
270  ; its really important to do this, only other way to recover
271  ; XMS blocks is to re-boot
272  
273 XMSdealparms STRUC
274  
275         DW      0, 0
276         DW      0
277 xmsdealHdl  DW      ?
278  
279 XMSdealparms ENDS
280  
281  
282 procname  XMS_dealloc
283  
284         PUSH    BP
285         MOV     BP,SP
286  
287         PUSH    BX
288         PUSH    DX
289  
290 ;        CALL    XMS_setup               ; Ensure XMS memory is set.
291 ;        TEST    AX,AX                   ;
292 ;        JZ      XMS_dealloc01           ; Return zero if not.
293  
294         MOV     DX,xmsdealHdl[BP]       ; Get the handle to de-allocate.
295         MOV     AH,0AH                  ;
296  
297         CALL    DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.
298  
299   XMS_dealloc01:
300         POP     DX
301         POP     BX
302  
303         POP     BP
304         RET                             ; Exit
305  
306 endproc   XMS_dealloc
307  
308 SUBTTL  Extended Memory - XMS Allocate a memory block.
309 PAGE+
310  
311  ;
312  ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );
313  ;
314  ;     rsrved and size are in 16K byte blocks.
315  ;     rsrved is mem set aside for EMS, generaly zero
316  ;
317  ;  Zero is returned if the operation fails.
318  ;  Block (XMS) handle is returned if success.
319  ;
320  ;  size - is reduced by the amount of XMS memory actually allocated.
321  ;
322  
323 XMSalparms STRUC
324  
325         DW      0, 0
326         DW      0
327 xmsalrsrvd DW      ?
328 xmsalsize  DD      ?
329  
330 XMSalparms ENDS
331  
332 procname  XMS_alloc
333  
334         PUSH    BP
335         MOV     BP,SP
336  
337         PUSH    BX
338         PUSH    CX
339         PUSH    DX
340         PUSH    DI
341         PUSH    ES
342         PUSH    DS
343  
344         MOV     AX,CS                   ; Set the data segment to the code
345         MOV     DS,AX                   ;  segment.
346  
347         MOV     CX,4                    ;
348         ADD     xmsalrsrvd[BP],CX       ; Subtract out the HMA (HIMEM.SYS
349 bug).
350         SHL     xmsalrsrvd[BP],CL       ; Convert reserved blocks to K-bytes.
351  
352         LES     DI,xmsalsize[BP]        ; Load size address.
353         XOR     AX,AX                   ;
354         MOV     BX,ES:[DI]              ; Get the requested size in blocks.
355  
356         TEST    BX,0F000H               ; Check for more than 64 Megabytes.
357         JZ      XMS_alloc01             ;
358         MOV     BX,00FFFH               ;
359  
360   XMS_alloc01:
361         MOV     CL,4                    ;
362         SHL     BX,CL                   ; Convert to K-Bytes.
363         MOV     CX,BX                   ; In CX.
364         JZ      XMS_alloc05             ; Return zero if no size requested.
365  
366 ;        CALL    XMS_setup               ; Ensure XMS memory is set.
367 ;        TEST    AX,AX                   ;
368 ;        JZ      XMS_alloc05             ; Return zero if not.
369  
370         XOR     BX,BX                   ;
371         MOV     AH,08H                  ; Set to Query Free XMS Memory.
372         CALL    DWORD PTR [XMSfunctAdr] ;
373  
374         SUB     DX,xmsalrsrvd[BP]       ; Subtract out reserved blocks.
375         JB      XMS_alloc03             ; Ensure no borrow.
376         CMP     AX,DX                   ;
377         JBE     XMS_alloc02             ;
378         MOV     AX,DX                   ;
379  
380   XMS_alloc02:
381         MOV     DX,AX                   ;
382         CMP     AX,68                   ; Ensure enough memory to allocate.
383  
384   XMS_alloc03:
385         MOV     AX,0                    ;
386         JB      XMS_alloc05             ; Exit if not.
387  
388         CMP     BL,80H                  ; Check for errors.
389         JE      XMS_alloc05             ;
390         CMP     BL,81H                  ;
391         JE      XMS_alloc05             ;
392  
393         CMP     CX,DX                   ; Check actual against requested size.
394         JBE     XMS_alloc04             ;
395         MOV     CX,DX                   ; Set if actual < requested.
396  
397   XMS_alloc04:
398         MOV     DX,CX                   ; Set requested size.
399         MOV     AH,09H                  ;
400         CALL    DWORD PTR [XMSfunctAdr] ; Allocate it.
401         DEC     AX                      ; Check for errors.
402         MOV     AX,0                    ;
403         JNZ     XMS_alloc05             ;
404  
405  
406         MOV     AX,CX                   ; Convert allocated size in KBytes
407         MOV     CL,4                    ; to allocated blocks.
408         SHR     AX,CL                   ;
409  
410         SUB     ES:[DI],AX              ; Subtract the blocks allocated.
411         MOV     AX,DX                   ; Set to return the handle.
412  
413   XMS_alloc05:
414         POP     DS
415         POP     ES
416         POP     DI
417         POP     DX
418         POP     CX
419         POP     BX
420  
421         POP     BP
422         RET                             ; Exit
423  
424 endproc  XMS_alloc
425  
426 SUBTTL  Extended Memory - XMS get, put Stack Frame definition
427 PAGE+
428  
429  
430 XMSgpparms STRUC
431  
432         DW      0, 0
433         DW      0
434 xmsgpHdl     DW      ?
435 xmsgpblk     DW      ?
436 xmsgpblkAdr  DW      ?
437 xmsgpBytes   DW      ?
438 xmsgpmemAdr  DD      ?
439  
440 XMSgpparms ENDS
441  
442 SUBTTL  Extended Memory - XMStoMem
443 PAGE+
444  
445  
446  ;
447  ; Stack frame definition for int XMStoMem( unsigned Handle,
448  ;                                          unsigned blk,
449  ;                                          unsigned blkAdr,
450  ;                                          unsigned Bytes,
451  ;                                          char     *memAdr
452  ;                                        );
453  ;
454  ;  XMSmemError is returned if the operation fails, Zero if success.
455  ;
456  
457 procname  XMStoMem
458  
459         PUSH    BP
460         MOV     BP,SP
461  
462         PUSH    BX
463         PUSH    CX
464         PUSH    DX
465         PUSH    SI
466         PUSH    DI
467         PUSH    ES
468         PUSH    DS
469  
470         MOV     AX,CS                   ; Set Data Segment to Code Segment.
471         MOV     DS,AX                   ;
472  
473         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
474         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
475         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
476         MOV     [XMSmainGET.SrcHandle],DX ; Set it in the move structures.
477         MOV     [XMSwordGET.SrcHandle],DX ;
478  
479         XOR     DX,DX                   ;
480         MOV     DI,xmsgpblk[BP]         ; Get the block number.
481         SHR     DI,1                    ; Form the 32 bit XMS address in
482         RCR     DX,1                    ;  DI:DX.
483         SHR     DI,1                    ;
484         RCR     DX,1                    ;
485         ADD     DX,xmsgpblkAdr[BP]      ;
486  
487         TEST    CX,1                    ; Check for an odd number of bytes
488         JZ      XMStoMem02              ;  to transfer.
489  
490         DEC     CX                      ; Decrement to an even number of
491 bytes.
492  
493         TEST    DX,1                    ; Check for an odd XMS address.
494         JZ      XMStoMem01              ;
495  
496                                         ; XMS address is odd.
497                                         ; -------------------
498         DEC     DX                      ;
499         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
500         MOV     [XMSwordGET.SrcOffsetX],DI  ;
501  
502         MOV     AH,0BH                  ; Set the XMS move, function code.
503         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
504  
505         PUSH    BX                      ;
506         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
507         POP     BX                      ;
508         DEC     AX                      ; Check for errors.
509         JNZ     XMStoMem03              ; Error out if error.
510  
511         MOV     AX,[XMSword]            ; Get the moved word.
512  
513         MOV     ES:[BX],AH              ; Move the odd byte to memory.
514  
515         INC     BX                      ; Reset the memory address.
516         ADD     DX,2                    ; And the XMS address.
517  
518         JMP     XMStoMem02              ; Move the block.
519  
520  
521   XMStoMem01:
522                                         ; XMS address is even.
523                                         ; --------------------
524         ADD     DX,CX                   ;
525         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
526         SUB     DX,CX                       ;
527         MOV     [XMSwordGET.SrcOffsetX],DI  ;
528  
529         MOV     AH,0BH                  ; Set the XMS move, function code.
530         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
531  
532         PUSH    BX                      ;
533         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
534         POP     BX                      ;
535         DEC     AX                      ; Check for errors.
536         JNZ     XMStoMem03              ; Error out if error.
537  
538         MOV     AX,[XMSword]            ; Get the moved word.
539  
540         XCHG    DI,CX                   ;
541         MOV     ES:[BX+DI],AL           ; Move the odd byte to memory.
542         XCHG    DI,CX                   ;
543  
544   XMStoMem02:
545         JCXZ    XMStoMem04              ; Avoid a zero byte move.
546  
547         MOV     XMSmainGET.Length,CX    ; Set length for the move.
548  
549         MOV     XMSmainGET.DestOffset,BX   ; Set Memory address.
550         MOV     XMSmainGET.DestOffsetX,ES  ;
551  
552         MOV     XMSmainGET.SrcOffset,DX    ; Set XMS address.
553         MOV     XMSmainGET.SrcOffsetX,DI   ;
554  
555         MOV     AH,0BH                  ; Set the XMS move, function code.
556         MOV     SI,OFFSET XMSmainGET    ; Set address of the move structure.
557  
558         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
559         DEC     AX                      ; Check for errors.
560         JZ      XMStoMem05
561  
562   XMStoMem03:
563         MOV     AX,XMSmemError          ; Set error code if error.
564         JMP     XMStoMem05              ;
565  
566   XMStoMem04:
567         XOR     AX,AX                   ;
568  
569   XMStoMem05:
570         POP     DS
571         POP     ES
572         POP     DI
573         POP     SI
574         POP     DX
575         POP     CX
576         POP     BX
577  
578         POP     BP
579         RET                             ; Exit
580  
581 endproc  XMStoMem
582  
583 SUBTTL  Extended Memory - MemToXMS
584 PAGE+
585  
586  
587  ;
588  ; Stack frame definition for int MemToXMS( unsigned Handle,
589  ;                                        unsigned blk,
590  ;                                        unsigned blkAdr,
591  ;                                        unsigned Bytes,
592  ;                                        char     *memAdr
593  ;                                       );
594  ;
595  ;  XMSmemError is returned if the operation fails, Zero if success.
596  ;
597  
598 procname  MemToXMS
599  
600         PUSH    BP
601         MOV     BP,SP
602  
603         PUSH    BX
604         PUSH    CX
605         PUSH    DX
606         PUSH    SI
607         PUSH    DI
608         PUSH    ES
609         PUSH    DS
610  
611         MOV     AX,CS                   ;
612         MOV     DS,AX                   ;
613  
614         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
615         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
616         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
617         MOV     [XMSmainPUT.DestHandle],DX ; Set it in the move structures.
618         MOV     [XMSwordPUT.DestHandle],DX ;
619         MOV     [XMSwordGET.SrcHandle],DX  ;
620  
621         XOR     DX,DX                   ;
622         MOV     DI,xmsgpblk[BP]         ; Get the block number.
623         SHR     DI,1                    ; Form the 32 bit XMS address in
624         RCR     DX,1                    ;  DI:DX.
625         SHR     DI,1                    ;
626         RCR     DX,1                    ;
627         ADD     DX,xmsgpblkAdr[BP]      ;
628  
629         TEST    CX,1                    ; Check for an odd number of bytes
630         JZ      MemToXMS02              ;  to transfer.
631  
632         DEC     CX                      ; Decrement to an even number of
633 bytes.
634  
635         TEST    DX,1                    ; Check for an odd XMS address.
636         JZ      MemToXMS01              ;
637  
638                                         ; XMS address is odd.
639                                         ; -------------------
640         DEC     DX                      ;
641         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
642         MOV     [XMSwordGET.SrcOffsetX],DI  ;
643         MOV     [XMSwordPUT.DestOffset],DX  ;
644         MOV     [XMSwordPUT.DestOffsetX],DI ;
645  
646         MOV     AH,0BH                  ; Set the XMS move, function code.
647         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
648  
649         PUSH    BX                      ;
650         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
651         POP     BX                      ;
652         DEC     AX                      ; Check for errors.
653         JNZ     MemToXMS03              ; Error out if error.
654  
655         MOV     AH,ES:[BX]              ; Get the odd memory byte.
656  
657         MOV     [XMSwordByte+1],AH      ; Put it in the moved word.
658  
659         MOV     AH,0BH                  ; Set the XMS move, function code.
660         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
661  
662         PUSH    BX                      ;
663         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
664         POP     BX                      ;
665         DEC     AX                      ; Check for errors.
666         JNZ     MemToXMS03              ; Error out if error.
667  
668         INC     BX                      ; Reset the memory address.
669         ADD     DX,2                    ; And the XMS address.
670  
671         JMP     MemToXMS02              ; Move the block.
672  
673   MemToXMS01:
674                                         ; XMS address is even.
675                                         ; --------------------
676         ADD     DX,CX                   ;
677         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
678         MOV     [XMSwordPUT.DestOffset],DX  ;
679         SUB     DX,CX                       ;
680         MOV     [XMSwordGET.SrcOffsetX],DI  ;
681         MOV     [XMSwordPUT.DestOffsetX],DI ;
682  
683         MOV     AH,0BH                  ; Set the XMS move, function code.
684         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
685  
686         PUSH    BX                      ;
687         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
688         POP     BX                      ;
689         DEC     AX                      ; Check for errors.
690         JNZ     MemToXMS03              ; Error out if error.
691  
692         XCHG    DI,CX                   ;
693         MOV     AL,ES:[BX+DI]           ; Get the odd memory byte.
694         XCHG    DI,CX                   ;
695  
696         MOV     [XMSwordByte],AL        ; Set the moved word.
697  
698         MOV     AH,0BH                  ; Set the XMS move, function code.
699         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
700  
701         PUSH    BX                      ;
702         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
703         POP     BX                      ;
704         DEC     AX                      ; Check for errors.
705         JNZ     MemToXMS03              ; Error out if error.
706  
707   MemToXMS02:
708         JCXZ    MemToXMS04              ; Avoid a zero byte move.
709  
710         MOV     XMSmainPUT.Length,CX    ; Set length for the move.
711  
712         MOV     XMSmainPUT.SrcOffset,BX    ; Set Memory address.
713         MOV     XMSmainPUT.SrcOffsetX,ES   ;
714  
715         MOV     XMSmainPUT.DestOffset,DX   ; Set XMS address.
716         MOV     XMSmainPUT.DestOffsetX,DI  ;
717  
718         MOV     AH,0BH                  ; Set the XMS move, function code.
719         MOV     SI,OFFSET XMSmainPUT    ; Set address of the move structure.
720  
721         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
722         DEC     AX                      ; Check for errors.
723         JZ      MemToXMS05
724  
725   MemToXMS03:
726         MOV     AX,XMSmemError          ; Set error code if error.
727         JMP     MemToXMS05              ;
728  
729   MemToXMS04:
730         XOR     AX,AX                   ;
731  
732   MemToXMS05:
733         POP     DS
734         POP     ES
735         POP     DI
736         POP     SI
737         POP     DX
738         POP     CX
739         POP     BX
740  
741         POP     BP
742         RET                             ; Exit
743  
744 endproc  MemToXMS
745  
746  
747 SUBTTL  Last Page
748 PAGE+
749  
750 pwrlolvl_TEXT   ENDS
751  
752         END
753