计算机系统实验4

每日一言

I’m not going to lie to you, Vegeta, although the answer may be difficult for you to hear. This is the truth. Goku devoted his life to protecting the lives of other. Because of his selflessness, when he died, he was allowed to keep his body and travel to King Kai’s Planet. You, on the other hand, have spent your life in pursuit of your own selfish desires. You’ve caused too much pain. When you die, you will not receive the same reward. – Piccolo
from Dragon Ball Z

准备工作

要进行linux0.11 的内核编译,首先我们需要搭建好实验环境,安装好实验所需的所有工具。

对于虚拟机的选择,我选择了VMware Workstation 17 pro,该版本较新,在网络上容易找到下载资源,而且对于高版本的win11 系统支持较好,不易出现程序崩溃等问题。

操作系统按照要求选择了ubuntu-16.04.1-desktop-i386,在ubuntu官方网址进行下载:Ubuntu 16.04 LTS (Xenial Xerus)

准备好这两样东西后我们就可以开始进行实验环境的配置了。

安装Ubuntu 16.04.1

在VMware中,我们选择新建虚拟机,并选择我们下载好的ubuntu 16.04.1 的iso文件,然后点击下一步:

1733535007305

然后我们输入系统的名称(可以随便取),用户名(可以随便取),密码(需要记住,登录系统用)。点击下一步:

1733535174472

之后的选项一路下一步即可,直到最后这个页面:

1733535328904

我们点击自定义硬件,为了让虚拟机流畅一些,我们可以将虚拟机可利用核心数提升到16:

1733535441780

网络设置选择自定义模式,并且选择VMnet0:

1733536208642

现在我们就可以关闭当前窗口,然后点击完成,等待虚拟机开机。

在此期间,我们可以点击VMware 左上角的编辑->虚拟网络编辑器:

1733536329986

我们再点击右下角的更改设置,来自定义配置虚拟网络。

1733536372550

按照如下选项配置NMnet0:

1733536459703

本地DHCP(动态主机配置协议)是一种网络管理协议,用于自动分配IP地址和其他网络配置参数(如子网掩码、网关和DNS服务器)给网络中的设备(如计算机、打印机和其他网络设备)。本地DHCP服务器通常在局域网(LAN)中运行,简化了网络管理员的工作,它可以自动管理和分配IP地址,而不需要手动配置每个设备。

这样我们的虚拟机中就正常拥有网络啦。

1733536647468

安装构建环境

现在的虚拟机中的文件与我们的windows 是隔离的,我们如果想要向其中传输文件并不方便,这里我采用建立sfpt连接的方式进行文件管理。首先我们在桌面右键打开终端:

1733537694956

首先输入 sudo su 然后输入你的用户密码,我们进入root用户。

1733537797838

然后按顺序输入 apt updateapt install openssh-server , 安装ssh服务。SSH (Secure Shell) 是一种网络协议,用于在计算机之间建立安全的加密连接。通过 SSH,你可以安全地远程登录到另一台计算机,执行命令、传输文件,就像直接坐在那台计算机前一样。

最后我们按顺序输入:systemctl start sshsystemctl enable ssh 开启ssh服务并且将ssh加入开机自启动。

我们可以通过命令:systemctl status ssh 来检查服务的运行状态:

1733538179702

如上图就是运行成功!

最后的最后我们通过:ifconfig 来查看我们虚拟机系统的ip地址。

1733538357357

我们输入对应信息,通过sfpt协议登录服务端

1733538833022

1733538890281

即可对虚拟机中的文件进行管理。

然后我们将实验所需的文件全部传到虚拟机中即可。同时将以下内容保存在install.sh文件中一并传到虚拟机中:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# 安装GCC 3.4

wget http://old-releases.ubuntu.com/ubuntu/pool/universe/g/gcc-3.4/gcc-3.4-base_3.4.6-6ubuntu3_i386.deb
sudo dpkg -i gcc-3.4-base_3.4.6-6ubuntu3_i386.deb
wget http://old-releases.ubuntu.com/ubuntu/pool/universe/g/gcc-3.4/cpp-3.4_3.4.6-6ubuntu3_i386.deb
sudo dpkg -i cpp-3.4_3.4.6-6ubuntu3_i386.deb
wget http://old-releases.ubuntu.com/ubuntu/pool/universe/g/gcc-3.4/gcc-3.4_3.4.6-6ubuntu3_i386.deb
sudo dpkg -i gcc-3.4_3.4.6-6ubuntu3_i386.deb
wget http://old-releases.ubuntu.com/ubuntu/pool/universe/g/gcc-3.4/libstdc++6-dev_3.4.6-6ubuntu3_i386.deb
sudo dpkg --force-depends -i libstdc++6-dev_3.4.6-6ubuntu3_i386.deb
wget http://old-releases.ubuntu.com/ubuntu/pool/universe/g/gcc-3.4/g++-3.4_3.4.6-6ubuntu3_i386.deb
sudo dpkg -i g++-3.4_3.4.6-6ubuntu3_i386.deb

该脚本为一键安装所有所需的工具。

使用方法为:在终端中打开install.sh所在的目录,然后按顺序执行:

1
2
chmod +x install.sh //赋予文件执行权限
./install.sh

中途可能会需要输入一次root权限的密码。

1733540117346

等待自动安装结束即可。这里我们安装的工具,都是为了后续自己make linux所需要的工具。

所以我们打开实验的Linux路径,然后尝试输入make all 来构建项目:

1733540397291

但是这里又报了一个错,提示我们缺少工具,那么我们再继续安装缺少的工具:bin86

1733540474020

现在再次输入 make cleanmake clean 就可以构建成功啦

1733540552316

实现ppt演示功能

当键盘按F12健,字母显示变为*,再按F12,复原。

修改keyboard.S

根据PPT中的提示,我们在keyboard.S中需要进行如下修改。

按下F12调用自定义函数

首先查看key_table函数中的内容,根据键盘扫描码与调用函数的对应关系:

1733553052223

我们可以知道当按下键盘上的F12后,会调用func函数,那么我们接下来查看func函数中的内容:

1733553300302

根据内核注释书终端内容,我们知道按下F12后,会一直执行到图中位置并且并不会跳转,那么我们就在该语句的下面增加call 来调用一个我们自定义的函数。

修改完成后如下:

1
2
3
4
jb end_func
cmpb $11,%al
ja end_func
call change_f12Flag

然后我们在文件顶部的声明

1
.globl keyboard_interrupt

添加我们自己引入的全局变量,改为:

1
.globl keyboard_interrupt,f12Flag

修改console.c

我们在console.c中找到合适位置,添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//fix:从外部引入全局变量f12Flag,用于判断是否按下F12
extern int f12Flag=0;
//fix:创建函数change_f12Flag,用于改变f12Flag的值
void change_f12Flag(void)
{
switch(f12Flag)
{
case 1: //如果f12Flag为1,则将其改为0
f12Flag=0;
break;
case 0: //如果f12Flag为0,则将其改为1
f12Flag=1;
break;
}
}

这样就实现了我们按下f12后,改变f12Flag 的状态的功能。

接着需要更改con_write() 中的内容:

1733554177400

这一段代码控制输入的是一个普通字符时,将这个字符写到显示内存pos的地址处,那么我们则在将字符打印到屏幕前,增加一个判断条件。修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (c>31 && c<127) {
if (x>=video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf();
}
if(f12Flag && ((c>64&&c<91)||(c>96&&c<123)))//f12有效时显示*
c='*';
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (c),"m" (*(short *)pos)
);
pos += 2;
x++;
}

修改效果

根据PPT中的操作修改后,我们依次 make cleanmake all./run 结果得到的效果如下:

1733554704377

