天天看點

CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------

-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------

.

.

.

.

.

.

.

.

.

  1. 準備環境

  2. 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的調用。

    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    在判斷不是F12的語句( cmpb $11, %al ja end_func)後添加call指令,由于沒有參數,是以不需要進行其他操作
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    在console.c中添加如下内容
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    在下方的con_write函數中添加如下内容,隻修改列印到控制台後的狀态
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    cd進入linux-0.11目錄,make clean一下,然後重新make,cd …傳回上層,輸入./run運作模拟器,效果如下
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    雖然已經實作基本功能,但是按下F12時會有字元L溢出顯示,修改如下
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------

    即處理F12後立即結束

    此外,也可以全在keyborads interrupt中處理F12事件,注冊.global變量後在c中extern引用即可。

    .

  3. Phase1

    實驗要求鍵入F12激活※功能,鍵入學生姓名拼音,首尾字母等顯示※,例如:zhangsan,顯示為: ※ha※gsa※

    第二部分的需求的實作比較麻煩,以我的了解來看就是每輸入一個字元進行一次判斷,先記錄坐标和狀态,若為合法的拼音聲母開頭字元則将其記錄并加密,若其中插入了非法字元則判斷中斷,還原顯示,直到最後一個合法的韻母結尾為之,結束這一段的更改,其中更新狀态也應該被倒退鍵這些按鍵觸發…

    .

    總結一下,先設定一個狀态變量status_phase來對操作狀态進行判斷。當沒有輸入&完成了一串拼音的加密&由于一些非法字元的輸入中斷了加密時,這個值置為0。開始正常接收輸入時,這個值置為1

    .

    随後,設定兩個變量pos_cache&recent_length來控制對緩沖區内容的讀取。pos_cache記錄最後一次處理開始時的緩沖區内容起始位置,每輸入一個字元操作recent_length進行增減後從記錄的位置開始一次周遊,先删去輸入數量的字元數,再調用__asm__根據緩存重新列印字元到控制台。

    .

    先來看看tty對各種行為的定義

    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    以上定義了tty 等待隊列中緩沖區操作宏函數,每一個tty結構中會附帶三個tty_queue,發現緩沖區是利用循環隊列實作的,在進行操作時并不會直接修改其中隊列的緩沖區記憶體,我們可以利用這一點直接對緩沖區中的内容進行讀取,然後在console.c中進行修改,調用csi_p和周遊緩沖區資料并輸出到控制台來操作列印出的内容。
    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------

    根據我的思路主要用到的函數(删除光标處的p個字元)然後在讀取并列印内容時選擇根據自己設定的偏移量進行讀取

    .

    其餘可選的還有直接操作x和pos,循環調用del等,這裡放一個我的簡單實作版本,檢測什麼的隻做了簡單的判斷,控制按鍵之類的也沒做處理想做處理的話可以根據字元寬度調整startPos的位置與輸出政策,輸入的内容具體是不是拼音可以寫個樹做狀态機自己體驗一下…本人實屬一條懶狗 ,大半夜寫的邏輯比較亂,總之各位可以運作一下看看笑話,權當抛磚引玉。

    .

    注:按2下F12激活此模式,下圖為預覽效果:

    CSAPP LAB4 鍵盤驅動程式的分析與修改(謝罪)-------------不用往下看力,,我實驗想多了導緻畫蛇添足,請各位大手子根據實驗報告要求編寫,在此謝罪-----------------------
    替換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();
}
           

繼續閱讀