【实现在Windows下直接读写内存的方法】

1.利用Windows提供的各个段选择符标号,在C源程序中将选择符标号说明为外部变量。其对照表如下:表1

2.利用宏定义MAKELONG(段内偏移量,&段选择符标号)即可得到一个长指针。

3.经上述方法得到的指针与C语言中定义的指针是一样的。

4.如果使用的段是D000H或E000H或其它上位内存时,需改动Windows的系统配置文件SYSTEM.INI,利用字符编辑器,在[386Enh]小节中加入EmmExclude=xxxxyyyy一行,禁止Windows使用这段存储空间。值xxxx和yyyy是16位内存范围。如开发的插件占用D000H段的64K,则应加入这样一行:EmmExclude=d000-dfff。

利用这一方法,已使我们自己开发的电路板(占用D000H段),在Windows控制下成功地运行了。考虑到读者没有相应的硬件,这里以读取中断向量、计算机ROM的制造时间和对DOS用户通讯区的读写为例,详见以下程序。对于DOS用户通讯区的内容,读者可用DOS的DEBUG程序检查(D命令)和修改(E命令)。DOS的用户通讯区在0040∶00F0H处开始,共计16个字节。在修改时请注意:从0040∶00F0H开始存放可显示ASCII码字符串,并以0结尾。

;MEMORY.DEF模块定义文件

NAME

Memory

DESCRIPTION’demotrateanintergratedmenu’

EXETYPEWINDOWS

STUB’WITUB.EXE’

CODEPRELOADMOVEABLEDISCARDABLE

DATAPRELOADMOVEABLEMULTIPLE

HEAIZE1024

STACKSIZE8192

EXPORTSWndProc

/*----------

MEMORY.RC

直接读写内存的资源定义文件

----------*/

#include"memory.h"

MemoryMenuMENU

BEGIN

POPUP"取中断向量[&I]"

BEGIN

MENUITEM"int0&3h",IDM-INT03H

MENUITEM"int&10h",IDM-INT10H

MENUITEM"int&21h",IDM-INT21H

END

POPUP"ROM区域[&R]"

BEGIN

MENUITEM"制造时间[&T]",

IDM-TIME

MENUITEM"取用户通讯区[&U]",IDM-READ

MENUITEM"存用户通讯区[]",IDM-WRITE

END

MENUITEM"\a退出[&X]",

IDM-EXIT

END

/*----------

MEMORY.H

直接读写内存的头文件

----------*/

#defineIDM-INT03H101

#defineIDM-INT10H102

#defineIDM-INT21H103

#defineIDM-TIME201

#defineIDM-READ202

#defineIDM-WRITE203

#defineIDM-EXIT300

/*----------

MEMORY.C

用户对固定内存直接读写的表演程序

----------*/

#include

#include"memory.h"

#include

intPASCALWinMain(HANDLE,HANDLE,LTR,int);

longFARPASCALWndProc(HWND,UINT,UINT,LONG);

/*----WinMain()----*/

intPASCALWinMain(HANDLEhItance,HANDLEhPrevItance

,LTRlzCmdLine,intnCmdShow)

{

MSG

msg;

HWNDhWnd;

WNDCLAwndcla

if(!hPrevItance)

{

wndcla.style=CS-HREDRAW|CS-VREDRAW;

wndcla.lpfnWndProc=WndProc;

wndcla.cbClsExtra=0;

wndcla.cbWndExtra=0;

wndcla.hItance=hItance;

wndcla.hIcon=LoadIcon(NULL

,IDI-ALICATION);

wndcla.hCursor=LoadCursor(NULL,IDC-ARROW);

wndcla.hpBackground=GetStockObject(WHITE-pUSH);

wndcla.lzMenuName="MemoryMenu";

wndcla.lzClaame="直接读写存储器";

if(!RegisterCla(&wndcla))

returnFALSE;

}

hWnd=CreateWindow(

"直接读写存储器",

"直接读写存储器",

WS-OVERLAEDWINDOW,

CW-USEDEFAULT,

CW-USEDEFAULT,

CW-USEDEFAULT,

CW-USEDEFAULT,

NULL,

NULL,

hItance,

NULL);

if(!hWnd)

returnFALSE;

ShowWindow(hWnd,nCmdShow);

UpdateWindow(hWnd);

while(GetMeage(&msg,NULL,0,0))

{

TralateMeage(&msg);

DiatchMeage(&msg);

}

returnmsg.wParam;

}

/*----WndProc()----*/

longFARPASCALWndProc(HWNDhWnd,UINTmeage,UINTw

Param,LONGlParam

)

{

HDC

hDC;

HPENhOldPen,hNewPe

RECTrect;

TEXTMETRICtm;

PAINTSTRUCT

UINTi;

charStrbuf[50];

WORDfar*InterruptVector;

charfar*bio

externWORD-0000H;

externWORD-0040H;

externWORD-F000H;

switch(meage)

{

caseWM-COMMAND:

switch(wParam)

{

caseIDM-INT03H:

InterruptVector=(WORDfar*)MAKELONG(0,&-0000H);

wrintf(Strbuf,"向量地址:X:XH\n",

*(InterruptVector 0x06),

*(InterruptVector 0x07));

MeageBox(hWnd,Strbuf,

"int03h",MB-OK|MB-ICOTOP);

return0;

caseIDM-INT10H:

InterruptVector=(WORDfar*)MAKELONG(0,&-0000H);

wrintf(Strbuf,"向量地址:X:XH\n",*(InterruptVecto

r 0x20),

*(InterruptVector 0x21));

MeageBox(hWnd,Strbuf,

"int10h",MBOK|MB-ICOTOP);

return0;

caseIDM-INT21H:

InterruptVector=(WORDfar*)MAKELONG(0,&-0000H);

wrintf(Strbuf,"向量地址:X:XH\n",*(InterruptVecto

r 0x42),

*(InterruptVector 0x43));

MeageBox(hWnd,Strbuf,"int21h",MB-OK|MB-ICOTOP);

return0;

caseIDM-TIME:

bios=(charfar*)MAKELONG(0xfff5,&-F000H);

MeageBox(hWnd,bios,

"ROM制造时间",MB-OK|MB-ICOTOP);

return0;

caseIDM-READ:

bios=(charfar*)MAKELONG(0xF0,&-0040H);

MeageBox(hWnd,bios,

"取用户通讯区内容",MB-OK|MB-ICOTOP);

return0;

caseIDM-WRITE:

bios=(charfar*)MAKELONG(0xF0,&-0040H);

for(i=0;i<10;i )*(bios i)=’A’ i;*(bios 10)=0;

MeageBox(hWnd,"Write’A’-’J’charstring!",

"写用户通讯区内容",MB-OK|MB-ICOTOP);

return0;

caseIDM-EXIT:

SendMeage(hWnd,WM-CLOSE,0,0);

return0;

}

peak;

caseWM-DESTROY:

PostQuitMeage(0);

return0;

default:

peak;

}

returnDefWindowProc(hWnd,meage,wParam,lParam);

}

/*----EndProgrammingofDemo----*/