按下f12后,会先输出一些状态信息,且每次按下都会弹出,然后我们输入字符,字符确实都变为了*,而且再次按下f12后,我们输入的字符又不再显示为*。这样的效果显然是有点一言难尽的,接下来让我们继续优化。

再次修改keyboard.S

我们再次查看func:

1733555011131

调用func时不经过任何判断一定会调用_show_stat函数,不用想都知道一定是这个函数在捣鬼,我们这里只需要对于按下F12 有反应,而且f12的键盘扫描码为0x58。我们直接在func的开头进行判断,我们修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func:
cmpb $0x58,%al
je call_f12func /* fix:按下f12取消出现状态*/
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
ok_func:
cmpl $4,%ecx /* check that there is enough room */
jl end_func
movl func_table(,%eax,4),%eax
xorl %ebx,%ebx
jmp put_queue
end_func:
ret
call_f12func: /*fix:调用函数*/
call change_f12Flag
ret /*fix:调用后直接结束*/

现在我们再次构建来看一下效果:

1733555536078

很完美,按下f12后显示变为*,再次按下f12后输入的字符正常显示。

但是这可能与我们最开始设想的结果不太一样。在我的设想中,我们要实现的效果应该是,当我们按下f12,我们之前输入的字符,和我们现在新输入的字符,应该一同全部变为*,当我再次按下f12,之前所有变为*的内容都会在一瞬间恢复,并且新输入的字符也将正常显示。

好那么我们继续修改我们的程序:

再次修改console.c

首先我们修改程序使得程序的触发逻辑变为:按下12立即调用一个函数对于之前输入的字符进行处理。

那么我们在之前的基础上进行如下简单修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//fix:创建变量f12Flag,用于判断是否按下F12
extern int f12Flag=0;
//fix:声明函数change_f12Flag
void console_transform(struct tty_struct * tty);
//fix:创建函数change_f12Flag,用于改变f12Flag的值
void change_f12Flag(void)
{
switch(f12Flag)
{
case 1:
f12Flag=0;
break;
case 0:
f12Flag=1;
break;
}
console_transform(0+ tty_table);//fix:让功能在按下F12后立即生效
}

我们新声明了一个函数,并且在f12Flag状态改变后立即进行调用,来对于之前输入的字符串进行处理。并且我们的传参为0+ tty_table。这是因为tty_table[0] 中存储了从键盘中输入的所有内容。

然后我们来写console_transform函数中的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//fix:创建函数console_transform,用于将屏幕上的字母转换为*
void console_transform(struct tty_struct * tty)
{
if (f12Flag)
{
unsigned long tpos = pos;
int len = x; //光标的横坐标
pos -= len << 1;
char* tmp = (char*)(&(tty->write_q.buf[tty->write_q.head - len]));
while (pos < tpos) //将该行的内容重写,将字母变为*
{
if(f12Flag && ((* tmp>64&&* tmp<91)||(* tmp>96&&* tmp<123)))
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" ('*'), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
else
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
}
}
else
{
unsigned long tpos = pos;
int len = x;
pos -= len << 1;
char* tmp = (char*)(&(tty->write_q.buf[tty->write_q.head - len]));
while (pos < tpos) //对该行重写,全部正常显示。
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
}
}

同时,我们保留con_write中的内容修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (c>31 && c<127) {
if (x>=video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf();
}
//fix:在这里判断是否按下F12,如果按下F12,则新输入的字母转换为*
if(f12Flag && ((c>64&&c<91)||(c>96&&c<123)))
c='*';
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (c),"m" (*(short *)pos)
);
pos += 2;
x++;
}

这样我们就实现了如下效果:

按下f12后,该行的字母全部变为*

1733571309292

再次按下f12,所有的字符立即复原:

1733571368341

虽然看似一切都完美无缺,但是当你在输入字符的过程中,如果按下过DEL,或者方向键,等功能按键,那么你可能会看到如下效果:

