diff --git a/cod/chp1.md b/cod/chp1.md new file mode 100644 index 0000000..70dc0ef --- /dev/null +++ b/cod/chp1.md @@ -0,0 +1,24 @@ +计算机组成原理第一章知识脉络 +========================= + +本章讨论的主要内容是数据通路(data path)的设计,关键在于如果实现一个ALU。 + +为了实现一个计算机(computing machine),首要的当然是要能够实现基本的计算功能。而为了实现计算功能,首先需要将数据在计算机中表示,这包括字符型数据,定点数(整数)以及浮点数,这里主要讨论定点数的表示。将定点数在计算机中表示,最简单直白的方法就是直接将它的二进制形式存储在计算机中,新增一位符号位来表示它的正负,这就是原码表示法。然而原码表示法具有一些致命性的缺陷,比如原码的计算不服从加法性质;为了构造一种复合加法性质的表示法,就产生了反码。反码的确是可以进行加法和减法运算的,但是在反码表示法下,`0`将具有两种反码表示,可以将反码简单加`1`来规避这种情况,这就是补码表示法。现代计算机中数据的存储几乎都是采用补码。 + +成功将数据在计算机中表示后,紧接着就需要讨论如何实现计算的问题。首先是最简单的加法运算,可以首先构造一个一位的全加器,其中加法的结果`S`和进位位`C1`都可以表达成两个输入`X, Y`以及上一位的进位`C0`的简单组合逻辑;通过将多个这样一位的全加器组合起来,就可以形成多位的全加器。然而,这样的全加器在计算的效率上存在缺陷,因为每一位必须等到前一位的进位计算完毕之后才可以开始计算,为了改进改进这种缺陷,产生了`超前进位`的策略,实际中采用的是分组的超前进位。 + +利用补码的运算法则,可以方便地通过全加器实现减法运算。由于 + +``` +(x - y)补 = (x)补 + (-y)补 +``` + +因此可以通过求被减数的相反数的补码,将减法转化成加法来进行。为此,只需要将被减数逐位取反再加一,再添加一些控制逻辑即可。 + +乘法和除法的实现则稍显复杂。对于乘法,是通过多次的加法和移位操作来实现的。乘法器的设计具有三个版本,需要把握三个版本的不同,以及优化的思想。而补码的乘法,是通过`布斯算法`来实现的。除法的逻辑电路和乘法几乎相同,只是在一些细节上有所改变,除法的实现主要有`恢复余数法`与`加减交替法`两种方法,后者是前者的一种改进策略,其正确性要能够证明。补码的除法的运行算法也有有所了解。 + +实现了基本的算术运算(与逻辑运算)后,就可以着手进行ALU的搭建。构造ALU的方法与前面的加法器是类似的,首先建立一位的ALU,确立其输入与输出,以及必要的控制信号,通过算术逻辑给出真值表,从而搭建起组合逻辑电路。将多个一位的ALU组合起来,即可得到多位的ALU了。 + +最后讨论浮点数的表示与运算。浮点数的表示分为两个部分,即阶码与尾数,两个部分都有自己的符号位。浮点数的表示遵循IEEE754标准,为了理解这个标准,关键在于各个部分的位数以及它们的位置,以及相应的表示方法,比如阶码采用移码表示,而尾数则采用原码,并且省略了规范后首位的`1`。此外,IEEE754还保留了两个部分一些特殊的值,来表示一些特殊情况,比如`0`的表示,无穷的表示,`NaN`的表示以及非规范化浮点数的表示。此外,浮点数的加减法与乘除法的实现,也需要有一定的了解,比方说由于浮点数本身的特点,浮点加法并不满足结合律,两个浮点数之间也不能判等。 + +最后的最后还有一些内容,(我觉得和计算机组成真的没有什么关系),是检错纠错码。这里主要是讨论了两种检错纠错码,即奇偶检验码和汉明校验码,两种的编码方式都要非常熟悉。对于汉明校验码,其关键在于理解数据数位`k`和检验数位`r`之间满足的两个不等式关系。这里还需要把握码距的概念。 diff --git a/thu_os/lab2_report.md b/thu_os/lab2_report.md index 70099fe..ead2f6f 100644 --- a/thu_os/lab2_report.md +++ b/thu_os/lab2_report.md @@ -258,7 +258,7 @@ page_init(void) { * | Free Memory (*) | * | | * freemem -------------> +---------------------------------+ - * | Struct Page *pages | + * | Struct Page *pages | * pages ---------------> +---------------------------------+ * | Invalid Memory (*) | * end kern ------------> +---------------------------------+ @@ -613,4 +613,22 @@ boot_pgdir[0] = boot_pgdir[PDX(KERNBASE)]; ## 自映射机制 -可以查看实验指导书吧,我不想写了......还是非常巧妙的,值得一看。 +自映射机制的思想是为了使操作系统(和用户程序)方便快捷地查看当前的页目录表项以及页表项。为了查看页目录表和页表的全部内容,一种方法是从页目录表的起始地址,逐个遍历其中的表项,我是觉得这种方法挺好的,但是老师觉得不太行...... + +为了方便地查看页表中的所有页表项,可以人为设定一个虚拟地址`VPT`,其低20位为零,并且在页目录表中添加一项,将该虚拟地址对应的页表映射为页目录表本身。即 + +```c +boot_pgdir[PDX(VPT)] = PADDR(boot_pgdir) | PTE_W | PTE_P; +``` + +这样,整个页目录表成为了该虚拟地址的页表,而全局的页表,则成为了该虚拟地址对应的页帧。这样,通过访问`VPT[n]`,就可以访问全局页表中的第`n`个页表项了。 + +同理,还可以设置`vpd = PGADDR(PDX(VPT), PDX(VPT), 0)`,这样整个页目录表就成为了虚拟地址`vpd`对应的物理页帧,通过访问`vpd[n]`就可以访问第`n`个页目录表项。 + +同样的机制也可以用于用户程序当中。比如某个用户程序希望知道自己当前页表的结构,但是页表是由操作系统维护的,此时设置用户虚拟地址`UVPT`,并且将它对应的页表映射到用户程序的页目录表,即 + +```c +user_pgdir[PDX(UVPT)] = user_pgdir | PTE_P | PTE_U; //no PTE_W +``` + +用户程序就可以通过虚拟地址`UVPT`访问到它自己的页表项了。需要注意的是,这里不能给`写权限`。 diff --git a/words.md b/words.md index 7e5b36b..2a00df4 100644 --- a/words.md +++ b/words.md @@ -1857,6 +1857,7 @@ Some Words > (adj)a deductible expense is a cost that you can subtract from the earnings on which you have to pay income tax.
> (n)a part of the cost of an accident, injury etc that you agree to pay yourself when you buy insurance. + - Expenses like office phone bills are tax-deductible. - Customers can lower insurance premiums by taking higher deductibles. + odds @@ -1902,6 +1903,6 @@ Some Words > (v)to work hard
> (n)hard work, especially work that makes you feel physically tired. - - People who toiled in dim factores were too exhausted to enjoy their family life. + - People who toiled in dim factories were too exhausted to enjoy their family life. - Well, after a day's toil in the office I like to relax a little. \ No newline at end of file