`
897371388
  • 浏览: 530049 次
文章分类
社区版块
存档分类
最新评论

字符显示的控制

 
阅读更多

第六次实验可以算是很简单的一次了,只要知道了0.11如何响应你的键盘事件,一切问题都迎刃而解了。实现这个实验的方法有很多,我的也是仅供参考,其他方法可能还有些是涉及到修改汇编代码的。

首先,要做的就是在linux-0.11\kernel\chr_drv文件夹下的keyboard.S文件中,将第245行的call show_stat注释掉或者删掉都可以。在原来的代码中,按下F12便是调用了keyboard.S的call show_stat,而call show_stat又调用了其他的一些方法,是用来显示进程信息的。

原始的keyboard.S文件,方便大家查找call show_stat的位置。

func:
	pushl %eax
	pushl %ecx
	pushl %edx
	call show_stat
	popl %edx
	popl %ecx
	popl %eax
	subb $0x3B,%al
	jb end_func
	cmpb $9,%al
	jbe ok_func
	subb $18,%al
	cmpb $10,%al
	jb end_func
	cmpb $11,%al
	ja end_func
接着,进入正题,我们需要知道操作系统对于F12的按下,所获取的code是什么。为了知道这,我采用了很简单但也很暴力的方法,用printk方法来打印。最后根据打印的信息,我们可以知道F12的按下相当于三个键的按下,分别是21,97和76。在完成了这些准备工作之后,可以进入编写对F12按下的响应捕获事件了。

值得说明的一点是,对于这三个键值的捕获利用到了状态机的思想。虽然当时并不了解状态机,但是确实在编程中使用了这样的思想,也即必须在连续获取21,97和76才认为是F12的按下。

在linux-0.11\kernel\chr_drv文件夹下的tty_io.c文件

首先声明了这些标志位

int flag = -1;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0

在copy_to_cooked函数里实现我们的获取键值为21,97,和76.在获取了这三个键之后设置标志位flag

void copy_to_cooked(struct tty_struct * tty)
{
	signed char c;
	
	while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
		GETCH(tty->read_q,c);
		/*printk("\nI am %d\n",c);*/
		
		if (c == 27)
		{
			flag1 = 1;
		}
		else if (flag1 == 1 && c == 91 && flag2 == 0)
		{
			flag2 = 1;
		}
		else if (flag1 == 1 && flag2 == 1 && c == 91)
		{
			flag3 = 1;
		}
		else if (flag1 == 1 && flag2 == 1 && flag3 == 1 && c == 76)
		{
			flag *= -1;
			continue ;
		}
		else 
		{
			flag1 = 0;
			flag2 = 0;
			flag3 = 0;
		}

		if (c==13)
			if (I_CRNL(tty))
				c=10;
			else if (I_NOCR(tty))
				continue;
			else ;
		else if (c==10 && I_NLCR(tty))
			c=13;
		if (I_UCLC(tty))
			c=tolower(c);
		if (L_CANON(tty)) {
			if (c==KILL_CHAR(tty)) {
				/* deal with killing the input line */
				while(!(EMPTY(tty->secondary) ||
				        (c=LAST(tty->secondary))==10 ||
				        c==EOF_CHAR(tty))) {call show_stat
					if (L_ECHO(tty)) {
						if (c<32)
							PUTCH(127,tty->write_q);
						PUTCH(127,tty->write_q);
						tty->write(tty);
					}
					DEC(tty->secondary.head);
				}
				continue;
			}
			if (c==ERASE_CHAR(tty)) {
				if (EMPTY(tty->secondary) ||
				   (c=LAST(tty->secondary))==10 ||
				   c==EOF_CHAR(tty))
					continue;
				if (L_ECHO(tty)) {
					if (c<32)
						PUTCH(127,tty->write_q);
					PUTCH(127,tty->write_q);
					tty->write(tty);
				}
				DEC(tty->secondary.head);
				continue;
			}
			if (c==STOP_CHAR(tty)) {
				tty->stopped=1;
				continue;
			}
			if (c==START_CHAR(tty)) {
				tty->stopped=0;
				continue;
			}
		}
		if (L_ISIG(tty)) {
			if (c==INTR_CHAR(tty)) {
				tty_intr(tty,INTMASK);
				continue;
			}
			if (c==QUIT_CHAR(tty)) {
				tty_intr(tty,QUITMASK);
				continue;
			}
		}
		if (c==10 || c==EOF_CHAR(tty))
			tty->secondary.data++;
		if (L_ECHO(tty)) {
			if (c==10) {
				PUTCH(10,tty->write_q);
				PUTCH(13,tty->write_q);
			} else if (c<32) {
				if (L_ECHOCTL(tty)) {
					PUTCH('^',tty->write_q);
					PUTCH(c+64,tty->write_q);
				}
			} else
				PUTCH(c,tty->write_q);
			tty->write(tty);
		}
		/*printk("\nI am %d after..\n",c);*/
		PUTCH(c,tty->secondary);
	}
	wake_up(&tty->secondary.proc_list);
}

在linux-0.11\kernel\chr_drv文件夹下的console.c文件

设置了一个外部的变量flag,表明是否是F12的按下

extern int flag;

在con_write方法中对字母和数字替换为“*”即可。


void con_write(struct tty_struct * tty)
{
	int nr;
	char c;
	nr = CHARS(tty->write_q);
	while (nr--) {
		GETCH(tty->write_q,c);
		
		switch(state) {
			case 0:
				if (c>31 && c<127) {
					if (x>=video_num_columns) {
						x -= video_num_columns;
						pos -= video_size_row;
						lf();
					}
					if (((c>='A' && c<='Z')||(c>='a' && c<='z')) && flag == 1)
						c = '*';
					__asm__("movb attr,%%ah\n\t"
						"movw %%ax,%1\n\t"
						::"a" (c),"m" (*(short *)pos)
						);
					pos += 2;
					x++;
				} else if (c==27)
					state=1;
				else if (c==10 || c==11 || c==12)
					lf();
				else if (c==13)
					cr();
				else if (c==ERASE_CHAR(tty))
					del();
				else if (c==8) {
					if (x) {
						x--;
						pos -= 2;
					}
				} else if (c==9) {
					c=8-(x&7);
					x += c;
					pos += c<<1;
					if (x>video_num_columns) {
						x -= video_num_columns;
						pos -= video_size_row;
						lf();
					}
					c=9;
				} else if (c==7)
					sysbeep();
				break;
			case 1:
				state=0;
				if (c=='[')
					state=2;
				else if (c=='E')
					gotoxy(0,y+1);
				else if (c=='M')
					ri();
				else if (c=='D')
					lf();
				else if (c=='Z')
					respond(tty);
				else if (x=='7')
					save_cur();
				else if (x=='8')
					restore_cur();
				break;
			case 2:
				for(npar=0;npar<NPAR;npar++)
					par[npar]=0;
				npar=0;
				state=3;
				if ((ques=(c=='?')))
					break;
			case 3:
				if (c==';' && npar<NPAR-1) {
					npar++;
					break;
				} else if (c>='0' && c<='9') {
					par[npar]=10*par[npar]+c-'0';
					break;
				} else state=4;
			case 4:
				state=0;
				switch(c) {
					case 'G': case '`':
						if (par[0]) par[0]--;
						gotoxy(par[0],y);
						break;
					case 'A':
						if (!par[0]) par[0]++;
						gotoxy(x,y-par[0]);
						break;
					case 'B': case 'e':
						if (!par[0]) par[0]++;
						gotoxy(x,y+par[0]);
						break;
					case 'C': case 'a':
						if (!par[0]) par[0]++;
						gotoxy(x+par[0],y);
						break;
					case 'D':
						if (!par[0]) par[0]++;
						gotoxy(x-par[0],y);
						break;
					case 'E':
						if (!par[0]) par[0]++;
						gotoxy(0,y+par[0]);
						break;
					case 'F':
						if (!par[0]) par[0]++;
						gotoxy(0,y-par[0]);
						break;
					case 'd':
						if (par[0]) par[0]--;
						gotoxy(x,par[0]);
						break;
					case 'H': case 'f':
						if (par[0]) par[0]--;
						if (par[1]) par[1]--;
						gotoxy(par[1],par[0]);
						break;
					case 'J':
						csi_J(par[0]);
						break;
					case 'K':
						csi_K(par[0]);
						break;
					case 'L':
						csi_L(par[0]);
						break;
					case 'M':
						csi_M(par[0]);
						break;
					case 'P':
						csi_P(par[0]);
						break;
					case '@':
						csi_at(par[0]);
						break;
					case 'm':
						csi_m();
						break;
					case 'r':
						if (par[0]) par[0]--;
						if (!par[1]) par[1] = video_num_lines;
						if (par[0] < par[1] &&
						    par[1] <= video_num_lines) {
							top=par[0];
							bottom=par[1];
						}
						break;
					case 's':
						save_cur();
						break;
					case 'u':
						restore_cur();
						break;
				}
		}
	}
	set_cursor();
}

最后说明的一点是,上述的修改并不会对向文件输出的字符进行修改,只过滤了向终端输出的字符。





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics