Announcement

Collapse
No announcement yet.

XMS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Jose Antonio Esteva R
    Guest replied
    Thank you very much,

    Maybe this code to be useful for many PowerBasic programmers.

    Jose Antonio Esteva Ramirez
    MEXICO

    ------------------
    * UNNECESSARY message quoting removed by ADMINISTRATOR!

    Leave a comment:


  • Hans Ruegg
    replied
    As I started posting to this thread, I had to finish fixing your code!
    (I am thankful for the many people on this forum who helped me to learn
    new things, so I am glad being able to help somebody else.)
    Here follows the code which works (at least on my computer...):
    Code:
    '==================================================================
    ' XMS handling code, original by Jose Antonio Esteva R.
    
    ' BUGS FIXED:
    ' 1) The following lines will fail because of an error I learnt about some 
    '    weeks ago in this forum (see Topic "Inline Assembler Bug?", don't 
    '    remember the exact date):
    '  ! mov DS, SegEstructura??
    '  ! mov SI, DesEstructura??
    '  ! call Dword Ptr Pointer
    '   --> "Pointer" is a PB variable, so DS must correspond to the PB Data
    '   Segment when you refer to it. But you are modifying DS two lines before.
    '   In this special case, where you NEED to pass a parameter in DS,
    '   you have to declare "Pointer" as a Code Segment variable.
    '   (See code below for the way to implement it.)
    ' 2) - very easy this one:
    '  If you set bufferXMS$ to "", you are implicitly allocating ZERO data
    '  bytes to bufferXMS$, so you cannot expect this string to return any
    '  data. You must define the length of the string before using it to
    '  receive data. (The allocated length of a string is not altered by just
    '  writing data to its address; more likely you will overwrite other data
    '  which is located past the end of the string.)
    ' 3) - a more subtle one:
    '  When passing a 32-bit pointer as you are doing it in "Estructura",
    '  the Offset value (Low-order word) comes FIRST, the Segment value
    '  (high-order word) comes SECOND. Therefore you must assign STRPTR(bufferXMS$)
    '  first, STRSEG(bufferXMS$) second. (You did this right when initializing
    '  the value of "Pointer", but not when filling in the EMM structure.)
    '  - You might probably want to rename the members of your type declaration
    '  in order to reflect this change. I preserved your original names in the 
    '  following code. 
    
    ' Hans Ruegg, March 2001
    
    
    Cls
    
    '*********************************************************
    Variables:
    
    Shared BufferXMS$
    Shared Identificador??
    
    Type EstructuraParaMoverDatos
    
    NoBytes as DWORD
    IDFuente as WORD
    SegDirFuente as WORD
    DesDirFuente as WORD
    IDDestino as WORD
    SegDirDestino as WORD
    DesDirDestino as WORD
    
    end type
    
    DIM Estructura as shared EstructuraParaMoverDatos
    
    
    '*********************************************************
    Inicio:
    
    Print "CITLALLI 3.0"
    Print "Memoria extendida."
    Print
    
    ! mov ax,&H4300
    ! int &H2F
    ! mov SiHay?,al
    
    If SiHay?=128 then
    
    Call VersionXMS
    Call TotalMemoriaExtendida
    Call ReservarBloqueDeMemoriaExtendida
    
    BufferXMS$="01234567890123456789012345678912"
    Call SubirInformacionXMS
    BufferXMS$ = STRING$(32,0)   'allocating space here for receiving data
    Call BajarInformacionXMS
    Print "-"; BufferXMS$; "-"
    
    Call LiberarBloqueDeMemoriaExtendida
    
    else
    
    Print "No se encontr¢ administrador de memoria extendida"
    
    end if
    
    End
    
    '*********************************************************
    'Here are 4 bytes reserved for the Code Segment variable "Pointer".
    'Make sure you put these lines in a place which is NEVER reached by
    'the program execution flow, else your program will try to execute
    'the contents of these 4 bytes as a machine instruction.
    
    'Code Segment variables are always shared, but if you have a very long
    'program with different segments, you must make sure that you are referring
    'only to CS variables within the same segment.
    ' (If you put a $SEGMENT metastatement between these lines and any
    '  code which refers to CS:Pointer, your program would crash.)
    
    ' Note also that you can access Code Segment variables ONLY in Assembly
    ' Language statements, not in PB statements; so you will see that I
    ' translated all PB statements referring to "Pointer" into Assembler.
    
    Pointer:
    ! DW 0
    ! DW 0
    
    '*********************************************************
    SubProcedimientos:
    
    SUB VersionXMS()
    
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized01    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized01
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov CS:Pointer[0], BX
    ! mov CS:Pointer[2], ES
    ! pop DS
    
    alreadyInitialized01:
    ! push DS
    ! mov AH, 0
    ! mov BL, 0
    ! call Dword Ptr Pointer
    ! pop DS                     ; Restore DS here to be able to access
    ! mov OK??, DX               ; PB variables again.
    ! mov Version1?, AH          ; In this place it does not matter because
    ! mov Version2?, AL          ; DS is not modified, but in other places
                                 ' it DOES matter!
    If OK??=1 then
    Print "Version del controlador XMS: ";
    Print LTrim$(Str$(Version1?)); "." LTrim$(Str$(Version2?))
    end if
    
    END SUB
    
    
    SUB TotalMemoriaExtendida()
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized02    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized02
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov CS:Pointer[0], BX
    ! mov CS:Pointer[2], ES
    ! pop DS
    
    alreadyInitialized02:
    ! push DS
    ! mov AH, 8
    ! mov BL, 0
    ! call Dword Ptr CS:Pointer
    ! pop DS
    ! mov TMB??, AX
    ! mov Libre??, DX
    
    Print "Memoria extendida libre: "; Libre??; "KB"
    Print "Tama¤o del maximo bloque libre: "; TMB??; "KB"
    
    END SUB
    
    
    SUB ReservarBloqueDeMemoriaExtendida()
    
    Rem Por ahora siempre de 32K
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized03    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized03
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS
    
    alreadyInitialized03:
    ! push DS
    ! mov AH, 9
    ! mov BL, 0
    ! mov DX, 100
    ! call Dword Ptr CS:Pointer
    ! pop DS
    ! mov OK??, AX
    ! mov Identificador??, DX
    
    If OK??=1 then
    Print "Se reserv¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if
    
    END SUB
    
    
    SUB LiberarBloqueDeMemoriaExtendida()
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized04    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized04
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov CS:Pointer[0], BX
    ! mov CS:Pointer[2], ES
    ! pop DS
    
    alreadyInitialized04:
    ! push DS
    ! mov AH, &H0A
    ! mov BL, 0
    ! mov DX, Identificador??
    ! call Dword Ptr CS:Pointer
    ! pop DS
    ! mov OK??, AX
    
    If OK??=1 then
    Print "Se liber¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if
    
    END SUB
    
    
    SUB SubirInformacionXMS()
    
    Estructura.NoBytes = 32
    Estructura.IDFuente = 0
    Estructura.SegDirFuente = STRPTR(BufferXMS$)
    Estructura.DesDirFuente = STRSEG(BufferXMS$)
    Estructura.IDDestino = Identificador??
    Estructura.SegDirDestino = 0
    Estructura.DesDirDestino = 0
    
    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized05    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized05
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov CS:Pointer[0], BX
    ! mov CS:Pointer[2], ES
    ! pop DS
    
    alreadyInitialized05:
    ! push DS
    ! mov AH, &H0B
    ! mov SI, DesEstructura??
    ! mov DS, SegEstructura??     ; from here on you cannot use PB variables any longer
    ! call Dword Ptr CS:Pointer   ; because DS is modified!!
    ! pop DS                      ; Restore DS HERE to be able to access PB variables again
    ! mov OK??, AX
    ! mov ER?, BL
    
    Print "Subir datos a la memoria extendida: ";
    Print " OK="; Hex$(OK??)
    If OK??<>1 then print " Error "; Hex$(ER?)
    
    END SUB
    
    
    SUB BajarInformacionXMS()
    
    Estructura.NoBytes = 32
    Estructura.IDFuente = Identificador??
    Estructura.SegDirFuente = 0
    Estructura.DesDirFuente = 0
    Estructura.IDDestino =0
    Estructura.SegDirDestino = STRPTR(BufferXMS$)
    Estructura.DesDirDestino = STRSEG(BufferXMS$)
    
    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)
    
    ! CMP WORD CS:Pointer, 0      ; These four lines replace the
    ! JNZ alreadyInitialized06    ; original   IF pointer=0 THEN.
    ! CMP WORD CS:Pointer[2], 0
    ! JNZ alreadyInitialized06
    
    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov CS:Pointer[0], BX
    ! mov CS:Pointer[2], ES
    ! pop DS
    
    alreadyInitialized06:
    ! push DS
    ! mov AH, &H0B
    ! mov SI, DesEstructura??
    ! mov DS, SegEstructura??
    ! call Dword Ptr CS:Pointer
    ! pop DS                      ; Restore DS HERE to be able to access PB variables again
    ! mov OK??, AX
    ! mov ER?, BL
    
    Print "Bajar datos de la memoria extendida: ";
    Print " OK="; Hex$(OK??)
    If OK??<>1 then print " Error "; Hex$(ER?)
    
    END SUB

    Leave a comment:


  • Jose Antonio Esteva R
    Guest replied
    Sorry,

    I correct that problem but it not works jet, here is again my
    code with all the corrections:

    1.- I verify if there is an Extended Memory driver
    2.- Get XMS version
    3.- Query Free Extended Memory
    4.- Allocate Extended Memory Block
    5.- Upload BufferXMS$ to Extended Memory
    6.- Erase BufferXMS$
    7.- Download the data at Extended Memory to BufferXMS$
    8.- Print BufferXMS$ (But there is not data)
    9.- Free Extended Memory Block

    Rem CITLALLI 3.0, memoria extendida.
    Rem JAER Mex2001

    Cls

    '*********************************************************
    Variables:

    Shared BufferXMS$
    Shared Identificador??

    Type EstructuraParaMoverDatos

    NoBytes as DWORD
    IDFuente as WORD
    SegDirFuente as WORD
    DesDirFuente as WORD
    IDDestino as WORD
    SegDirDestino as WORD
    DesDirDestino as WORD

    end type

    DIM Estructura as shared EstructuraParaMoverDatos


    '*********************************************************
    Inicio:

    Print "CITLALLI 3.0"
    Print "Memoria extendida."
    Print

    ! mov ax,&H4300
    ! int &H2F
    ! mov SiHay?,al

    If SiHay?=128 then

    Call VersionXMS
    Call TotalMemoriaExtendida
    Call ReservarBloqueDeMemoriaExtendida

    BufferXMS$="01234567890123456789012345678912"
    Call SubirInformacionXMS
    BufferXMS$=""
    Call BajarInformacionXMS
    Print "-"; BufferXMS$; "-"

    Call LiberarBloqueDeMemoriaExtendida

    else

    Print "No se encontr¢ administrador de memoria extendida"

    end if

    End


    '*********************************************************
    SubProcedimientos:

    SUB VersionXMS()

    DIM Pointer AS SHARED DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 0
    ! mov BL, 0
    ! call Dword Ptr Pointer
    ! mov OK??, DX
    ! mov Version1?, AH
    ! mov Version2?, AL
    ! pop DS

    If OK??=1 then
    Print "Version del controlador XMS: ";
    Print LTrim$(Str$(Version1?)); "." LTrim$(Str$(Version2?))
    end if

    END SUB


    SUB TotalMemoriaExtendida()

    DIM Pointer AS SHARED DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 8
    ! mov BL, 0
    ! call Dword Ptr Pointer
    ! mov TMB??, AX
    ! mov Libre??, DX
    ! pop DS

    Print "Memoria extendida libre: "; Libre??; "KB"
    Print "Tama¤o del maximo bloque libre: "; TMB??; "KB"

    END SUB


    SUB ReservarBloqueDeMemoriaExtendida()

    DIM Pointer AS SHARED DWORD

    Rem Por ahora siempre de 32K

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 9
    ! mov BL, 0
    ! mov DX, 100
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov Identificador??, DX
    ! pop DS

    If OK??=1 then
    Print "Se reserv¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if

    END SUB


    SUB LiberarBloqueDeMemoriaExtendida()

    DIM Pointer AS SHARED DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0A
    ! mov BL, 0
    ! mov DX, Identificador??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! pop DS

    If OK??=1 then
    Print "Se liber¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if

    END SUB


    SUB SubirInformacionXMS()

    DIM Pointer AS SHARED DWORD

    Estructura.NoBytes = 32
    Estructura.IDFuente = 0
    Estructura.SegDirFuente = STRSEG(BufferXMS$)
    Estructura.DesDirFuente = STRPTR(BufferXMS$)
    Estructura.IDDestino = Identificador??
    Estructura.SegDirDestino = 0
    Estructura.DesDirDestino = 0

    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0B
    ! mov DS, SegEstructura??
    ! mov SI, DesEstructura??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov ER?, BL
    ! pop DS

    Print "Subir datos a la memoria extendida: ";
    Print " OK="; Hex$(OK??)
    If OK??<>1 then print " Error "; Hex$(ER?)

    END SUB


    SUB BajarInformacionXMS()

    DIM Pointer AS SHARED DWORD

    Estructura.NoBytes = 32
    Estructura.IDFuente = Identificador??
    Estructura.SegDirFuente = 0
    Estructura.DesDirFuente = 0
    Estructura.IDDestino =0
    Estructura.SegDirDestino = STRSEG(BufferXMS$)
    Estructura.DesDirDestino = STRPTR(BufferXMS$)

    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0B
    ! mov DS, SegEstructura??
    ! mov SI, DesEstructura??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov ER?, BL
    ! pop DS

    Print "Bajar datos de la memoria extendida: ";
    Print " OK="; Hex$(OK??)
    If OK??<>1 then print " Error "; Hex$(ER?)

    END SUB


    Originally posted by Gary Akins:
    Jose -

    Estructura may not be a string, but BufferXM$ is a string, as identified by the $ type declarator. From the PowerBASIC Reference Guide, p284:

    So when you do this:
    Code:
    Estructura.SegDirFuente = VARSEG(BufferXM$)
    Estructura.DesDirFuente = VARPTR(BufferXM$)
    Estructura.SegDirFuente and Estructura.DesDirFuente contain the segment : offset address of BufferXM$'s handle, not the segment : offset address of BufferXM$'s data space. If you change it to:

    Code:
    Estructura.SegDirFuente = STRSEG(BufferXM$)
    Estructura.DesDirFuente = STRPTR(BufferXM$)
    then Estructura.SegDirFuente and Estructura.DesDirFuente will point to the segment : offset address of BufferXM$'s data space.



    ------------------

    Leave a comment:


  • Gary Akins
    Guest replied
    Jose -

    Estructura may not be a string, but BufferXM$ is a string, as identified by the $ type declarator. From the PowerBASIC Reference Guide, p284:

    When you use VARSEG to get the segment of a string, keep in mind that the value being returned is the segment where the string handle is located, not the segment where the actual contents of the string are located; use STRPTR and STRSEG to fond this address.
    and from p.282:

    When you use VARPTR to get the offset of a string, keep in mind that the value being returned is the offset of the string handle not the actual data in the string.
    So when you do this:
    Code:
    Estructura.SegDirFuente = VARSEG(BufferXM$)
    Estructura.DesDirFuente = VARPTR(BufferXM$)
    Estructura.SegDirFuente and Estructura.DesDirFuente contain the segment : offset address of BufferXM$'s handle, not the segment : offset address of BufferXM$'s data space. If you change it to:

    Code:
    Estructura.SegDirFuente = STRSEG(BufferXM$)
    Estructura.DesDirFuente = STRPTR(BufferXM$)
    then Estructura.SegDirFuente and Estructura.DesDirFuente will point to the segment : offset address of BufferXM$'s data space.

    ------------------


    [This message has been edited by Gary Akins (edited March 09, 2001).]

    Leave a comment:


  • Jose Antonio Esteva R
    Guest replied
    But Estructura is not a string!

    Originally posted by Hans Ruegg:
    Forgot to mention also: You must refer to the address of a string
    with STRSEG and STRPTR, not VARSEG and VARPTR.

    Greetings,

    Hans Ruegg.


    ------------------

    Leave a comment:


  • Jose Antonio Esteva R
    Guest replied
    Yes, I declare this variables:

    Shared BufferXMS$
    Shared Identificador??

    Type EstructuraParaMoverDatos

    NoBytes as DWORD
    IDFuente as WORD
    SegDirFuente as WORD
    DesDirFuente as WORD
    IDDestino as WORD
    SegDirDestino as WORD
    DesDirDestino as WORD

    end type

    DIM Estructura as shared EstructuraParaMoverDatos

    Buffer$ is where I like download the information that is at the
    extended memory.

    And Estructura is the "Extended Memory Move Structure" defined at
    the XMS 2.0.

    Originally posted by Hans Ruegg:
    Maybe you have to check some "obvious" error sources before doubting
    about the XMS support code itself (which I did not check exactly).
    But the following lines called my attention:

    Estructura.SegDirFuente = VARSEG(BufferXM$)
    Estructura.DesDirFuente = VARPTR(BufferXM$)
    Estructura.IDDestino = Identificador??

    These lines are inside a SUB. Did you declare BufferXM$ and
    Identificador?? as SHARED ? If not, these variables are not
    initialized when you enter the SUB, so you are passing invalid
    values to the XMS manager.

    Hans Ruegg


    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    Well spotted Hans!

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Hans Ruegg
    replied
    Forgot to mention also: You must refer to the address of a string
    with STRSEG and STRPTR, not VARSEG and VARPTR.

    Greetings,

    Hans Ruegg.

    Leave a comment:


  • Hans Ruegg
    replied
    Maybe you have to check some "obvious" error sources before doubting
    about the XMS support code itself (which I did not check exactly).
    But the following lines called my attention:

    Estructura.SegDirFuente = VARSEG(BufferXM$)
    Estructura.DesDirFuente = VARPTR(BufferXM$)
    Estructura.IDDestino = Identificador??

    These lines are inside a SUB. Did you declare BufferXM$ and
    Identificador?? as SHARED ? If not, these variables are not
    initialized when you enter the SUB, so you are passing invalid
    values to the XMS manager.

    Hans Ruegg

    Leave a comment:


  • Lance Edmonds
    replied
    That is an "unknown" error - it is not documented in the list I have.

    BTW, you may want to note the O/S and XMS driver are you using...

    Can anyone else help with this problem?




    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Jose Antonio Esteva R
    Guest replied
    BL return 32H.



    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    I understood that support for MAXLIB was dropped a couple of years ago, any registering it was no longer possible... meaning that it can't be used in any commercial/shareware applications anymore.

    Does anyone know differently?

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Mark Hunter
    replied
    Download Brian McLaughlin's MAXLIB -- MAX12C.ZIP at http://www.powerbasic.com/files/pub/pbdos/library/
    This will give PB support for XMS.

    If you're using PB 3.5, you must first convert
    the MAXLIB.PBL to the new format. Run the
    release 3.2 (or whatever < 3.5) PBLIB program
    and list and extract the object files, then
    with the 3.5 PBLIB build them into a new
    MAXLIB.PBL.

    Brian gives out MAXLIB free for personal use.


    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    What is the error code returned by the XMS driver?

    The error code for that function is returned in the BL register... a table of the error values can be found at http://www.ctyme.com/intr/rb-4768.htm#Table2775

    An overview of the XMS functions can be found at http://www.ctyme.com/intr/rb-4768.htm


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Jose Antonio Esteva R
    Guest started a topic XMS

    XMS

    I am developing a XMS support to my programs based on a script
    writing by Dave Navarro, Jr.

    I can:

    08h) Query Free Extended Memory
    09h) Allocate Extended Memory Block
    0Ah) Free Extended Memory Block

    But not:

    0Bh) Move Extended Memory Block

    My code is it:

    Sub VersionXMS()

    DIM Pointer AS DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 0
    ! mov BL, 0
    ! call Dword Ptr Pointer
    ! mov OK??, DX
    ! mov Version1?, AH
    ! mov Version2?, AL
    ! pop DS

    If OK??=1 then
    Print "Version del controlador XMS: ";
    Print LTrim$(Str$(Version1?)); "." LTrim$(Str$(Version2?))
    end if

    END SUB

    SUB TotalMemoriaExtendida()

    DIM Pointer AS DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 8
    ! mov BL, 0
    ! call Dword Ptr Pointer
    ! mov TMB??, AX
    ! mov Libre??, DX
    ! pop DS

    Print "Memoria extendida libre: "; Libre??; "KB"
    Print "Tama¤o del maximo bloque libre: "; TMB??; "KB"

    END SUB


    SUB ReservarBloqueDeMemoriaExtendida()

    DIM Pointer AS DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, 9
    ! mov BL, 0
    ! mov DX, 40
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov Identificador??, DX
    ! pop DS

    If OK??=1 then
    Print "Se reserv¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if

    END SUB


    SUB LiberarBloqueDeMemoriaExtendida()

    DIM Pointer AS DWORD

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0A
    ! mov BL, 0
    ! mov DX, Identificador??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! pop DS

    If OK??=1 then
    Print "Se liber¢ bloque de memoria extendida ID: "; Hex$(Identificador??)
    end if

    END SUB


    SUB SubirInformacionXMS()

    DIM Pointer AS DWORD
    DIM Estructura as EstructuraParaMoverDatos

    Estructura.NoBytes = 10
    Estructura.IDFuente = 0
    Estructura.SegDirFuente = VARSEG(BufferXM$)
    Estructura.DesDirFuente = VARPTR(BufferXM$)
    Estructura.IDDestino = Identificador??
    Estructura.DesDirDestino = 0
    Estructura.SegDirDestino = 1

    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0B
    ! mov DI, SegEstructura??
    ! mov SI, DesEstructura??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov ER?, BL
    ! pop DS

    If OK??=1 then
    Print "Se subieron los datos a la memoria extendida."
    else
    Print "ERROR "; Hex$(ER?)
    end if

    END SUB

    SUB BajarInformacionXMS()

    DIM Pointer AS DWORD
    DIM Estructura as EstructuraParaMoverDatos

    Estructura.NoBytes = 10
    Estructura.IDFuente = Identificador??
    Estructura.SegDirFuente = 0
    Estructura.DesDirFuente = 1
    Estructura.IDDestino =0
    Estructura.SegDirDestino = VARSEG(BufferXM$)
    Estructura.DesDirDestino = VARPTR(BufferXM$)

    SegEstructura?? = VARSEG(Estructura)
    DesEstructura?? = VARPTR(Estructura)

    IF Pointer = 0 THEN

    ! push DS
    ! mov AX, &h4310
    ! int &h2f
    ! mov Word Ptr Pointer[0], BX
    ! mov Word Ptr Pointer[2], ES
    ! pop DS

    END IF

    ! push DS
    ! mov AH, &H0B
    ! mov DS, SegEstructura??
    ! mov SI, DesEstructura??
    ! call Dword Ptr Pointer
    ! mov OK??, AX
    ! mov ER?, BL
    ! pop DS

    If OK??=1 then
    Print "Se bajaron los datos de la memoria extendida."
    else
    Print "ERROR "; Hex$(ER?)
    end if

    END SUB

    Someone can help me?

    JAER Mex2001

    ------------------
Working...
X