
 Area: FC_prog 
  Msg#: 1743                                         Date: 04-02-96  06:53
  From: Matthew Probert                              Read: Yes    Replied: No 
    To: All                                          Mark:                     
  Subj: MCBs in PC HMA

                       Scanning The PC High Memory Area

                           Matthew  Probert
                           Servile Software


A PC's conventional memory extends from address 00000 to FFFFF. Within 
this area some regions are occupied by vector data and ROMs, with the 
BIOS occupying the area from F0000 to FFFFF. A second expansion ROM 
area is defined as commencing at location C0000. However, it is rare 
to find expansion ROMs occupying the entire area from C0000 to EFFFF, 
and any unused address range is known as the "High Memory Area", in 
which DOS creates "Upper Memory Blocks" or "loads programs high". 

If we want to search this area for memory control blocks we must first 
determine the end of the ROM code, and thereby the start of the high 
memory area. 

This code fragment will scan the memory addresses from C0000 (segment 
C000) onwards untill it locates RAM. The pointer 'q' is a standard far 
pointer. 


    seg = 0xc000;

    /*
        Step past ROM
    */
    for(;;)
    {
        q = MK_FP(seg,0);
        if (*q != 0x55 || *(q+1) != 0xAA)
            break;
        seg += 0x80;
    }


Having found the start of high memory, MCBs may be read, not as a 
linked list, but sequentially from RAM. Remembering that a MCB is 
identified by the identifier byte recording the value of 'M' or 'Z'. 
The order of MCBs in high memory seems to be different from that in 
conventional memory. I'm sorry if this is a bit crude, but at least 
its something!

    /*
        q points to start of High Memory
    */
    for(;;)
    {
        READ_MCB(q);
        psp = mcb->psp_seg[1] * 256 + mcb->psp_seg[0];
        length = mcb->paras[1] * 256 + mcb->paras[0];

        /*
            A program may be identified by the MCB which preceeds
            the program's PSP as indicated in this test
        */

        if ((mcb->id == 'M' || mcb->id == 'Z') && psp == seg + 1)
        {
            printf("\n%04x %04x   ",psp,length * 16);
            printf("%-8.8s    ",mcb->pad + 3);
        }
        seg++;
        if (seg > 0xEFFF)
            break;
        q = MK_FP(seg,0);
    }
}

The data structure 'MCB' refered to looks like this:

typedef struct
{
    unsigned char id;
    unsigned char psp_seg[2];
    unsigned char paras[2];
    char pad[11];        /* pad + 3 == owner name */
}
MCB;

MCB *mcb;


And the function 'READ_MCB()' referred to is simply this:

void READ_MCB(void far *mcb_addr)
{
    _fmemcpy(mcb,mcb_addr,16);
}




... [Servile Info Journal]
___ Blue Wave/QWK v2.12