当你按下f12后,原本正常的字符串却突然出现了一些你没有输入过的‘[’

1733571634671

再次按下f12后:

1733571714768

很多奇怪的字符改变了你原本输入的字符,这是因为:你输入的功能按键,也被一起保存在tty的write队列中,这些按键的字符,顶替了原本输入的文本字符的位置出现在了屏幕中。

解决输入功能键导致的字符错乱

要想在从缓冲区中获取字符的时候,过滤出我们输入的字符,剔除掉那些不应该打印出来的字符,我们最好从tty->secondary中获取缓冲区中的内容,因为tty->secondary中的字符都是没有经过tty系统各种处理的,与我们从键盘按下的按键顺序是一一对应的关系,也没有程序输出 的字符在其中。

然后我们需要知道的是,对于方向键,其在tty->secondary中需要三个字符来表示,类似0x27 + ‘[’+ “A”,而backspace,在其中的转译码为127。

所以我们得到如下函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//fix:创建函数console_transform,用于将屏幕上的字母转换为*
void console_transform(struct tty_struct * tty)
{
if (f12Flag)
{
unsigned long tpos = pos;
int len = x-13;
pos -= (len) <<1;
char* tmp = (char*)(&(tty->secondary.buf[tty->secondary.head]));
int i = 0;
for( i = 1;i<len;i++)
{
if(*tmp == 27) //遇到方向键则向后多获取三个字符
{
if(*(tmp+1) == '[')
{
i-=3;
}
else
{
i--;
}
}
else if((*tmp < 32 || *tmp > 126)) //遇到其他功能键则向后多获取一个字符
{
i--;
if( *tmp == 127)
{
i--;
}
}
tmp--;
}
while (pos < tpos)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[') //遇到方向键则跳过方向键不打印
{
tmp+=3;
}
else{
tmp++;
}
continue;
}
else if(*tmp < 32 || *tmp > 126) //遇到其他功能字符也不打印
{
tmp++;
if( *tmp == 127)
{
pos-=2;
}
continue;
}
if(f12Flag && ((*tmp>64&&*tmp<91)||(*tmp>96&&*tmp<123))) //将正规的字符打印出来
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" ('*'), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
else
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}

}
}
else
{
unsigned long tpos = pos;
int len = x-13;
pos -= (len) <<1;
char* tmp = (char*)(&(tty->secondary.buf[tty->secondary.head]));
int i = 0;
for( i = 1;i<len;i++)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
i-=3;
}
else
{
i--;
}
}
else if((*tmp < 32 || *tmp > 126))
{
i--;
if( *tmp == 127)
{
i--;
}
}
tmp--;
}
while (pos < tpos)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
tmp+=3;
}
else{
tmp++;
}
continue;
}
else if((*tmp < 32 || *tmp > 126))
{
tmp++;
if( *tmp == 127)
{
pos-=2;
}
continue;
}
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
}
}

现在我们输入字符串后,随意按下方向键,再按下f12,也不会出现那些转译字符啦:

1733581208504

从字符串末尾通过backspace来删除字符串,也不会产生字符串的错位问题,能够正常显示和遮挡:

1733581292223

1733581299633

1733581299633

嗯,现在又解决了一个小问题,但是仍然面临很多其他问题:

  1. 无论从哪里删除一个字符,按下f12后,删除的都会是最后一个字符。
  2. 在字符串中间插入时,按下f12 后插入的字母会到最后
  3. 在字符串中间删除,再插入,按下f12后会出现之前已经删除的在字符串末尾的字符
  4. 如果输入超过一行,则无法处理上一行的内容

要解决前三个问题需要我们维护tty->secondary队列中的内容。

任务一

1)键入F12,激活功能,键入学生姓名,将名字首末字母以及名字中包含首末字幕单词修改为 比如:zhangsan,显示为: *ha*gsa*

实现这个功能只需要在我们实现的ppt演示功能基础上修改即可,原本我们对于*遮挡的条件是:

