中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 在DOS下如何用C实现键盘某键的按下
« [1] [2] »
作者:
标题: 在DOS下如何用C实现键盘某键的按下 上一主题 | 下一主题
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『楼 主』:  在DOS下如何用C实现键盘某键的按下

例如,我希望用C语言写一程序实现CAPS LOCK,NUM LOCK,SCR LOCK键的按下,然后对应的灯会自动亮起
大虾们知道的帮帮忙,小弟谢谢了,很急!!!

2006-12-24 04:04
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
bill2241
新手上路





积分 2
发帖 1
注册 2006-3-11
状态 离线
『第 2 楼』:  

你可以自己去测试啦
使用BIOSDISK函数可以
使用BIOS中断~~~~
测试扫描码~~就可以啦

2006-12-24 10:28
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
zyl910
中级用户





积分 282
发帖 126
注册 2006-5-17
状态 离线
『第 3 楼』:  

BIOS内存区:

   40:17   byte   Keyboard flag byte 0 (see KB FLAGS)
      |7|6|5|4|3|2|1|0| keyboard flag byte 0
       | | | | | | | `--- right shift key depressed
       | | | | | | `---- left shift key depressed
       | | | | | `----- CTRL key depressed
       | | | | `------ ALT key depressed
       | | | `------- scroll-lock is active
       | | `-------- num-lock is active
       | `--------- caps-lock is active
       `---------- insert is active
   40:18   byte   Keyboard flag byte 1 (see KB FLAGS)
      |7|6|5|4|3|2|1|0| keyboard flag byte
       | | | | | | | `--- left CTRL key depressed
       | | | | | | `---- left ALT key depressed
       | | | | | `----- system key depressed and held
       | | | | `------ suspend key has been toggled
       | | | `------- scroll lock key is depressed
       | | `-------- num-lock key is depressed
       | `--------- caps-lock key is depressed
       `---------- insert key is depressed



人类存在的目的就是试图理解人类为何存在
2006-12-24 23:08
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 4 楼』:  

感谢大家,问题已经解决了~我是直接从0x00400017H中进行位操作来实现的
但现在我又面临一个新的测试,还是关于键盘测试的,有些特殊的键盘上面有一些很特别的键,如SONY笔记本中一些键盘上有播放/暂停,快近,后退,停止键等,这些键在WINDOWS下是可以的,现在我要在DOS下进行测试,在DOS中按下肯定是没有任何反应的,但是在BIOS中肯定有相应的响应,或者有相应的扫描码被存入到键盘缓冲区中,但是我现在不知道如何去抓,请教下有没有谁做过这样的测试.
用BC和TC都可以,如果有汇编也可以,不过我汇编不是熟

[ Last edited by hebecoco on 2006-12-25 at 03:16 PM ]

2006-12-25 22:07
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 5 楼』:  

我有试过用bioskey()函数,抓不出来
现在主要的问题是我不知道在哪个地址位按那几个特殊键有变化,如果能知道哪个位的话,我直接用peek读出来就可以了,我有试过从键盘缓冲区0x401c中去读,也读不出来
有知道的麻烦告知下,谢谢了~~~~

2006-12-26 00:05
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
AlwaysInherit
初级用户

