home *** CD-ROM | disk | FTP | other *** search
/ For Beginners & Professional Hackers / cd.iso / docum / doc.all / extendm.doc < prev    next >
Encoding:
Text File  |  1979-12-31  |  11.9 KB  |  344 lines

  1.                 Using Extended Memory on the PC AT
  2.                 __________________________________
  3.  
  4.             Paul Thomson Dr.Dobb's Journal January 1989
  5.  
  6.  The PC AT BIOS contains a service - service 87h of interrupt 15h - forcopying
  7.  memory in protected mode, thereby allowing you to copy memory anywhere in the
  8.  16-MByte address range or the 80286.This means that you can copy memory from
  9.  real-mode memory to extended memory amd back again.Before calling this servi-
  10.  ce routine,however,you must set up a data structure for protected-mode opera-
  11.  tion.This structure is called a global descriptor table.It contains six des-
  12.  criptors, each with 8 bytes.Two of these are segment descriptors that descri-
  13.  be the source and target byffers.The rest of the descriptors that will be
  14.  initialized by the BIOS routine.The 8-byte segment descriptors are shown in
  15.  Table 1.
  16.  
  17.  Before calling the service routine,you must set up the registers as shown in
  18.  Table 2.
  19.  
  20.  There is also another interrupt 15h service - service 88h - which is useful
  21.  for extended memory.Service 88h returns the number of Kbytes of extended me-
  22.  mory (which starts at 0x100000) in AX.Since service 88h will not return an
  23.  error when accessing nonexistent memory,service 88h can be used to determine
  24.  if the move will involve valid memory locations.
  25.  
  26.  Listing One shows a Microsft C (compact or large model) version of the move
  27.  routine (movphy),the top of memory routine (getext),and a test routine (main)
  28.  while Listing Two is an assembly language version movphy will copy memory
  29.  in 64K-byte chunks given the source and destination addresses in 24-bit format
  30.  getext,which must be called once (before movphy is called for the first time)
  31.  sets up a static variable with the maximum physical address of extended memory.
  32.  The test copies a string between extended and real-mode memory to show that
  33.  the routine is working correctly.An error can be discovered be checking the
  34.  routine return code (AX in C, AH in the assembler routine).Before you use the
  35.  program, check that your extended memory is not occypied by VDISK;the program
  36.  can wipe out your virtual disk files and/or render VDISK unusable.
  37.  
  38.  
  39.  Table 1: Segment descriptor formats
  40.  ___________________________________
  41.  
  42.  Descriptor              Format
  43.  __________              ______
  44.  
  45.  16 bits                 Null : Reserved for future use
  46.  
  47.   8 bits                 Access rights byte:Contains attribute flags for
  48.                          the segment
  49.  
  50.  24 bits                 Physical address:Any real mode address must be conver-
  51.                          ted to a 24 bit physical address by the following
  52.                          formula: (segreg*16)+offset
  53.  
  54.  16 bits                 Segment length in bytes:Words to transfer*2
  55.  
  56.  
  57.  Table 2: Setup for registers
  58.  ____________________________
  59.  
  60.  
  61.          AH            = 87H
  62.          ES:SI         = Real mode address of global descriptor table
  63.          CX            = Count of words to copy
  64.  
  65.  
  66.  
  67.  Listing One
  68.  ___________
  69.  
  70. /***
  71.  *** ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES OF THE PCAT.
  72.  ***     COMPILE USING MICROSOFT C V4.0, LARGE OR COMPACT MODEL
  73.  ***/
  74.  
  75. #include <stdio.h>
  76. #include <dos.h>
  77.  
  78. #define PHYS(s)  (((long)FP_SEG(s) << 4) + FP_OFS(s))   /* CALC PHYS ADDR */
  79. #define BUFSZ 16                                        /* BUF SIZE IN BYTES */
  80. #define PHY_ADDR 0x100000L                              /* BEG OF EXT MEMORY */
  81.  
  82. char *buf="ORIGINAL MESSAGE";
  83.  
  84. /* TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK */
  85. main()
  86. {
  87.   extsize();
  88.   puts(buf);
  89.   movphy(PHY_ADDR,PHYS(buf),BUFSZ/2);       /* MOVE TO EXTENDED MEMORY */
  90.   sprintf(buf,"XXXXXXXXXXXXXXXXXX");        /* OVERWRITE BUFFER */
  91.   puts(buf);
  92.   movphy(PHYS(buf),PHY_ADDR,BUFSZ/2);       /* MOVE BACK FROM EXTENDED MEM */
  93.   puts(buf);
  94. }
  95.  
  96. static long maxext;               /* HOLDS MAX ADDRESS OF EXTEBDED MEMORY */
  97. extsize()
  98. {
  99.  
  100.      union REGS r;
  101.  
  102.      r.h.ah = 0x88;
  103.      int86(0x15,&r,&r);           /* RETURNS SIZE OF EXTENDED MEM IN KBYTES */
  104.      maxext = (r.x.ax + 1024L)*1024; /* FIND TOP OF EXTENDED MEMORY */
  105. }
  106.  
  107. /* MOVE MEMORY USING PHYSICAL ADDRESSES */
  108. movphy(target,source,wcount)
  109. unsigned long target;             /* PHYSICAL 24 BIT TARGET ADDRESS */
  110. unsigned long source;             /* PHYSICAL 24 BIT SOURCE ADDRESS */
  111. int wcount;                       /* 16 BIT COUNT OF WORDS TO MOVE 0 -32767 */
  112. {
  113.     int bcount;
  114.     char gdt[48];              /* GLOBAL DESCRIPTOR TABLE (6 DESCRIPTORS * 8)*/
  115.     char *g = gdt;             /* POINTER TP gdt FOR MACROS FP_SEG & FP_OFF */
  116.     union REGS r;              /* HOLDS REGISTER VALUE FOR int86x CALL */
  117.     struct SREGS s;            /* HOLDS SEG REGISTER VALUES FOR int86x CALL */
  118.  
  119.     if(wcount <= 0)            /* CHECK FOR WORD COUNT TOO BIG OR 0 */
  120.        return(wcount);
  121.     bcount = wcount*2;         /* SIZE IN BYTES TO MOVE */
  122.  
  123.     if(target+bcount >= maxext || source+bcount >= maxext)
  124.        return(4);
  125.  
  126.     /* DESCRIPTORS 0 AND 1 ARE DUMMIES (NULL) */
  127.     gdt[0]=gdt[1]=gdt[2]=gdt[3]=gdt[4]=gdt[5]=gdt[6]=gdt[7]=0;
  128.     gdt[8]=gdt[9]=gdt[10]=gdt[11]=gdt[12]=gdt[13]=gdt[14]=gdt[15]=0;
  129.  
  130.     /* DESCRIPTOR 2: SOURCE */
  131.     gdt[16] = bcount;                 /* BYTE COUNT */
  132.     gdt[17] = bcount>>8;
  133.     gdt[18] = source;                 /* PHYSICAL ADDRESS TO COPY FROM */
  134.     gdt[19] = source>>8;
  135.     gdt[20] = source>>16;
  136.     gdt[21] = 0x93;                   /* ACCESS RIGHT BYTE */
  137.     gdt[22] = gdt[23] = 0;            /* UNUSED ENTRIES */
  138.  
  139.     /* DESCRIPTORS 4 AND 5 ARE DUMMIES (NULL) */
  140.     gdt[32]=gdt[33]=gdt[34]=gdt[35]=gdt[36]=gdt[37]=gdt[38]=gdt[39]=0;
  141.     gdt[40]=gdt[41]=gdt[42]=gdt[43]=gdt[44]=gdt[45]=gdt[46]=gdt[47]=0;
  142.  
  143.     r.h.ah = 0x87;                    /* AH = SERVICE 0x87 */
  144.     r.x.cx = wcount;                  /* CX = COUNT OF WORDS TO TRANSFER */
  145.     s.es   = FP_SEG(g);               /* ES:SI = SEGMENT:OFFSET OF GDT */
  146.     r.x.si = FP_OFF(g);
  147.  
  148.     int86x(0x15,&r,&r,&s);            /* PERFORM BIOS INTERRUPT 0x15 */
  149.  
  150.     return(r.h.ah);                   /* RETURN STATUS:
  151.                                          0: SUCCESSFUL MOVE
  152.                                          1: RAM PARITY ERROR
  153.                                          2: EXCEPRION ERROR
  154.                                          3: ADDRESS LINE 20 FAILED
  155.                                          4: MEMORY OUT OF RANGE
  156.                                          < 0: WORD COUNT >32767
  157.                                       */
  158.  
  159.  
  160.  Listing Two
  161.  ___________
  162.  
  163. ; ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES ON THE PCAT.
  164. ; DO NOT USE THIS ROUTINE WITH A VURTUAL DISK IN EXTENDED MEMORY.
  165.  
  166. .286p                                     ;allow 286 instructions
  167. code segment
  168. assume cs:code,ds:code,es:code,ss:code
  169.  
  170. ; TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK
  171.  
  172. test proc near
  173.      mov  ax,cs                           ;allow access of data in code seg
  174.      mov  ds,ax
  175.  
  176.      call extsize                         ;find top of extended memory
  177.  
  178.      mov  dx,offset mess1                 ;print message
  179.      mov  ah,9
  180.      int  21h
  181.  
  182.      mov  dx,cs                           ;calculate phys addr from real addr
  183.                                           ;of message buf
  184.      shr  dx,12                           ;si = bits 0-15,dl = bits 15-23
  185.      mov  ax,cs
  186.      shl  ax,4
  187.      mov  si,offset mess1
  188.      add  si,ax
  189.      adc  dl,0
  190.      push si                              ;save phys address for later
  191.      push dx
  192.  
  193.      mov  dh,10h                          ;top of extended memory (100000h)
  194.      mov  di,0                            ;di = bits 0-15,dh = 16-23
  195.  
  196.      mov  cx,8                            ;size of message buf in words
  197.      call movphy                          ;move message to extended memory
  198.  
  199.      sub  bx,bx                           ;overwrite message buffer
  200. top:
  201.      mov  al,mess2[bx]
  202.      mov  mess1[bx],al
  203.      inc  bx
  204.      cmp  bx,16
  205.      jl   top
  206.      mov  dx,offset mess1
  207.  
  208.      mov  ah,9                            ;print ovewritten message buffer
  209.      int  21h
  210.  
  211.      pop  dx                              ;get phys buffer address from before
  212.      pop  di                              ;di = bits 0-15 dh = 16-23
  213.  
  214.      mov  cx,8                            ;size of message buf in words
  215.      call movphy                          ;move message back from extended mem
  216.  
  217.      mov  dx,offset mess1                 ;print restored message
  218.      mov  ah,9
  219.      int  21h
  220.  
  221.      mov  ah,4ch
  222.      int  21h
  223. test endp
  224. mess1     db 'ORIGINAL MESSAGE',0dh,0ah,'$'
  225. mess2     db 'XXXXXXXXXXXXXXXX'
  226.  
  227. ;extsize - GET PHYSICAL ADDRESS OF TOP OF EXTENDED MEMORY
  228. ;ADDRESS RETURNED IN max_hi,max-lo
  229. extsize proc near
  230.      mov  ah,88h
  231.      int  15h
  232.      mov  cx,1024
  233.      add  ax,cx
  234.      mul  cx
  235.      mov  max_hi,dl
  236.      mov  max_lo,ax
  237.      ret
  238. extsize   endp
  239. max_hi    db ?
  240. max_lo    dw ?
  241.  
  242. ;movphy - MOVE MEMORY USING PHYSICAL ADDRESSES
  243. ;CALLED WITH:
  244. ;       dh:di = physical 24 bit target address.
  245. ;       dl:si = physical 24 bit source address.
  246. ;       cx    = word count
  247. ;STATUS RETURNED IN ah:
  248. ;       0 : successful move
  249. ;       1 : RAM parity error
  250. ;       2 : exception error
  251. ;       3 : address line 20 failed
  252. ;       4 : memory out of range
  253. ;     255 : word count > 32767.
  254.  
  255. public movphy
  256. movphy proc near
  257.      push ds
  258.      mov  ax,cs                           ;allow access of gdt in code segment
  259.      mov  ds,ax
  260.      mov  es,ax                           ;es = segment of gdt for int 15h
  261.      mov  ax,cx                           ;calculate maximum target address
  262.      shl  ax,1
  263.      mov  bl,dh
  264.      add  ax,di
  265.      adc  bl,0
  266.      cmp  bl,max_hi                       ;check if target address out of range
  267.      jl   $target_ok
  268.      jg   $bad_range
  269.      cmp  ax,max_lo
  270.      jge  $bad_range
  271. $target_ok:
  272.      mov  cx,ax                           ;calculate maximum source address
  273.      shl  ax,1
  274.      mov  bl,dl
  275.      add  ax,si
  276.      adc  bl,0
  277.      cmp  bl,max_hi                       ;check if source address out of range
  278.      jl   $source_ok
  279.      jg   $bad_range
  280.      cmp  ax,max_lo
  281.      jl   $source_ok
  282. $bad_range:
  283.      mov  ah,4                            ;if accessing non-existent memory,
  284.                                           ;return error 4
  285.      jmp  $xend
  286. $source_ok:
  287.  
  288.      cmp  cx,0                            ;check for word count too big or 0
  289.      jg   $wcount_ok
  290.      mov  ax,cx                           ;return 255 if word count > 32767
  291.      jmp  $xend
  292. $wcount_ok:
  293.  
  294. ;DESCRIPTORS 0,1,4,5 ARE DUMMIES (NULL)
  295.      sub  ax,ax
  296.  
  297.      mov  gdt,ax                          ;descriptor 0
  298.      mov  gdt+2,ax
  299.      mov  gdt+4,ax
  300.      mov  gdt+6,ax
  301.  
  302.      mov  gdt+8,ax                        ;descriptor 1
  303.      mov  gdt+10,ax
  304.      mov  gdt+12,ax
  305.      mov  gdt+14,ax
  306.  
  307.      mov  gdt+32,ax                       ;descriptor 4
  308.      mov  gdt+34,ax
  309.      mov  gdt+36,ax
  310.      mov  gdt+38,ax
  311.  
  312.      mov  gdt+40,ax                       ;descriptor 5
  313.      mov  gdt+42,ax
  314.      mov  gdt+44,ax
  315.      mov  gdt+46,ax
  316.  
  317.      mov  gdt+22,ax                       ;unused entries in descriptor 2
  318.      mov  gdt+30,ax                       ;unused entries in descriptor 3
  319.  
  320.      mov  ax,cx                           ;change word count to byte count
  321.      shl  ax,1
  322.      mov  gdt+16,ax                       ;byte count descriptor 2
  323.      mov  gdt+24,ax                       ;byte count descriptor 3
  324.  
  325.      mov  gdt+18,si                       ;physical address to copy from
  326.      mov  al,dl
  327.      mov  ah,93h                          ;access right byte
  328.      mov  gdt+28,ax
  329.  
  330.      mov  ah,87h
  331.      mov  si,offset gdt                   ;es:si = segment:offset of global
  332.                                           ;descriptor table
  333.      int  15h                             ;perform move
  334. $xend:
  335.      pop  ds
  336.      ret
  337.  
  338.      gdt  dw 24 dup (?)                   ;global descriptor table
  339.  
  340. movphy endp
  341. code ends
  342. end
  343.  
  344.