Win32控制台程序写的游戏

请教一位C语言高手(关于TC中编写键盘测试程序的DOS中断问题)

奖励分:50-结算时间:2006-10-4 20:55。

我现在在编一个键盘测试软件(tc),这些键我都可以测试,但是只有那些特殊的键,比如WINDOWS键,测试不了。我问过老师,老师说我会调用DOS中断,但是我不知道怎么调用DOS中断。

那个专家给我写了个例子,或者加我QQ: 11567373。

解决这个问题我要给你加分!

问题补充:只需按下键盘上的一个键,然后显示在屏幕上的模拟键盘上。现在有五个特殊键不能考。请专家帮忙解答。如何通过DOS使它们中断,然后显示出来?

发问者:克拉克086-学者II

最佳答案

PC的键盘是智能键盘,相当于一台完整的电脑。键盘中有一个Intel 8048(或8049)单片机(处理器)来管理整个键盘上的字符键、功能键、控制键和组合键。当键盘上的某个按键被按下时,键盘上的处理器首先向电脑主机发出硬件中断请求,然后将该按键的扫描码以串行方式传输给电脑主机。在硬件中断的作用下,电脑主机调用INT 09H硬件中断读取键盘发送的扫描码并转换成ASCII码存储在键盘缓冲区。按下一个键发送关闭代码,松开该键时,发送断开代码。键盘处理中断程序从键盘I/O端口(端口地址为60H)读取一个字节的数据。如果读取数据的第七位是1,则表示该键已被释放(发送断开码)。如果第七位为0,表示按键被按下(发送关闭码),数据位0-6为0。键盘上的每个按键对应一个扫码,根据扫码可以唯一确定一个按键。键盘缓冲区位于0040:001EH -4000:003EH之间的BIOS数据区,长度为34字节,为FIFO循环队列。使用PC原有的键盘处理程序可以很方便的处理键盘,但是因为调用BIOS,所以响应比较慢。另外,当我们要同时处理几个键的时候(比如同时按下向上箭头键和向左箭头键来对角移动),原来的键盘中断程序是不能满足要求的,所以需要编写一个适合我们要求的键盘中断程序。

编写一个新的键盘中断程序来完成以下工作:

1.进入键盘中断程序。

2.从键盘I/O口60H读取一个字节的键码,存储在一个全局变量中,供主程序处理,或者将键码存储在数据表中。

3.读取控制寄存器61H,并在82h内完成一次OR运算。

4.将结果写回控制寄存器端口61H。

5.用7fh对控制寄存器完成一个AND运算,从而复位键盘触发器,告诉硬件已经处理了一个键,可以读取下一个键。

6.复位中断控制器8259,并向端口20h写入一个20h。

7.退出键盘中断程序。

先定义一组宏常量记录键值,包括128键盘扫描码:

#define KEY_A 0x1E

#define KEY_B 0x30

#define KEY_C 0x2e

#define KEY_D 0x20

#define KEY_E 0x12

#define KEY_F 0x21

#define KEY_G 0x22

#define KEY_H 0x23

#define KEY_I 0x17

#define KEY_J 0x24

#define KEY_K 0x25

#define KEY_L 0x26

#define KEY_M 0x32

#define KEY_N 0x31

#define KEY_O 0x18

#define KEY_P 0x19

#define KEY_Q 0x10

#define KEY_R 0x13

#define KEY_S 0x1f

#define KEY_T 0x14

#define KEY_U 0x16

#define KEY_V 0x2f

#define KEY_W 0x11

#define KEY_X 0x2d

#define KEY_Y 0x15

#define KEY_Z 0x2c

#define KEY_1 0x02

#定义关键字_2 0x03

#定义关键字_3 0x04

#定义关键字_4 0x05

#定义关键字_5 0x06

#定义关键字_6 0x07

#定义关键字_7 0x08

#定义关键字_8 0x09

#定义键_9 0

#define KEY_0 0x0b

#define KEY_DASH 0x0c /* _- */

#define KEY_EQUAL 0x0d /* += */

# define KEY _ lbrack 0x 1a/* {[*/

# define KEY _ rbrack 0x 1b/* }]*/

# define KEY _分号0x 27/*:;*/

# define KEY _ RQUOTE 0x 28/* ' */

#define KEY_LQUOTE 0x29 /* ~` */

# define KEY _ PERIOD 0x 33/* & gt;。*/

# define KEY _ COMMA 0x 34/* & lt;, */

#define KEY_SLASH 0x35 /*?/ */

# define KEY _反斜杠0x2b /* |\ */

#define KEY_F1 0x3b

#define KEY_F2 0x3c

#define KEY_F3 0x3d

#定义键_F4 0x3e

#define KEY_F5 0x3f

#定义键_F6 0x40

#定义键_F7 0x41

#定义键_F8 0x42

#定义键_F9 0x43

#define KEY_F10 0x44

#define KEY_ESC 0x01

#定义KEY_BACKSPACE 0x0e

#define KEY_TAB 0x0f

#define KEY_ENTER 0x1c

#define KEY_CONTROL 0x1d

#define KEY_LSHIFT 0x2a

#define KEY_RSHIFT 0x36

#define KEY_PRTSC 0x37

#define KEY_ALT 0x38

#定义键空间0x39

#define KEY_CAPSLOCK 0x3a

#define KEY_NUMLOCK 0x45

#define KEY_SCROLLLOCK 0x46

#define KEY_HOME 0x47

#define KEY_UP 0x48

#define KEY_PGUP 0x49

#define KEY_MINUS 0x4a

#define KEY_LEFT 0x4b

#define KEY_CENTER 0x4c

#define KEY_RIGHT 0x4d

#define KEY_PLUS 0x4e

#define KEY_END 0x4f

#define KEY_DOWN 0x50

#define KEY_PGDOWN 0x51

#define KEY_INS 0x52

#define KEY_DEL 0x53

然后定义两个字符数组来保存键盘状态:

char key_state[128],key _ pressed[128];

其中key_state[128]用于表示按键的当前状态,保存在key_pressed[128]中的值表示按下了哪些按键,1表示按下,0表示释放。

在挂起新的键盘中断之前,保存原键盘中断程序的地址,以便在程序运行后恢复。我们定义一个中断指针来存储原始地址:

void中断far(* old int 9 handler)();

1.安装新键盘中断程序的功能:

void安装键盘(void)

{

int I;

for(I = 0;我& lt128;i++)

key _ state[I]= key _ pressed[I]= 0;

old int 9 handler = get vect(9);

setvect(9,new int 9);

}

2.恢复旧键盘中断程序的功能:

键盘(void)

{

setvect(9,old int 9 handler);

}

3.新的键盘中断程序:

void远中断NewInt9(void)

{

无符号字符扫描码,temp

scan code = in portb(0x 60);

temp = inport b(0x 61);

outportb(0x61,temp | 0x 80);

outportb(0x61,temp & amp0x7f);

if(扫描码& amp0x80)

{

扫描代码和。= 0x7f

key _ state[scan code]= 0;

}

其他

{

key _ state[scan code]= 1;

key _ pressed[scan code]= 1;

}

outportb(0x20,0x 20);

}

4.读取按键状态的函数(在游戏中调用以确定哪些按键被按下):

int GetKey(int ScanCode)

{

int res

RES = key _ state[ScanCode]| key _ pressed[ScanCode];

key _ pressed[ScanCode]= 0;

返回res

}

例如:

if(GetKey(KEY_UP))

{

....

}

用于确定是否按下向上键。

-

信息来源于网络。

-

不过有个问题,就是这个程序可能还是检测不到win键,因为win键不是键盘的标准键。

响应者:无效的昵称-二级助理12-28 19:02

其他答案*** 2

让我从这里开始:

首先,启动Quick Basic时必须添加/l参数。如果你是4.5版,输入qb/l,如果你是7.1版,输入qbx/l,在程序开头写一行:' $ include:' QB . bi '(4.5版)' $ include:' qBx.bi' (7.65433)。

QB调用中的中断:

1.中断号,输入参数和返回参数。

2.InterruptX中断号、输入参数和返回参数。

注意:如果中断号为0~255,如果鼠标为51,则参数为REGTYPE。

这些词可以得到DOS的当前版本:

将reg DIM作为RegTypeX

Regs.ax = &H3000

中断& ampH21,规则,规则

dos version $ = LTRIM $(STR $(regs . ax MOD 256))+" "+ LTRIM$(STR$(INT(Regs.ax / 256)))