征(武林高手||搞安全 ..



积分 112
发帖 46
注册 2005-9-28
状态 离线
『第 6 楼』:  

wikipedia ps/2 connector -> http://www.computer-engineering.org/ps2keyboard/
-> http://www.computer-engineering.org/ps2keyboard/scancodes2.html

2006-12-26 02:00
查看资料  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 7 楼』:  

AlwaysInherit
       感谢你提供的资料,我大概的看了一遍,其中提到MAKE/BREAK的问题,一个代表是键的按下,一个代表是键的释放,但我很想知道这2个值可以从从哪里读出来,是从0X64中吗?

2006-12-26 03:13
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 8 楼』:  

还是要用到中断?我对中断还不是很明白,如果用中断那又是如何实现该值的获取

2006-12-26 03:17
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
AlwaysInherit
初级用户

征(武林高手||搞安全 ..



积分 112
发帖 46
注册 2005-9-28
状态 离线
『第 9 楼』:  

kb 的 scancode ?? 那好像在kb buffer 中

我也不是清楚,你是问怎样读出kb 的 scancode吗? 还是加对应的scancode 到kb buffer中?

2006-12-26 03:55
查看资料  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 10 楼』:  

我有试过在kb buffer中抓,但抓不出来,kb buffer的地址为0x0040001CH
现在我是我想抓make code 和break code;

2006-12-26 04:10
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
AlwaysInherit
初级用户

征(武林高手||搞安全 ..



积分 112
发帖 46
注册 2005-9-28
状态 离线
『第 11 楼』:  

看样子,我误会你的意思!

http://www.nondot.org/sabre/os/articles/HumanInterfaceDevices/

有programming with kb tutorial,与一些接口用法

我觉得应该是处理 kb interrupt , 那个 BIOS data areas 中 40H:17H 是 IBM PC 时代定下的。 不能"看" ps/2  全部 data pin 进来的 data 。至于他家os 有没有定出一些比较方便的接口,我不清楚!看有没有人能顶上

[ Last edited by AlwaysInherit on 2006-12-26 at 05:04 AM ]

2006-12-26 04:53
查看资料  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 12 楼』:  

我得花点时间消化下,还是非常感谢你提供的资料

2006-12-26 06:16
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 13 楼』:  

虽然理解了很多,但是还是没办法读那几个播放键,我有试过把键盘缓冲区里的值全部读出来,然后去按那几个BUTONN,发现BUFFER里面的32个字节没有任何变化,就是说那几个BUTONN是根本没有经过键盘BUFFER.
但现在那几个BUTONN在资料里面有相应的make code 和break code,那肯定是可以读出来的,只是不知道在哪里读,这步才是最关键的,

2006-12-26 21:25
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hebecoco
初级用户





积分 63
发帖 25
注册 2006-12-24
状态 离线
『第 14 楼』:  

有人提到用键盘中断,本人还不是很会用中断,但我想就算是用中断,也要知道用什么值去中断,在DOS下,CPU是否又会响应这个中断,如果说CPU没做出相应的响应,我也是没办法去测的,
用中断我觉得模拟一个键的按下可能容易点,但要去测的话实现起来应该不是很简单

请教各路高手,有没有解决的办法,最主要的就是解决怎么去读那些BUTONN的make code和break code,

2006-12-26 21:32
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
zyl910
中级用户





积分 282
发帖 126
注册 2006-5-17
状态 离线
『第 15 楼』:  

那几个播放键不是PC标准,不会进键盘缓冲区的
你只有挂接键盘中断(IRQ1,INT9),从60h端口得到按键扫描码

而且注意,由于那几个播放键不是PC标准
所以在Windows系统不会为这几个按键触发中断的(还包括Win键、快捷菜单键等等)
也就是说,只有纯DOS下才能得知那几个按键的按下与释放



以前写的一个专用来研究按键扫描码的小程序:
#include <stdio.h>
#include <conio.h>
#include <dos.h>

#ifdef __cplusplus
    #define __CPPARGS ...
#else
    #define __CPPARGS
#endif


#define        MAXKEYQUEUE        0x40
static        char        kqQueue[MAXKEYQUEUE];        // 队列
static        int        kqFirst = 0;        // 指向首个数据
static        int        kqLast = 0;        // 指向首个空位
static        int        kqCount = 0;        // 该队列有多少元素

#define KSC_PRESS        0x80
#define KSC_DATAMASK        0x7F
#define        KSC_EXTEND        0xE0

#define        KSC_ESC        1

void interrupt get_out(__CPPARGS);    /* interrupt prototype */

void interrupt (*oldfunc)(__CPPARGS); /* interrupt function pointer */


int main(void)
{
        unsigned char        byKey;
        int        iEscCount=0;

        puts("Esc*3: Exit\n");

        /* save the old interrupt */
        oldfunc  = _dos_getvect(9);

        /* install interrupt handler */
        _dos_setvect(9,get_out);

        /* do nothing */
        while (iEscCount < 3){
                /* show key queue */
                while(kqCount > 0){
                        /* get curent ScanCode */
                        __asm        cli;
                                byKey = kqQueue[kqFirst++];
                                if (kqFirst >= MAXKEYQUEUE)        kqFirst -= MAXKEYQUEUE;
                                kqCount--;
                        __asm        sti;

                        /* show */
                        printf("%X\t", byKey);

                        /* check Esc */
                        if (byKey & KSC_PRESS)        {
                                if (KSC_ESC == (byKey & KSC_DATAMASK))        {
                                        iEscCount++;
                                        if (2 == iEscCount){
                                                clrscr();
                                        }
                                }else        {
                                        iEscCount = 0;
                                }
                        }
                }
        };

        /* restore to original interrupt routine */
        _dos_setvect(9,oldfunc);

        puts("Success");
        return 0;
}

void interrupt get_out(__CPPARGS)
{
        {
                unsigned char byKey;

                /* get ScanCode */
                byKey = inportb(0x60);

                /* add to key queue */
                if (kqCount < MAXKEYQUEUE){
                        kqQueue[kqLast++] = byKey;
                        if (kqLast >= MAXKEYQUEUE)        kqLast -= MAXKEYQUEUE;
                        kqCount++;
                }
        }
        oldfunc(__CPPARGS);
}


   此帖被 +2 点积分    点击查看详情   
评分人:【 hebecoco 分数: +2  时间:2007-5-9 15:48




人类存在的目的就是试图理解人类为何存在
2006-12-26 22:22
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: