
                               ASSEMBLY
                            Gerenciamento de Memria
                                Aula nr. 16 de 26

    Usando a memria Expandida (EMS).

    Muitos modplayers hoje  em  dia  usam  a  memria expandida para
armazenar os samples.  Neste texto veremos como funciona  a  memria
expandida e como us-la...

    A  maioria  dos  PC-ATs  com  mais de 1Mb de memria possui dois
tipos de memria:

     Convencional - Na faixa de 0 at 1Mb
     Extendida: de 1Mb em diante.

    A  memria extendida  facilmente manipulvel quando um programa
est em modo protegido e com  toda  a  memria mapeada em um ou mais
seletores.  Os 386s permitem que um seletor acesse  um  segmento  de
at  4Gb  de  tamanho...   Mas,  no   esse o nosso caso.  Temos um
pequeno programa rodando sob o MS-DOS, no modo real (modo nativo dos
processadores Intel), que tem acesso somente  memria convencional.
Podemos acessar a memria  extendida  atravs do driver HIMEM.SYS ou
usando  uma  funo  de  movimento  de  blocos  da  BIOS,  mas  isso
aumentaria em muito a complexidade do software (e, por conseguncia,
seu tamanho).

    A Lotus, Intel e Microsoft criaram a especificao EMS para esse
caso.  O  programa  EMM386.EXE,  ou  qualquer  outro  gerenciador de
memria como o QEMM, emula a memria expandida da  mesma  forma  que
uma  mquina  com  apenas  este  tipo  de  memria  faria (A memria
expandida por hardware no fez muito  sucesso nos EUA como a memria
extendida!).  A especificao EMS  simplesmente  usa  um  espao  da
memria  convencional  (chamado  de  "Page  Frame")  para  armazenar
"pginas" de 16kb da memria extendida.  Isto  ...   divida  a  sua
memria  extendida  em  diversos  blocos  de  16k e ter o nmero de
pginas (pages) que podero estar disponveis para  uso.

    O EMM (Expanded  Memory  Manager)  simplesmente  faz a cpia das
pginas  desejadas  para  o  "Page  Frame" para que o nosso software
posssa l-las e escrev-las,  copiando-as  de  volta para as pginas
corretas quando fizermos a troca de pginas  do  "Page  Frame".   No
"Page  Frame"  cabem,  normalmente, 4 pginas... fazendo um total de
64kb (ou seja, exatamente o  tamanho  de um segmento!).  Considere a
figura abaixo:


         Memria extendida          Memria extendida
                                         paginada

               Ŀ                       Ŀ
                                          Page 0
                                        Ĵ
                                          Page 1
                                        Ĵ
                                          Page 2
                                        Ĵ
                                          Page 3
                                        Ĵ
                                          Page 4
                                        Ĵ
               ...                    ...


    Ok...  a memria extendida foi dividida em 'n' pginas  de  16k.
O  "Page  Frame" fica na memria convencional.  Por exemplo, suponha
que o "Page Frame" esteja localizado no segmento 0C000h:


                         "Page Frame"

                     Ŀ0
     Pgina fisica 0                    
                     Ĵ16k
     Pgina fisica 1                    
                     Ĵ32k
     Pgina fisica 2                    
                     Ĵ48k
     Pgina fisica 3                    
                     64k


    Do offset 0 at 16k-1 fica a primeira pgina do "Page Frame", do
offset 16k at 32k-1 a segunda, e assim por diante.  A especificao
EMS nos permite colocar apenas 4  pginas no "Page Frame".  Assim, o
nosso programa escolhe cada uma das  quatro  "pginas  lgicas"  que
sero  copiadas  da  memria  extendida  para  cada  uma  das quatro
"pginas fisicas" do Page Frame.

    Vale a pena lembrar que o  Page Frame est sempre em algum lugar
da memria convencional, portanto  acessvel  aos  programas  feitos
para MS-DOS, que normalmente trabalham em modo real.

    A  interrupo  67h   a porta de entrada para as funes do EMM
(EMM386,  QEMM,  386MAX,  entre  outros).  Mas antes de comearmos a
futucar o EMM precisamos saber se ele est presente...  Eis a rotina
de deteco do EMM p/ os compiladores C da BORLAND:

---%<----------------------------------%<---------------------------
#include <io.h>
#include <fcntl.h>
#include <dos.h>

#define CARRY_BIT   (_FLAGS & 0x01)

/* Obtm a maior verso do EMM - definida em outro mdulo! */
extern int emm_majorVer(void);

/* Testa a presena do EMM
   Retorna 0 se EMM no presente ou verso < 3.xx
   Retorna 1 se tudo ok! */
int isEMMpresent(void)
{
    int handle;

    /* Tenta abrir o device driver EMMXXXX0 para leitura! */
    if ((handle = open("EMMXXXX0", O_BINARY | O_RDONLY)) == -1)
        return 0;   /* No tem EMM! */

    /* Verifica se  um arquivo ou dispositivo
       Usa IOCTL para isso! */
    _BX = handle;
    _AX = 0x4400;
    geninterrupt(0x21);
    if (!(_DX & 0x80))
        return 0;   /*  um arquivo!!! No  o EMM! */

    /* Verifica o dispositivo est ok */
    _BX = handle;
    _AX = 0x4407;
    geninterrupt(0x21);
    if (CARRY_BIT || !_AL) return 0; /* No est ok */

    /* Verifica a verso do EMM.
       Para nossos propsitos tem que ser >= que
       3.xx */
    if (emm_majorVer() < 3) return 0; /* No  ver >= 3.xx */

    /* Tudo ok... EMM presente */
    return 1;
}
---%<----------------------------------%<---------------------------

    No prximo texto mostrarei como usar o EMM.
                                                 
