实现在Windows下直接读写内存的方法[1]

[入库:2005年8月28日] [更新:2007年3月24日]

本文简介:

windows以它一致的图形用户界面、完善的内存管理等特点,已被广大用户所接受,但在windows下,计算机已运行在保护模式,虽然windows已提供了一整套的内存管理函数,用户还是不可访问指定地址的内存,致使许多中、小型企业开发的计算机插件无法在windows下使用,因为编写驱动程序是很费事的。他们仅希望能直接读、写电路板所占的内存即可。本文介绍的是在windows 3.1下,用borland c++ 3.1编程环境,实现用户对内存直接读写的方法,读者不难将它移植到其它编程语言。

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'demonstrate an intergrated menu'
exetypewindows
stub'winstub.exe'
codepreload moveable discardable
datapreload moveable multiple
heapsize1024
stacksize8192
exportswndproc
/*----------
memory.rc
直接读写内存的资源定义文件
----------*/
#include "memory.h"
memorymenu menu
begin
popup"取中断向量[&i]"
begin
menuitem "int 0&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 "存用户通讯区[&s]", idm-write
end
menuitem "\a退出[&x]",
idm-exit
end
/*----------
memory.h
直接读写内存的头文件
----------*/
#define idm-int03h 101
#define idm-int10h102
#define idm-int21h103
#define idm-time201
#define idm-read202
#define idm-write203
#define idm-exit300
/*----------
memory.c
用户对固定内存直接读写的表演程序
----------*/
#include<windows.h>
#include "memory.h"
#include <dos.h>
int pascal winmain(handle,handle,lpstr,int);
long far pascal wndproc(hwnd,uint,uint,long);
/*----winmain()----*/
int pascal winmain(handle hinstance,handle hprevinstance
,lpstr lpszcmdline,int ncmdshow)
{
msg
msg;
hwnd hwnd;
wndclass wndclass;
if (! hprevinstance)
{
wndclass.style=cs-hredraw | cs-vredraw;
wndclass.lpfnwndproc=wndproc;
wndclass.cbclsextra=0;
wndclass.cbwndextra=0;
wndclass.hinstance=hinstance;
wndclass.hicon=loadicon(null,idi-application);
wndclass.hcursor=loadcursor(null,idc-arrow);
wndclass.hbrbackground=getstockobject(white-brush);
wndclass.lpszmenuname="memorymenu";
wndclass.lpszclassname="直接读写存储器";
if (! registerclass (&wndclass))
return false;
}
hwnd=createwindow(
"直接读写存储器",
"直接读写存储器",
ws-overlappedwindow,
cw-usedefault,
cw-usedefault,
cw-usedefault,
cw-usedefault,
null,
null,
hinstance,
null);
if (! hwnd)
return false;
showwindow(hwnd, ncmdshow);
updatewindow(hwnd);
while (getmessage(&msg,n

ull,0,0))
{
translatemessage(&msg);
dispatchmessage(&msg);
}
return msg.wparam;
}
/*----wndproc()----*/
long far pascal wndproc (hwnd hwnd, uint message, uint w
param,long lparam
)
{
hdc
hdc;
hpen holdpen,hnewpen;
rectrect;
textmetrictm;
paintstructps;
uint i;
char strbuf[50];
word far * interruptvector;
char far * bios;
extern word-0000h;
extern word-0040h;
extern word-f000h;
switch (message)
{
case wm-command:
switch (wparam)
{
case idm-int03h:
interruptvector=(word far *)makelong(0,&-0000h);
wsprintf(strbuf,"向量地址:%04x:%04xh\n",
*(interruptvector+0x06),
*(interruptvector+0x07));
messagebox (hwnd,strbuf,
"int 03h", mb-ok | mb-iconstop);
return 0;
case idm-int10h:
interruptvector=(word far *)makelong(0,&-0000h);
wsprintf(strbuf,"向量地址:%04x:%04xh\n",*(interruptvecto
r+0x20),
*(interruptvector+0x21));
messagebox (hwnd,strbuf,
"int 10h",mb ok | mb-iconstop);
return 0;
case idm-int21h:
interruptvector=(word far *)makelong(0,&-0000h);
wsprintf(strbuf,"向量地址:%04x:%04xh\n",*(interruptvecto
r+0x42),
*(interruptvector+0x43));
messagebox (hwnd,strbuf,"int 21h",mb-ok | mb-iconstop);
return 0;
case idm-time:
bios=(char far *)makelong(0xfff5,&-f000h);
messagebox (hwnd,bios,
"rom制造时间",mb-ok | mb-iconstop);
return 0;
case idm-read:
bios=(char far *)makelong(0xf0,&-0040h);
messagebox (hwnd,bios,
"取用户通讯区内容",mb-ok | mb-iconstop);
return 0;
case idm-write:
bios=(char far *)makelong(0xf0,&-0040h);
for(i=0;i<10;i++) *(bios+i)='a'+i; *(bios+10)=0;
messagebox (hwnd,"write 'a'-'j'char string !",
"写用户通讯区内容",mb-ok | mb-iconstop);
return 0;
case idm-exit:
sendmessage (hwnd,wm-close,0,0);
return 0;
}
break;
case wm-destroy:
postquitmessage (0);
return 0;
default:
break;
}
return defwindowproc (hwnd,message,wparam,lparam);
}

本文关键:实现在Windows下直接读写内存的方法
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top