下面可以得到软驱的信息:

DIM reg AS RegType

注册= & ampH100

中断和。H13,注册,注册

IF reg.ax MOD 256 & lt& gt那么0

DEF SEG = 0

N% = PEEK。H43E)

定义分段

如果N%和1 & lt;& gt0,则Count% = 1

如果N%和2 & lt& gt0那么Count% = Count% + 1

SoftDiskCount% =计数%

如果…就会结束

受访者:

我和花王有点关系,QQ: 504988247

让我从这里开始:

首先,启动Quick Basic时必须添加/l参数。如果你是4.5版,输入qb/l,如果你是7.1版,输入qbx/l,在程序开头写一行:' $ include:' QB . bi '(4.5版)' $ include:' qBx.bi' (7.65433)。

QB调用中的中断:

1.中断号,输入参数和返回参数。

2.InterruptX中断号、输入参数和返回参数。

注意:如果中断号为0~255,如果鼠标为51,则参数为REGTYPE。

这些词可以得到DOS的当前版本:

将reg DIM作为RegTypeX

Regs.ax = &H3000

中断& ampH21,规则,规则

dos version $ = LTRIM $(STR $(regs . ax MOD 256))+" "+ LTRIM$(STR$(INT(Regs.ax / 256)))

下面可以得到软驱的信息:

DIM reg AS RegType

注册= & ampH100

中断和。H13,注册,注册

IF reg.ax MOD 256 & lt& gt那么0

DEF SEG = 0

N% = PEEK。H43E)

定义分段

如果N%和1 & lt;& gt0,则Count% = 1

如果N%和2 & lt& gt0那么Count% = Count% + 1

SoftDiskCount% =计数%

如果…就会结束

被调查人:陈_ k _ y-经理四级12-27 01:45

-

PC的键盘是智能键盘,相当于一台完整的电脑。键盘中有一个Intel 8048(或8049)单片机(处理器)来管理整个键盘上的字符键、功能键、控制键和组合键。当键盘上的某个按键被按下时,键盘上的处理器首先向电脑主机发出硬件中断请求,然后将该按键的扫描码以串行方式传输给电脑主机。在硬件中断的作用下,电脑主机调用INT 09H硬件中断读取键盘发送的扫描码并转换成ASCII码存储在键盘缓冲区。按下一个键发送关闭代码,松开该键时,发送断开代码。键盘处理中断程序从键盘I/O端口(端口地址为60H)读取一个字节的数据。如果读取数据的第七位是1,则表示该键已被释放(发送断开码)。如果第七位为0,表示按键被按下(发送关闭码),数据位0-6为0。键盘上的每个按键对应一个扫码,根据扫码可以唯一确定一个按键。键盘缓冲区位于0040:001EH -4000:003EH之间的BIOS数据区,长度为34字节,为FIFO循环队列。使用PC原有的键盘处理程序可以很方便的处理键盘,但是因为调用BIOS,所以响应比较慢。另外,当我们要同时处理几个键的时候(比如同时按下向上箭头键和向左箭头键来对角移动),原来的键盘中断程序是不能满足要求的,所以需要编写一个适合我们要求的键盘中断程序。

编写一个新的键盘中断程序来完成以下工作:

1.进入键盘中断程序。

2.从键盘I/O口60H读取一个字节的键码,存储在一个全局变量中,供主程序处理,或者将键码存储在数据表中。

3.读取控制寄存器61H,并在82h内完成一次OR运算。

4.将结果写回控制寄存器端口61H。

5.用7fh对控制寄存器完成一个AND运算,从而复位键盘触发器,告诉硬件已经处理了一个键,可以读取下一个键。

6.复位中断控制器8259,并向端口20h写入一个20h。

7.退出键盘中断程序。

先定义一组宏常量记录键值,包括128键盘扫描码:

#define KEY_A 0x1E

#define KEY_B 0x30

#define KEY_C 0x2e

#define KEY_D 0x20

#define KEY_E 0x12

#define KEY_F 0x21

#define KEY_G 0x22

#define KEY_H 0x23

#define KEY_I 0x17

#define KEY_J 0x24

#define KEY_K 0x25

#define KEY_L 0x26

#define KEY_M 0x32

#define KEY_N 0x31

#define KEY_O 0x18

#define KEY_P 0x19

#define KEY_Q 0x10

#define KEY_R 0x13

#define KEY_S 0x1f

#define KEY_T 0x14

#define KEY_U 0x16

#define KEY_V 0x2f

#define KEY_W 0x11

#define KEY_X 0x2d

#define KEY_Y 0x15

#define KEY_Z 0x2c

#define KEY_1 0x02

#定义关键字_2 0x03

#定义关键字_3 0x04

#定义关键字_4 0x05

#定义关键字_5 0x06

#定义关键字_6 0x07

#定义关键字_7 0x08

#定义关键字_8 0x09

#定义键_9 0

#define KEY_0 0x0b

#define KEY_DASH 0x0c /* _- */

#define KEY_EQUAL 0x0d /* += */

# define KEY _ lbrack 0x 1a/* {[*/

# define KEY _ rbrack 0x 1b/* }]*/

# define KEY _分号0x 27/*:;*/

# define KEY _ RQUOTE 0x 28/* ' */

#define KEY_LQUOTE 0x29 /* ~` */

# define KEY _ PERIOD 0x 33/* & gt;。*/

# define KEY _ COMMA 0x 34/* & lt;, */

#define KEY_SLASH 0x35 /*?/ */

# define KEY _反斜杠0x2b /* |\ */

#define KEY_F1 0x3b

#define KEY_F2 0x3c

#define KEY_F3 0x3d

#定义键_F4 0x3e

#define KEY_F5 0x3f

#定义键_F6 0x40

#定义键_F7 0x41

#定义键_F8 0x42

#定义键_F9 0x43

#define KEY_F10 0x44

#define KEY_ESC 0x01

#定义KEY_BACKSPACE 0x0e

#define KEY_TAB 0x0f

#define KEY_ENTER 0x1c

#define KEY_CONTROL 0x1d

#define KEY_LSHIFT 0x2a

#define KEY_RSHIFT 0x36

#define KEY_PRTSC 0x37

#define KEY_ALT 0x38

#定义键空间0x39

#define KEY_CAPSLOCK 0x3a

#define KEY_NUMLOCK 0x45

#define KEY_SCROLLLOCK 0x46

#define KEY_HOME 0x47

#define KEY_UP 0x48

#define KEY_PGUP 0x49

#define KEY_MINUS 0x4a

#define KEY_LEFT 0x4b

#define KEY_CENTER 0x4c

#define KEY_RIGHT 0x4d

#define KEY_PLUS 0x4e

#define KEY_END 0x4f

#define KEY_DOWN 0x50

#define KEY_PGDOWN 0x51

#define KEY_INS 0x52

#define KEY_DEL 0x53

然后定义两个字符数组来保存键盘状态:

char key_state[128],key _ pressed[128];

其中key_state[128]用于表示按键的当前状态,保存在key_pressed[128]中的值表示按下了哪些按键,1表示按下,0表示释放。

在挂起新的键盘中断之前,保存原键盘中断程序的地址,以便在程序运行后恢复。我们定义一个中断指针来存储原始地址:

void中断far(* old int 9 handler)();

1.安装新键盘中断程序的功能:

void安装键盘(void)

{

int I;

for(I = 0;我& lt128;i++)

key _ state[I]= key _ pressed[I]= 0;

old int 9 handler = get vect(9);

setvect(9,new int 9);

}

2.恢复旧键盘中断程序的功能:

键盘(void)

{

setvect(9,old int 9 handler);

}

3.新的键盘中断程序:

void远中断NewInt9(void)

{

无符号字符扫描码,temp

scan code = in portb(0x 60);

temp = inport b(0x 61);

outportb(0x61,temp | 0x 80);

outportb(0x61,temp & amp0x7f);

if(扫描码& amp0x80)

{

扫描代码和。= 0x7f

key _ state[scan code]= 0;

}

其他

{

key _ state[scan code]= 1;

key _ pressed[scan code]= 1;

}

outportb(0x20,0x 20);

}

4.读取按键状态的函数(在游戏中调用以确定哪些按键被按下):

int GetKey(int ScanCode)

{

int res

RES = key _ state[ScanCode]| key _ pressed[ScanCode];

key _ pressed[ScanCode]= 0;

返回res

}

例如:

if(GetKey(KEY_UP))

{

....

}

用于确定是否按下向上键。