-------------不用往下看力,,我实验想多了导致画蛇添足,请各位大手子根据实验报告要求编写,在此谢罪-----------------------
.
.
.
.
.
.
.
.
.
- 准备环境
略 - Demo
键盘功能主要由如下几个部分实现:
keyboard.S:接受键盘中断反馈的键盘码。
tty_io.c :二级处理输入数据
console.c :三级处理,之后打印到控制台
.
大致流程如下
keyboards(read/put_queue)------>tty_io(write_queue)—>console(asm)---->屏幕
.
按实验提示找到关键文件keyboards.S console.c tty_io.c,后面要做的修改集中于这三个文件之中。运行Bochs模拟器,在按下F头的几个按键之后发现有迫真大量(四行)状态信息输出,影响实验操作,所以先注释掉keyboards.S中第214行对show_stat的调用。
在判断不是F12的语句( cmpb $11, %al ja end_func)后添加call指令,由于没有参数,所以不需要进行其他操作
在console.c中添加如下内容
在下方的con_write函数中添加如下内容,只修改打印到控制台后的状态
cd进入linux-0.11目录,make clean一下,然后重新make,cd …返回上层,输入./run运行模拟器,效果如下
虽然已经实现基本功能,但是按下F12时会有字符L溢出显示,修改如下
即处理F12后立即结束
此外,也可以全在keyborads interrupt中处理F12事件,注册.global变量后在c中extern引用即可。
. - Phase1
实验要求键入F12激活※功能,键入学生姓名拼音,首尾字母等显示※,例如:zhangsan,显示为: ※ha※gsa※
第二部分的需求的实现比较麻烦,以我的理解来看就是每输入一个字符进行一次判断,先记录坐标和状态,若为合法的拼音声母开头字符则将其记录并加密,若其中插入了非法字符则判断中断,还原显示,直到最后一个合法的韵母结尾为之,结束这一段的更改,其中更新状态也应该被退格键这些按键触发…
.
总结一下,先设置一个状态变量status_phase来对操作状态进行判断。当没有输入&完成了一串拼音的加密&由于一些非法字符的输入中断了加密时,这个值置为0。开始正常接收输入时,这个值置为1
.
随后,设置两个变量pos_cache&recent_length来控制对缓冲区内容的读取。pos_cache记录最后一次处理开始时的缓冲区内容起始位置,每输入一个字符操作recent_length进行增减后从记录的位置开始一次遍历,先删去输入数量的字符数,再调用__asm__根据缓存重新打印字符到控制台。
.
先来看看tty对各种行为的定义
以上定义了tty 等待队列中缓冲区操作宏函数,每一个tty结构中会附带三个tty_queue,发现缓冲区是利用循环队列实现的,在进行操作时并不会直接修改其中队列的缓冲区内存,我们可以利用这一点直接对缓冲区中的内容进行读取,然后在console.c中进行修改,调用csi_p和遍历缓冲区数据并输出到控制台来操作打印出的内容。
根据我的思路主要用到的函数(删除光标处的p个字符)然后在读取并打印内容时选择根据自己设定的偏移量进行读取
.
其余可选的还有直接操作x和pos,循环调用del等,这里放一个我的简单实现版本,检测什么的只做了简单的判断,控制按键之类的也没做处理想做处理的话可以根据字符宽度调整startPos的位置与输出策略,输入的内容具体是不是拼音可以写个树做状态机自己体验一下…本人实属一条懒狗,大半夜写的逻辑比较乱,总之各位可以运行一下看看笑话,权当抛砖引玉。
.
注:按2下F12激活此模式,下图为预览效果:
替换console.c中的con_write及添加部分代码
#define START 0
#define HANDLEING 1
#define EXITED 2
static unsigned char f12Flag = 0;
static unsigned char ph1Flag = 0;
static int startedPos = 0; //record current position
static unsigned char status_phase = 0; //record display status
static int puttedCnt = 0; //record the number of input section
static unsigned char inited_phase = 0;
void changed_f12Flag(void) {
f12Flag = ++f12Flag % 2;
ph1Flag++;
if(ph1Flag == 2) {
startedPos = 0;
status_phase = EXITED;
}
}
static void print2console(const char c) {
if(!(c>31 && c<127))
return;
if (x>=video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf();
}
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (c),"m" (*(short *)pos)
);
pos += 2;
x++;
}
static void printCacheBuffer(struct tty_struct* tty) {
//restore_cur();
int k;
for(k = 0; k < puttedCnt - 1; k++) {
x--;
pos -= 2;
set_cursor();
//del();
}
//csi_P(puttedCnt - 1);
int i = startedPos, j;
for(j = 0; j < puttedCnt; j++) {
if(i+j >= TTY_BUF_SIZE)
j = (i+j) % TTY_BUF_SIZE - i;
char temp = tty->secondary.buf[i+j];
if(status_phase == HANDLEING) {
char _begin = tty->secondary.buf[i];
char _end = tty->secondary.buf[i+puttedCnt - 1];
if(temp == _begin || temp == _begin - (_begin/97)*32 ||
temp == _end || temp == _end - (_end/97)*32
)
temp = '*';
}
print2console(temp);
}
//save_cur();
}
static void phase_1_func(const int cnt, struct tty_struct * tty) {
switch(status_phase) {
case START:
puttedCnt = cnt;
break;
case HANDLEING:
puttedCnt += cnt;
break;
case EXITED:
startedPos += puttedCnt;
puttedCnt = cnt;
break;
default:
puttedCnt += cnt;
break;
}
printCacheBuffer(tty);
}
void con_write(struct tty_struct * tty)
{
int nr;
char c;
int pd = 1;
nr = CHARS(tty->write_q);
while (nr--) {
GETCH(tty->write_q,c);
switch(state) {
case 0:
if (c>31 && c<127) {
if((c>64&&c<91) || (c>96&&c<123)) {
if(f12Flag)
c = '*';
if(ph1Flag) {
if(status_phase == START) {
status_phase = HANDLEING;
}
else if(status_phase == EXITED) {
if(inited_phase)
startedPos += 1;
else
inited_phase = 1;
status_phase = START;
}
}
pd = 0;
} else if(status_phase == HANDLEING)
status_phase = EXITED;
if(ph1Flag == 2) {
phase_1_func(1, tty);
} else {
startedPos = (++startedPos) % TTY_BUF_SIZE;
print2console(c);
}
} 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;
}
}
if(pd)
status_phase = EXITED;
}
set_cursor();
}