home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8901.arc
/
EXTMEM.ASC
< prev
next >
Wrap
Text File
|
1989-01-02
|
9KB
|
301 lines
_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