home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1989 / 01 / extmem.asc < prev    next >
Text File  |  1989-01-02  |  9KB  |  301 lines

  1. _USING EXTENDED MEMORY ON THE PC AT_
  2.  
  3. by Paul Thomson
  4.  
  5. [LISTING ONE]
  6.  
  7. /***
  8.  *** ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES ON THE PCAT.
  9.  *** WRITTEN BY PAUL THOMSON.
  10.  *** COMPILE USING MICROSOFT C V4.0, LARGE OR COMPACT MODEL.
  11.  *** DO NOT USE THIS ROUTINE WITH A VIRTUAL DISK IN EXTENDED MEMORY.
  12.  ***/
  13.  
  14. #include <stdio.h>
  15. #include <dos.h>
  16.  
  17. #define PHYS(s) (((long)FP_SEG(s) << 4) + FP_OFF(s))    /* CALC PHYS ADDR */
  18. #define BUFSZ 16                                        /* BUF SIZE IN BYTES */
  19. #define PHY_ADDR 0x100000L                              /* BEG OF EXT MEMORY */
  20.  
  21. char *buf="ORIGINAL MESSAGE";
  22.  
  23. /* TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK */
  24. main()
  25. {
  26.     extsize();
  27.     puts(buf);
  28.     movphy(PHY_ADDR, PHYS(buf), BUFSZ/2);   /* MOVE TO EXTENDED MEMORY */
  29.     sprintf(buf, "XXXXXXXXXXXXXXXX");       /* OVERWRITE BUFFER */
  30.     puts(buf);
  31.     movphy(PHYS(buf), PHY_ADDR, BUFSZ/2);   /* MOVE BACK FROM EXTENDED MEMORY */
  32.     puts(buf);
  33. }
  34.  
  35. static long maxext;                 /* HOLDS MAX ADDRESS OF EXTENDED MEMORY */
  36. extsize()
  37. {
  38.     union REGS r;
  39.  
  40.     r.h.ah = 0x88;
  41.     int86(0x15, &r, &r);            /* RETURNS SIZE OF EXTENDED MEM IN KBYTES */
  42.     maxext = (r.x.ax + 1024L)*1024; /* FIND TOP OF EXTENDED MEMORY */
  43. }
  44.  
  45. /* MOVE MEMORY USING PHYSICAL ADDRESSES */
  46. movphy(target, source, wcount)
  47. unsigned long target;           /* PHYSICAL 24 BIT TARGET ADDRESS */
  48. unsigned long source;           /* PHYSICAL 24 BIT SOURCE ADDRESS */
  49. int wcount;                     /* 16 BIT COUNT OF WORDS TO MOVE 0 - 32767 */
  50. {
  51.     int bcount;
  52.     char gdt[48];               /* GLOBAL DESCRIPTOR TABLE (6 DESCRIPTORS*8) */
  53.     char *g = gdt;              /* POINTER TO gdt FOR MACROS FP_SEG & FP_OFF */
  54.     union REGS r;               /* HOLDS REGISTER VALUES FOR int86x CALL */
  55.     struct SREGS s;             /* HOLDS SEG REGISTER VALUES FOR int86x CALL */
  56.  
  57.     if(wcount <= 0)             /* CHECK FOR WORD COUNT TOO BIG OR 0 */
  58.         return(wcount);
  59.     bcount = wcount*2;          /* SIZE IN BYTES TO MOVE */
  60.  
  61.     if(target+bcount >= maxext || source+bcount >= maxext)
  62.         return(4);
  63.  
  64.     /* DESCRIPTORS 0 AND 1 ARE DUMMIES (NULL) */
  65.     gdt[0]=gdt[1]=gdt[2]=gdt[3]=gdt[4]=gdt[5]=gdt[6]=gdt[7]=0;
  66.     gdt[8]=gdt[9]=gdt[10]=gdt[11]=gdt[12]=gdt[13]=gdt[14]=gdt[15]=0;
  67.  
  68.     /* DESCRIPTOR 2: SOURCE */
  69.     gdt[16] = bcount;           /* BYTE COUNT */
  70.     gdt[17] = bcount>>8;
  71.     gdt[18] = source;           /* PHYSICAL ADDRESS TO COPY FROM */
  72.     gdt[19] = source>>8;
  73.     gdt[20] = source>>16;
  74.     gdt[21] = 0x93;             /* ACCESS RIGHTS BYTE */
  75.     gdt[22] = gdt[23] = 0;      /* UNUSED ENTRIES */
  76.  
  77.     /* DESCRIPTOR 3: TARGET */
  78.     gdt[24] = bcount;           /* BYTE COUNT */
  79.     gdt[25] = bcount>>8;
  80.     gdt[26] = target;           /* PHYSICAL ADDRESS TO COPY TO */
  81.     gdt[27] = target>>8;
  82.     gdt[28] = target>>16;
  83.     gdt[29] = 0x93;             /* ACCESS RIGHTS BYTE */
  84.     gdt[30] = gdt[31] = 0;      /* UNUSED ENTRIES */
  85.  
  86.     /* DESCRIPTORS 4 AND 5 ARE DUMMIES (NULL) */
  87.     gdt[32]=gdt[33]=gdt[34]=gdt[35]=gdt[36]=gdt[37]=gdt[38]=gdt[39]=0;
  88.     gdt[40]=gdt[41]=gdt[42]=gdt[43]=gdt[44]=gdt[45]=gdt[46]=gdt[47]=0;
  89.  
  90.     r.h.ah = 0x87;              /* AH = SERVICE 0x87 */
  91.     r.x.cx = wcount;            /* CX = COUNT OF WORDS TO TRANSFER */
  92.     s.es = FP_SEG(g);           /* ES:SI = SEGMENT:OFFSET OF GDT */
  93.     r.x.si = FP_OFF(g);
  94.  
  95.     int86x(0x15, &r, &r, &s);   /* PERFORM BIOS INTERRUPT 0x15 */
  96.  
  97.     return(r.h.ah);
  98.                                 /* RETURN STATUS:
  99.                                     0: SUCCESSFUL MOVE
  100.                                     1: RAM PARITY ERROR
  101.                                     2: EXCEPTION ERROR
  102.                                     3: ADDRESS LINE 20 FAILED
  103.                                     4: MEMORY OUT OF RANGE
  104.                                     <0: WORD COUNT > 32767 */
  105. }
  106.  
  107.  
  108.  
  109. [LISTING TWO]
  110.  
  111. ; ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES ON THE PCAT.
  112. ; WRITTEN BY PAUL THOMSON.
  113. ; DO NOT USE THIS ROUTINE WITH A VIRTUAL DISK IN EXTENDED MEMORY.
  114.  
  115.  
  116. .286p                       ; ALLOW 286 INSTRUCTIONS
  117. code segment
  118. assume cs:code,ds:code,es:code,ss:code
  119.  
  120. ; TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK
  121. test proc near
  122.     mov     ax,cs           ; ALLOW ACCESS OF DATA IN CODE SEG
  123.     mov     ds,ax
  124.  
  125.     call    extsize        ; FIND TOP OF EXTENDED MEMORY
  126.  
  127.     mov     dx,offset mess1 ; PRINT MESSAGE
  128.     mov     ah,9
  129.     int     21h
  130.  
  131.     mov     dx,cs           ; CALCULATE PHYS ADDR FROM REAL ADDR OF MESSAGE BUF
  132.     shr     dx,12           ; SI = BITS 0-15, DL = BITS 16-23
  133.     mov     ax,cs
  134.     shl     ax,4
  135.     mov     si,offset mess1
  136.     add     si,ax
  137.     adc     dl,0
  138.     push    si              ; SAVE PHYS ADDRESS FOR LATER
  139.     push    dx
  140.  
  141.     mov     dh,10h          ; TOP OF EXTENDED MEMORY (100000h)
  142.     mov     di,0            ; DI = BITS 0-15, DH = 16-23
  143.  
  144.     mov     cx,8            ; SIZE OF MESSAGE BUF IN WORDS
  145.     call    movphy          ; MOVE MESSAGE TO EXTENDED MEMORY
  146.  
  147.     sub     bx,bx           ; OVERWRITE MESSAGE BUFFER
  148. top:
  149.     mov     al,mess2[bx]
  150.     mov     mess1[bx],al
  151.     inc     bx
  152.     cmp     bx,16
  153.     jl      top
  154.     mov     dx,offset mess1
  155.  
  156.     mov     ah,9            ; PRINT OVERWRITTEN MESSAGE BUFFER
  157.     int     21h
  158.  
  159.     pop     dx              ; GET PHYS BUFFER ADDRESS FROM BEFORE
  160.     pop     di              ; DI = BITS 0-15, DH = BITS 16-23
  161.     mov     dh,dl
  162.  
  163.     mov     dl,10h          ; TOP OF EXTENDED MEMORY (100000h)
  164.     mov     si,0            ; DI = BITS 0-15, DH = 16-23
  165.  
  166.     mov     cx,8            ; SIZE OF MESSAGE BUF IN WORDS
  167.     call    movphy          ; MOVE MESSAGE BACK FROM EXTENDED MEMORY
  168.  
  169.     mov     dx,offset mess1 ; PRINT RESTORED MESSAGE
  170.     mov     ah,9
  171.     int     21h
  172.  
  173.     mov     ah,4ch          ; EXIT
  174.     int     21h
  175. test endp
  176. mess1       db 'ORIGINAL MESSAGE',0dh,0ah,'$'
  177. mess2       db 'XXXXXXXXXXXXXXXX'
  178.  
  179. ; extsize - GET PHYSICAL ADDRESS OF TOP OF EXTENDED MEMORY
  180. ; ADDRESS RETURNED IN max_hi,max_lo
  181. extsize proc near
  182.     mov     ah,88h
  183.     int     15h
  184.     mov     cx,1024
  185.     add     ax,cx
  186.     mul     cx
  187.     mov     max_hi,dl
  188.     mov     max_lo,ax
  189.     ret
  190. extsize endp
  191. max_hi      db ?
  192. max_lo      dw ?
  193.  
  194. ; movphy - MOVE MEMORY USING PHYSICAL ADDRESSES
  195. ; CALLED WITH:
  196. ;   dh:di = physical 24 bit target address.
  197. ;   dl:si = physical 24 bit source address.
  198. ;   cx = word count
  199. ; STATUS RETURNED IN ah:
  200. ;   0: successful move
  201. ;   1: RAM parity error
  202. ;   2: exception error
  203. ;   3: address line 20 failed
  204. ;   4: memory out of range
  205. ;   255: word count > 32767
  206.  
  207. public movphy
  208. movphy proc near
  209.     push    ds
  210.     mov     ax,cs           ; ALLOW ACCESS OF gdt IN CODE SEGMENT
  211.     mov     ds,ax
  212.     mov     es,ax           ; es = SEGMENT OF gdt FOR int 15h
  213.  
  214.     mov     ax,cx           ; CALCULATE MAXIMUM TARGET ADDRESS
  215.     shl     ax,1
  216.     mov     bl,dh
  217.     add     ax,di
  218.     adc     bl,0
  219.     cmp     bl,max_hi       ; CHECK IF TARGET ADDRESS OUT OF RANGE
  220.     jl      $target_ok
  221.     jg      $bad_range
  222.     cmp     ax,max_lo
  223.     jge     $bad_range
  224. $target_ok:
  225.     mov     ax,cx           ; CALCULATE MAXIMUM SOURCE ADDRESS
  226.     shl     ax,1
  227.     mov     bl,dl
  228.     add     ax,si
  229.     adc     bl,0
  230.     cmp     bl,max_hi       ; CHECK IF SOURCE ADDRESS OUT OF RANGE
  231.     jl      $source_ok
  232.     jg      $bad_range
  233.     cmp     ax,max_lo
  234.     jl      $source_ok
  235. $bad_range:
  236.     mov     ah,4            ; IF ACCESSING NON-EXISTENT MEMORY, RETURN ERROR 4
  237.     jmp     $xend
  238. $source_ok:
  239.  
  240.     cmp     cx,0            ; CHECK FOR WORD COUNT TOO BIG OR 0
  241.     jg      $wcount_ok
  242.     mov     ax,cx           ; RETURN 255 IF WORD COUNT > 32767
  243.     jmp     $xend
  244. $wcount_ok:
  245.  
  246. ;   DESCRIPTORS 0,1,4,5 ARE DUMMIES (NULL)
  247.     sub     ax,ax
  248.  
  249.     mov     gdt,ax          ; DESCRIPTOR 0
  250.     mov     gdt+2,ax
  251.     mov     gdt+4,ax
  252.     mov     gdt+6,ax
  253.  
  254.     mov     gdt+8,ax        ; DESCRIPTOR 1
  255.     mov     gdt+10,ax
  256.     mov     gdt+12,ax
  257.     mov     gdt+14,ax
  258.  
  259.     mov     gdt+32,ax       ; DESCRIPTOR 4
  260.     mov     gdt+34,ax
  261.     mov     gdt+36,ax
  262.     mov     gdt+38,ax
  263.  
  264.     mov     gdt+40,ax       ; DESCRIPTOR 5
  265.     mov     gdt+42,ax
  266.     mov     gdt+44,ax
  267.     mov     gdt+46,ax
  268.  
  269.     mov     gdt+22,ax       ; UNUSED ENTRIES IN DESCRIPTOR 2
  270.     mov     gdt+30,ax       ; UNUSED ENTRIES IN DESCRIPTOR 3
  271.  
  272.     mov     ax,cx           ; CHANGE WORD COUNT TO BYTE COUNT
  273.     shl     ax,1
  274.     mov     gdt+16,ax       ; BYTE COUNT DESCRIPTOR 2
  275.     mov     gdt+24,ax       ; BYTE COUNT DESCRIPTOR 3
  276.  
  277.     mov     gdt+18,si       ; PHYSICAL ADDRESS TO COPY FROM
  278.     mov     al,dl
  279.     mov     ah,93h          ; ACCESS RIGHTS BYTE
  280.     mov     gdt+20,ax
  281.  
  282.     mov     gdt+26,di       ; PHYSICAL ADDRESS TO COPY TO
  283.     mov     al,dh
  284.     mov     ah,93h          ; ACCESS RIGHTS BYTE
  285.     mov     gdt+28,ax
  286.  
  287. ;   MAKE DOS CALL
  288.     mov     ah,87h          ; SELECT SERVICE 87h
  289.     mov     si,offset gdt   ; ES:SI = SEGMENT:OFFSET OF GLOBAL DESCRIPTOR TABLE
  290.     int     15h             ; PERFORM MEMORY MOVE
  291. $xend:
  292.     pop     ds
  293.     ret 
  294.  
  295.     gdt dw 24 dup(?)        ; GLOBAL DESCRIPTOR TABLE
  296.  
  297. movphy  endp
  298. code ends
  299. end
  300.  
  301.