1
f12Flag && ((*tmp>64&&*tmp<91)||(*tmp>96&&*tmp<123))

表示只要是个字母我们就用*替代。

我们现在需要获取输入姓名的首位字母,同时在输入后续字母时,需要实时调用函数来对于之前的字符串进行处理,因为在输入姓名的过程中,最后一位字母是实时变化的。

所以我们只需要对于遮挡部分的代码进行修改,对于还原部分的代码无需改动,修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
if (f12Flag)
{
unsigned long tpos = pos;
int len = x-13;
pos -= (len) <<1;
char* check[2] ; //用来保存当前姓名的首尾字母
char* tmp = (char*)(&(tty->secondary.buf[tty->secondary.head]));
int i = 0,flag= 1;
for( i = 1;i<len;i++)
{
if(flag)
{
check[0] = tmp;
flag = 0;
}
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
if(tmp+2 == check[0]) //首尾字母不能是功能按键中的字母
{
flag = 1;
}
i-=3;
}
else
{
if(tmp == check[0])
{
flag = 1;
}
i--;
}
}
else if((*tmp < 32 || *tmp > 126))
{
if(tmp == check[0])//首尾字母不是功能按键中的字母
{
flag = 1;
}
i--;
if( *tmp == 127)
{
i--;
}
}
tmp--;
}
check[1] = tmp;
while (pos < tpos)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
tmp+=3;
}
else{
tmp++;
}
continue;
}
else if(*tmp < 32 || *tmp > 126)
{
tmp++;
if( *tmp == 127)
{
pos-=2;
}
continue;
}
if(funcFlag &&((*tmp > 65 && *tmp<90) || (*tmp > 97 && *tmp<122)) &&(((*tmp>=65&&*tmp<=90)?((*tmp == *check[0]) || ((*tmp)+32) == *check[0]):((*tmp == *check[0]) || ((*tmp)-32) == *check[0])) || ((*tmp>=65&&*tmp<=90)?((*tmp == *check[1]) || ((*tmp)+32) == *check[1]):((*tmp == *check[1]) || ((*tmp)-32) == *check[1])))) //大小写字母只要是一个字母全都遮挡
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" ('*'), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
else
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}

}
}

