Mi is az a kiterjesztett memória ? Ez egy jó kérdés ... Amikor réges régen kitalálták a PC felépítését, még senki sem gondolt arra, hogy valaha 32 vagy 64mb ram lesz a gépekben. Mikor világossá vált, hogy a 640kb alapmemória egy kicsit kevés lesz, kitaláltak kétféle memóriakezelési módot. Az egyik ez EMS a másik az XMS. EMS esetén a felső memóriát egy címre képezi le és úgy kell lapozgatni. XMS esetén egy címet kell meghívni, és memóriát kell kérni, majd egy hívással feltölthetünk az XMS-be adatokat, és le is szedhetünk onnan. De hogyan működik ez ?

Egy interrupt hívással le lehet kérdezni az XMS driver címét, és ezt a dwordot kell meghivogatni. Először detektálni kell az XMS drivert, majd memóriát kérünk, lezárjuk, hogy más program ne tudjon belepiszkálni, feltöltjük értékekkel, olvasunk belőle, s ha már nincs rá szükségünk, akkor felszabadítjuk. Ennyi. Akkor lássunk először egy forrást, utána a magyarázatot:

-----------------------[ XMS.ASM ]----------------------   %include "macros.inc"   _64kb    equ          4096   segment code                               ; Ezután jönnek az utasítások ..start:   Initmem            mov          ax,data            mov          ds,ax            mov          ax,stack            mov          ss,ax            mov          sp,stacktop            Getmem       _64kb            mov          gs,ax            call         xmsdetect            ; van xms?            call         xmsaddress           ;            call         xmsshowmem           ; Xms cím lekérdezés és                                              ; A20 engedélyezés            mov          ax,64                ; Itt is kérünk 64k memóriát            call         xmsalloc            mov          [handle],ax          ; handle=handle            Grmode       13h                  ; mode 320x200x256            mov          dx,3c8h              ; ez csak egy sima 768 byteos            xor          al,al                ; paletta            out          dx,al            inc          dx            cld            mov          si,pal               ; pal1-től kezdődik a paletta            mov          cx,256*3            rep          outsb            Openfile     "data\poison.dat",gs,0  ; 320x200-as kép            mov          eax,64000            ; 64000 byteot máslunk            mov          [m_length],eax            xor          ax,ax                ; source= gs:0            mov          [m_shandle],ax            mov          ax,gs            shl          eax,16            mov          [m_sofs],eax            mov          ax,[handle]          ; dest= handle:0            mov          [m_dhandle],ax            xor          eax,eax            mov          [m_dofs],eax            call         copymem              ; átmásoljuk az XMS memóriába                                              ; a cuccost            push         gs            pop          es                   ; Kinullázzuk a Gs-től            mov          cx,16000             ; kezdődő memóriát, 64000            xor          eax,eax              ; hosszan            xor          di,di            rep          stosd            mov          ax,[handle]          ; source=handle:0            mov          [m_shandle],ax            xor          eax,eax            mov          [m_sofs],eax            xor          ax,ax                ; destination=gs:0            mov          [m_dhandle],ax            mov          ax,gs            shl          eax,16            mov          [m_dofs],eax            call         copymem              ; másolunk xms-ből simamembe            push         ds                   ; hogy lássuk is a gyönyörű            push         dword 0a000h         ; tömörítetlen képünket :)            pop          es            push         gs            pop          ds            xor          di,di            xor          si,si            mov          cx,16000            rep          movsd            pop          ds            mov          ax,data            mov          ds,ax            readkey            mov          ax,[handle]          ; felszabadítjuk a            call         xmsfree              ; kért XMS memót            Freemem      gs            Grmode       3h            mov          ax,4c00h            int          21h   %include "xmsunit.inc"   segment data   cim     dw    0   handle  dw    0   %include "poison.inc"   segment stack stack   resb 64   stacktop:   -----------------------[ XMSUNIT.INC ]----------------------   segment code                               ; Ezután jönnek az utasítások   xmsdetect: mov     ax,4300h              int     2fh              cmp     al,80h              jne     @nohimem              clc              ret   @nohimem:  stc              ret   xmsaddress:mov     ax,4310h                ; Beállítja az XMS címet              int     2fh              mov     ax,es              shl     eax,16              mov     ax,bx              mov     [xmsaddr],eax              mov     ah, 5                   ; az A20 vonal lokális              call    far [xmsaddr]           ; engedélyezése              ret   xmsshowmem:mov     ah,8                    ; mennyi memó van?              xor     bl,bl              call    far [xmsaddr]              mov     [maxblock],ax           ; maxblock=max foglalható              mov     [maxmem],dx             ; maxmem  =1értelmű              ret   xmsalloc:  mov     dx,ax                   ; memória foglalása              mov     ah,9                    ; ax=?kb              call    far [xmsaddr]              or      ax,ax              je      @err_all              mov     ax,dx              clc              ret   @err_all:  stc              ret   xmsfree:   mov      dx,ax                  ; xms felszabadítás              mov      ah,0ah              call     far [xmsaddr]              ret   copymem:   mov      ah,0bh                 ; memória másolása              mov      si,memblock              call     far [xmsaddr]              ret segment data   memblock:   m_length     dd       0   m_shandle    dw       0   m_sofs       dd       0   m_dhandle    dw       0   m_dofs       dd       0   xmsaddr      resd    1   maxblock     resw    1   maxmem       resw    1 -----------------------[ MACROS.INC ]----------------------   %macro     Initmem  0              mov     ah,4ah              mov     bx,8192              int     21h   %endmacro   %macro     Getmem  1              mov     ah,48h              mov     bx,%1              int     21h   %endmacro   %macro     Freemem 1              mov     ah,49h              push    es              push    word %1              pop     es              int     21h              pop     es   %endmacro   %macro     SetDta  2              push    ds              push    %1              pop     ds              mov     dx,%2              mov     ah,1ah              int     21h              pop     ds   %endmacro   %macro     GetDta  2              push    es bx              mov     ah,2fh              int     21h              push    es              pop     %1              mov     [%2],bx              pop     bx es   %endmacro   %macro     FindFir 2              mov     ah,4eh              mov     cx,[%2]              mov     dx,%1              int     21h   %endmacro   %macro     FindNxt 0              mov     ah,4fh              int     21h   %endmacro   %macro     Grmode  1              mov     ax,%1              int     10h   %endmacro   %macro     readkey 0              xor     ax,ax              int     16h   %endmacro   %macro     ShowCursor 0              mov     ah,1              xor     bh,bh              mov     cx,0607h              int     10h   %endmacro   %macro     HideCursor 0                    ; nem látod a villogó kurzort              mov     ah,1              xor     bh,bh              mov     cx,2000h              int     10h   %endmacro   ; megnyitja a "nev" filet, és a d_seg,d_ofs címre   ; másolja a szegmensugrásokat nem kezeli le!   ;   ; nev,d_seg,d_ofs   %macro     Openfile  3   segment data   %%cim      db      %1              db      0   %%fhandle  dw      0   segment code              mov     ax,3d00h              mov     dx,%%cim              int     21h              mov     [%%fhandle],ax              push    ds              xor     ax,ax              mov     ah,3fh              mov     bx,[%%fhandle]              mov     cx,0ffffh              mov     dx,%3              push    dword %2              pop     ds              int     21h   %%masol:   cmp     ax,0ffffh              je      %%c_copy              jmp     %%e_copy   %%c_copy:  mov     cx,0ffffh              mov     ah,3fh              int     21h              jmp     %%masol   %%e_copy:              pop     ds              mov     ax,data              mov     ds,ax              mov     ah,3eh              mov     bx,[%%fhandle]              int     21h   %endmacro -----------------------[ END OF EXAMPLE ]----------------------
Tehát először detektálja az XMS driver jelenlétét, majd lekérdezi a címet, ezt hívja meg a "call far [xmsdriver]". Itt jelenik meg egy újabb érdekesség, mégpedig az equ utasítás. Ezzel rengeteget lehet egyszerűsíteni a programunkon, hogy jobban érthető legyen:
      ofs  equ    offset       bptr equ  byte ptr       wptr equ  word ptr       dptr equ dword ptr       m    equ       mov
Tehát ez utasításokra is vonatkozhat, a program egyszerűen befordítja azokat.

E kis kitérő után folytassuk: Miután megkaptuk a megfelelő címet, kérünk egy kis kiterjesztett memóriát, másolgatunk bele, amit az emb táblázat kitöltésével tehetünk meg, melynek a felépítése:

      m_length   dd  0 Ennyi bájtot szeretnénk másolni.       m_shandle  dw  0 Source Handle, pl. ezt kapjuk vissza, amikor                        XMS memóriát  kérünk, ha 0,  akkor az m_soff                        egy  szegm:offs-et  mutat       m_sofs     dd  0 Ha srchandle nem 0,  akkor egy  32bites cím,                        a handle által  jelölt XMS memóriaszelet egy                        helyére  mutat, ahonnan  kezdi az olvasást !       m_dhandle  dw  0 Ez mutatja a célt, a többit: lásd m_shandle       m_dofs     dd  0 Mint az m_sofs-nél !
Az XMS_LOCK-kal vigyázzunk, mert - szerintem - nem megy Win 95/98/NT alatt...