home *** CD-ROM | disk | FTP | other *** search
- _USING EXTENDED MEMORY ON THE PC AT_
-
- by Paul Thomson
-
- [LISTING ONE]
-
- /***
- *** ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES ON THE PCAT.
- *** WRITTEN BY PAUL THOMSON.
- *** COMPILE USING MICROSOFT C V4.0, LARGE OR COMPACT MODEL.
- *** DO NOT USE THIS ROUTINE WITH A VIRTUAL DISK IN EXTENDED MEMORY.
- ***/
-
- #include <stdio.h>
- #include <dos.h>
-
- #define PHYS(s) (((long)FP_SEG(s) << 4) + FP_OFF(s)) /* CALC PHYS ADDR */
- #define BUFSZ 16 /* BUF SIZE IN BYTES */
- #define PHY_ADDR 0x100000L /* BEG OF EXT MEMORY */
-
- char *buf="ORIGINAL MESSAGE";
-
- /* TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK */
- main()
- {
- extsize();
- puts(buf);
- movphy(PHY_ADDR, PHYS(buf), BUFSZ/2); /* MOVE TO EXTENDED MEMORY */
- sprintf(buf, "XXXXXXXXXXXXXXXX"); /* OVERWRITE BUFFER */
- puts(buf);
- movphy(PHYS(buf), PHY_ADDR, BUFSZ/2); /* MOVE BACK FROM EXTENDED MEMORY */
- puts(buf);
- }
-
- static long maxext; /* HOLDS MAX ADDRESS OF EXTENDED MEMORY */
- extsize()
- {
- union REGS r;
-
- r.h.ah = 0x88;
- int86(0x15, &r, &r); /* RETURNS SIZE OF EXTENDED MEM IN KBYTES */
- maxext = (r.x.ax + 1024L)*1024; /* FIND TOP OF EXTENDED MEMORY */
- }
-
- /* MOVE MEMORY USING PHYSICAL ADDRESSES */
- movphy(target, source, wcount)
- unsigned long target; /* PHYSICAL 24 BIT TARGET ADDRESS */
- unsigned long source; /* PHYSICAL 24 BIT SOURCE ADDRESS */
- int wcount; /* 16 BIT COUNT OF WORDS TO MOVE 0 - 32767 */
- {
- int bcount;
- char gdt[48]; /* GLOBAL DESCRIPTOR TABLE (6 DESCRIPTORS*8) */
- char *g = gdt; /* POINTER TO gdt FOR MACROS FP_SEG & FP_OFF */
- union REGS r; /* HOLDS REGISTER VALUES FOR int86x CALL */
- struct SREGS s; /* HOLDS SEG REGISTER VALUES FOR int86x CALL */
-
- if(wcount <= 0) /* CHECK FOR WORD COUNT TOO BIG OR 0 */
- return(wcount);
- bcount = wcount*2; /* SIZE IN BYTES TO MOVE */
-
- if(target+bcount >= maxext || source+bcount >= maxext)
- return(4);
-
- /* DESCRIPTORS 0 AND 1 ARE DUMMIES (NULL) */
- gdt[0]=gdt[1]=gdt[2]=gdt[3]=gdt[4]=gdt[5]=gdt[6]=gdt[7]=0;
- gdt[8]=gdt[9]=gdt[10]=gdt[11]=gdt[12]=gdt[13]=gdt[14]=gdt[15]=0;
-
- /* DESCRIPTOR 2: SOURCE */
- gdt[16] = bcount; /* BYTE COUNT */
- gdt[17] = bcount>>8;
- gdt[18] = source; /* PHYSICAL ADDRESS TO COPY FROM */
- gdt[19] = source>>8;
- gdt[20] = source>>16;
- gdt[21] = 0x93; /* ACCESS RIGHTS BYTE */
- gdt[22] = gdt[23] = 0; /* UNUSED ENTRIES */
-
- /* DESCRIPTOR 3: TARGET */
- gdt[24] = bcount; /* BYTE COUNT */
- gdt[25] = bcount>>8;
- gdt[26] = target; /* PHYSICAL ADDRESS TO COPY TO */
- gdt[27] = target>>8;
- gdt[28] = target>>16;
- gdt[29] = 0x93; /* ACCESS RIGHTS BYTE */
- gdt[30] = gdt[31] = 0; /* UNUSED ENTRIES */
-
- /* DESCRIPTORS 4 AND 5 ARE DUMMIES (NULL) */
- gdt[32]=gdt[33]=gdt[34]=gdt[35]=gdt[36]=gdt[37]=gdt[38]=gdt[39]=0;
- gdt[40]=gdt[41]=gdt[42]=gdt[43]=gdt[44]=gdt[45]=gdt[46]=gdt[47]=0;
-
- r.h.ah = 0x87; /* AH = SERVICE 0x87 */
- r.x.cx = wcount; /* CX = COUNT OF WORDS TO TRANSFER */
- s.es = FP_SEG(g); /* ES:SI = SEGMENT:OFFSET OF GDT */
- r.x.si = FP_OFF(g);
-
- int86x(0x15, &r, &r, &s); /* PERFORM BIOS INTERRUPT 0x15 */
-
- return(r.h.ah);
- /* RETURN STATUS:
- 0: SUCCESSFUL MOVE
- 1: RAM PARITY ERROR
- 2: EXCEPTION ERROR
- 3: ADDRESS LINE 20 FAILED
- 4: MEMORY OUT OF RANGE
- <0: WORD COUNT > 32767 */
- }
-
-
-
- [LISTING TWO]
-
- ; ROUTINE FOR COPYING MEMORY USING PHYSICAL ADDRESSES ON THE PCAT.
- ; WRITTEN BY PAUL THOMSON.
- ; DO NOT USE THIS ROUTINE WITH A VIRTUAL DISK IN EXTENDED MEMORY.
-
-
- .286p ; ALLOW 286 INSTRUCTIONS
- code segment
- assume cs:code,ds:code,es:code,ss:code
-
- ; TEST MOVPHY BY COPYING A MESSAGE TO EXTENDED MEMORY AND BACK
- test proc near
- mov ax,cs ; ALLOW ACCESS OF DATA IN CODE SEG
- mov ds,ax
-
- call extsize ; FIND TOP OF EXTENDED MEMORY
-
- mov dx,offset mess1 ; PRINT MESSAGE
- mov ah,9
- int 21h
-
- mov dx,cs ; CALCULATE PHYS ADDR FROM REAL ADDR OF MESSAGE BUF
- shr dx,12 ; SI = BITS 0-15, DL = BITS 16-23
- mov ax,cs
- shl ax,4
- mov si,offset mess1
- add si,ax
- adc dl,0
- push si ; SAVE PHYS ADDRESS FOR LATER
- push dx
-
- mov dh,10h ; TOP OF EXTENDED MEMORY (100000h)
- mov di,0 ; DI = BITS 0-15, DH = 16-23
-
- mov cx,8 ; SIZE OF MESSAGE BUF IN WORDS
- call movphy ; MOVE MESSAGE TO EXTENDED MEMORY
-
- sub bx,bx ; OVERWRITE MESSAGE BUFFER
- top:
- mov al,mess2[bx]
- mov mess1[bx],al
- inc bx
- cmp bx,16
- jl top
- mov dx,offset mess1
-
- mov ah,9 ; PRINT OVERWRITTEN MESSAGE BUFFER
- int 21h
-
- pop dx ; GET PHYS BUFFER ADDRESS FROM BEFORE
- pop di ; DI = BITS 0-15, DH = BITS 16-23
- mov dh,dl
-
- mov dl,10h ; TOP OF EXTENDED MEMORY (100000h)
- mov si,0 ; DI = BITS 0-15, DH = 16-23
-
- mov cx,8 ; SIZE OF MESSAGE BUF IN WORDS
- call movphy ; MOVE MESSAGE BACK FROM EXTENDED MEMORY
-
- mov dx,offset mess1 ; PRINT RESTORED MESSAGE
- mov ah,9
- int 21h
-
- mov ah,4ch ; EXIT
- int 21h
- test endp
- mess1 db 'ORIGINAL MESSAGE',0dh,0ah,'$'
- mess2 db 'XXXXXXXXXXXXXXXX'
-
- ; extsize - GET PHYSICAL ADDRESS OF TOP OF EXTENDED MEMORY
- ; ADDRESS RETURNED IN max_hi,max_lo
- extsize proc near
- mov ah,88h
- int 15h
- mov cx,1024
- add ax,cx
- mul cx
- mov max_hi,dl
- mov max_lo,ax
- ret
- extsize endp
- max_hi db ?
- max_lo dw ?
-
- ; movphy - MOVE MEMORY USING PHYSICAL ADDRESSES
- ; CALLED WITH:
- ; dh:di = physical 24 bit target address.
- ; dl:si = physical 24 bit source address.
- ; cx = word count
- ; STATUS RETURNED IN ah:
- ; 0: successful move
- ; 1: RAM parity error
- ; 2: exception error
- ; 3: address line 20 failed
- ; 4: memory out of range
- ; 255: word count > 32767
-
- public movphy
- movphy proc near
- push ds
- mov ax,cs ; ALLOW ACCESS OF gdt IN CODE SEGMENT
- mov ds,ax
- mov es,ax ; es = SEGMENT OF gdt FOR int 15h
-
- mov ax,cx ; CALCULATE MAXIMUM TARGET ADDRESS
- shl ax,1
- mov bl,dh
- add ax,di
- adc bl,0
- cmp bl,max_hi ; CHECK IF TARGET ADDRESS OUT OF RANGE
- jl $target_ok
- jg $bad_range
- cmp ax,max_lo
- jge $bad_range
- $target_ok:
- mov ax,cx ; CALCULATE MAXIMUM SOURCE ADDRESS
- shl ax,1
- mov bl,dl
- add ax,si
- adc bl,0
- cmp bl,max_hi ; CHECK IF SOURCE ADDRESS OUT OF RANGE
- jl $source_ok
- jg $bad_range
- cmp ax,max_lo
- jl $source_ok
- $bad_range:
- mov ah,4 ; IF ACCESSING NON-EXISTENT MEMORY, RETURN ERROR 4
- jmp $xend
- $source_ok:
-
- cmp cx,0 ; CHECK FOR WORD COUNT TOO BIG OR 0
- jg $wcount_ok
- mov ax,cx ; RETURN 255 IF WORD COUNT > 32767
- jmp $xend
- $wcount_ok:
-
- ; DESCRIPTORS 0,1,4,5 ARE DUMMIES (NULL)
- sub ax,ax
-
- mov gdt,ax ; DESCRIPTOR 0
- mov gdt+2,ax
- mov gdt+4,ax
- mov gdt+6,ax
-
- mov gdt+8,ax ; DESCRIPTOR 1
- mov gdt+10,ax
- mov gdt+12,ax
- mov gdt+14,ax
-
- mov gdt+32,ax ; DESCRIPTOR 4
- mov gdt+34,ax
- mov gdt+36,ax
- mov gdt+38,ax
-
- mov gdt+40,ax ; DESCRIPTOR 5
- mov gdt+42,ax
- mov gdt+44,ax
- mov gdt+46,ax
-
- mov gdt+22,ax ; UNUSED ENTRIES IN DESCRIPTOR 2
- mov gdt+30,ax ; UNUSED ENTRIES IN DESCRIPTOR 3
-
- mov ax,cx ; CHANGE WORD COUNT TO BYTE COUNT
- shl ax,1
- mov gdt+16,ax ; BYTE COUNT DESCRIPTOR 2
- mov gdt+24,ax ; BYTE COUNT DESCRIPTOR 3
-
- mov gdt+18,si ; PHYSICAL ADDRESS TO COPY FROM
- mov al,dl
- mov ah,93h ; ACCESS RIGHTS BYTE
- mov gdt+20,ax
-
- mov gdt+26,di ; PHYSICAL ADDRESS TO COPY TO
- mov al,dh
- mov ah,93h ; ACCESS RIGHTS BYTE
- mov gdt+28,ax
-
- ; MAKE DOS CALL
- mov ah,87h ; SELECT SERVICE 87h
- mov si,offset gdt ; ES:SI = SEGMENT:OFFSET OF GLOBAL DESCRIPTOR TABLE
- int 15h ; PERFORM MEMORY MOVE
- $xend:
- pop ds
- ret
-
- gdt dw 24 dup(?) ; GLOBAL DESCRIPTOR TABLE
-
- movphy endp
- code ends
- end
-
-