同时,为了实现在输入姓名的时候实时调整遮挡的字母,我们将con_write()也做一点微小的改动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (c>31 && c<127) {
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++;
//fix:在这里判断是否按下F12,如果按下F12,则新输入的字母转换为*
if(f12Flag && ((c>64&&c<91)||(c>96&&c<123)))
console_transform(tty);

每输入一个新的字母我们就调用一次函数,对于已经输入的字符串进行处理。

结果演示

先输入我的名字第一个字的拼音:

1733714592558

按下f12:首位字母变为*

1733714610390

接着我们直接继续输入我剩下的名字:

1733714683318

在输入过程中可以观察到每输入一个字符,程序会自动更新当前的尾字母并进行遮挡,遮挡的字母是动态变化的。

最后我们再次按下f12,取消该功能:

1733714770341

所有字母恢复正常并且与我输入的内容一致。

任务2

键入学号,激活功能,键入学生姓名,将名字首末字母以及名字中包含首末字幕单词修改为 *

再次键入学号,取消该功能,正常显示。

由于在任务二中,功能的实现已经与f12,没有关联,我们先将之前的所有修改移除,即,接下来我们在一个原始的文件上修改。

首先我们还是仿照以前的思路,我们创建一个状态变量funcFlag,用于表示现在功能开启还是关闭,然后通过一个函数来改变funcFlag的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//fix:创建变量funcFlag
extern int funcFlag=0;
//fix:声明函数change_funcFlag
void console_transform(struct tty_struct * tty);
//fix:创建函数change_funcFlag,用于改变funcFlag的值
void change_funcFlag(void)
{
switch(funcFlag)
{
case 1:
funcFlag=0;
break;
case 0:
funcFlag=1;
break;
}
console_transform(0+ tty_table);
}

对于con_write(),我们进行如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (c>31 && c<127) {
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++;
if(judge(&tty->secondary.buf[tty->secondary.head-10]))
{
change_funcFlag();
}
if(funcFlag && ((c>64&&c<91)||(c>96&&c<123)))
console_transform(tty);
}

每写入一个字符串后,我们就将检测前面10个字符是否是学号,如果是学号,我们就调用函数,改变funcFlag的状态。同时,对于开启状态中写入的字符,我们都调用console_transform函数进行改写。

judge() 函数的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int judge(char* tmp)
{
int i = 0;
char* number = "2023211246";
for(i = 0;i<10;i++)
{
if(*tmp != number[i])
{
return 0;
}
tmp++;
}
return 1;
}

console_transform函数,我们也需要做一个小改动。由于在输入学号前,我们输入了我们的学号,所以对于输入过程中,我们输入姓名的第一个字母不再是第一个字符,而是学号后面的一个字符。所以我们修改完如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
void console_transform(struct tty_struct * tty)
{

if (funcFlag)
{
unsigned long tpos = pos;
int len = x-13;
pos -= (len) <<1;
char* check[2] ;
char* tmp = (char*)(&(tty->secondary.buf[tty->secondary.head]));
int i = 0,flag= 1;
for( i = 1;i<len;i++)
{
if(flag)
{
check[0] = tmp;
flag = 0;
}
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
if(tmp+2 == check[0])
{
flag = 1;
}
i-=3;
}
else
{
if(tmp == check[0])
{
flag = 1;
}
i--;
}
}
else if((*tmp < 32 || *tmp > 126))
{
if(tmp == check[0])
{
flag = 1;
}
i--;
if( *tmp == 127)
{
i--;
}
}
tmp--;
}
while (pos < tpos)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
tmp+=3;
}
else{
tmp++;
}
continue;
}
else if(*tmp < 32 || *tmp > 126)
{
tmp++;
if( *tmp == 127)
{
pos-=2;
}
continue;
}
if(judge(tmp))
{
check[1] = tmp+10;
}
if(funcFlag &&((*tmp > 65 && *tmp<90) || (*tmp > 97 && *tmp<122)) &&(((*tmp>=65&&*tmp<=90)?((*tmp == *check[0]) || ((*tmp)+32) == *check[0]):((*tmp == *check[0]) || ((*tmp)-32) == *check[0])) || ((*tmp>=65&&*tmp<=90)?((*tmp == *check[1]) || ((*tmp)+32) == *check[1]):((*tmp == *check[1]) || ((*tmp)-32) == *check[1]))))
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" ('*'), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
else
{
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}

}
}
else
{
unsigned long tpos = pos;
int len = x-13;
pos -= (len) <<1;
char* tmp = (char*)(&(tty->secondary.buf[tty->secondary.head]));
int i = 0;
for( i = 1;i<len;i++)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
i-=3;
}
else
{
i--;
}
}
else if((*tmp < 32 || *tmp > 126))
{
i--;
if( *tmp == 127)
{
i--;
}
}
tmp--;
}
while (pos < tpos)
{
if(*tmp == 27)
{
if(*(tmp+1) == '[')
{
tmp+=3;
}
else{
tmp++;
}
continue;
}
else if((*tmp < 32 || *tmp > 126))
{
tmp++;
if( *tmp == 127)
{
pos-=2;
}
continue;
}
__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (*tmp), "m" (*(short *)pos)
);
pos += 2;
tmp++;
}
}
}

结果演示

首先我们输入学号姓名,显示如下:

1734526319249

然后我们再次输入学号,取消功能,正常显示:

1733735524773


计算机系统实验4
http://blog.ulna520.com/2024/12/07/计算机系统实验4_20241207_091910/
Veröffentlicht am
December 7, 2024
Urheberrechtshinweis