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 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----*/