2004年10月27日

虽然不会买,但是仍然在侯捷老师的网站上面下载了包含部分章节的版本,不过没有细看。

现在才知道原来侯捷老师一直用Word+Acrobat的方式写作的。可惜即使他也没有想到去使用LaTeX这个伟大的工具,更别谈国内的其他作者了。

不是说用word就不行,所谓萝卜青菜各有所爱嘛。不过Word的不稳定(我指有时候你的word文档会损坏),大型word文档转pdf的速度,唉就不说了。

还有就是起码我自己,现在还是不很会用Word里面的“列表”,就是LaTex里面的\itemize,我是经常会上下两个列表不对齐,怎么调都不行。所见即所得没错啊,关键是你要能排成你要的样子啊。所以我更喜欢所想即所得,起码,我想它这样,它就是这样的。

我不是牛人,不是高手。一个即将靠计算机吃饭的人,目前基本所有涉及到的文档都用LaTeX来写。项目报告、简历、笔记等等。我就喜欢这样。一如候老师喜欢用word一样。

不要以为LaTeX很难。感谢CTeX.org,Windows用户可以在1个多小时内安装好并学会基本使用。Linux用户若有需要,我愿尽我所能帮助你。

2004年01月31日

 第三章 Windows运行机理

3.1 内核分析
 3.1.1 运行机理
 1. 概述
 VxD中的“x”代表任意的设备。可以把VxD看作是32位的DOS。Windows实现一个多任务的操作系统的方法是把运算时间轮流地分给每个虚拟器。
 VMM是一个32位的保护模式程序。它的主要任务是建立和维护一个支持虚拟机的框架,并对每个VM提供服务。VMM是第一个被加载到内存的VxD程序,放在系统目录下的VMM32.VxD中。
 在DOS程序中,虚拟设备驱动程序能控制系统的一切资源。当它们在虚拟机中运行时,Windows需要为每一个设备建立一种虚拟的设备来模拟DOS对硬件的操作。一个VxD程序通常控制真正的硬件设备,并对该设备在各个虚拟机之间的共享进行管理。尽管如此,并不是每个VxD程序必须和一个硬件设备相联。我们可以把VxD程序看做是在第0级别的DLL。
 Windows95下有两种VxD,静态VxD和动态VxD。静态VxD是那些从系统启动就被加载,在系统关闭前一直存在于内存中的VxD程序。动态VxD程序可以在需要的时候,通过程序本身加载或卸载。
 2. 虚拟机管理器
 虚拟机管理器(VMM)是Windows 9x的真正内核。VMM中使用了虚拟存储的技术,能够克服物理内存的限制。尽管再物理上不存在,但理论上4GB的空间是能被访问的。
 当一个Win32程序访问4MB空间内时,它其实访问的时映射的某物理空间。Windows中是按4KB的大小来对内存空间进行分页的。
 3. 虚拟设备
 静态VxD的加载过程:
 (1) 直接在system.ini中加入下一行代码:
  Device=VxD_NAME
 (2) 可以在Windows9x注册表中的HLM\System\CurrentControlSet\Services\VxD\key\StaticVxD子键下加入如下的VxD的路径和名字:VxD_NAME=PATHNAME
 3.1.2 LE文件的格式
 LE文件中代码和数据被存放在几类运行属性不同的段中:LCODE PCODE PDATA ICODE DBOCODE SCODE RCODE 16ICODE MCODE。
 总的说来,应该尽可能多地使用PCODE和PDATA,因为这样,VMM就可以在需要的时候把段调入调出内存。另外,硬件中断程序及其所用到的服务必须放在LCODE段里。
 在一个汇编的VxD项目中,段的定义是不必要的,段的定义主要用于C的VxD项目编写。
 3.1.3 VxD的设计实现
 系统消息Sys_Critical_Init:大多数VxD程序不要用到这个消息,除非VxD程序要接管一些其他VxD程序或者保护模式要用到的中断。
 在VMM加载VxD程序的时候,它是按照初始化顺序值小的VxD先加载的顺序加载的。
 动态VxD除了加载机制和接收到的初始化/结束消息跟静态VxD不通以外,它能做静态VxD所能做的一切。
 要在一个段里面定义函数,应该首先定义一个段,然后把函数放进去。
 VxD程序可以使用所有的寄存器,但是在改动段寄存器的时候一定要小心,一定不要改动CS和SS的内容,除非你对将发生的事情有绝对的把握。你可以使用DS和ES,但一定要记住在返回时恢复它们的初值。调用寄存器法服务函数时,通过各种寄存器来传递服务函数的参数。当调用堆栈服务函数时,你把要传递的参数压栈,在eax得到返回值。


3.2 消息的运行方式
 在16位时代,Windows的整个内核是32位的、分时的、抢占的。


(未完待续)

2004年01月17日

 第二章 认识CPU

2.1 8位处理器回顾
 Intel 8080由6000多个晶体管构成,每秒能执行约60万次操作。寻址空间达到64KB,指令多达60条以上。
 苹果II使用的是6502芯片,有256Byte的固定堆栈区,内有一些基本函数的功能。可惜它没有后续的兼容性的产品。


2.2 16位微处理器
 2.2.1 组成结构
 8086/8088与6502之间最大的不同在于指令的体系结构。8086在指令执行的时候引入了流水线的概念。
 2.2.4 终端处理
 可以把终端认为是一种函数的调用,不过,这个函数是随时都可能调用的。引起这种操作的时间就叫中断源。所谓中断号其实就是中断处理的入口地址。


2.3 32位微处理器
 2.3.1 寄存器组成
 在80386中,8个32位通用寄存器都可以作为指针寄存器使用。在保护模式下,内存逻辑地址分布方式总体上是通过可见部分寄存器指向不可见的内存部分。
 2.3.2 保护模式
 保护模式最重要的是完善了多任务保护机制。
 (1) 不通任务之间的保护:通过把每个不同的任务放在不同的虚拟地址空间中,来实现不通任务间的隔离。
 (2) 同一任务的保护:在每一任务之内定义了4种保护级别(0:最高权限,3:最低权限)。一般的系统只使用环0和环3这两个级(例如Windows)。
 2.3.3 80386的寻址方式
 80386继续采用分段的方法管理主内存。内存的逻辑地址由段基地址(段的起始地址)和段内偏移两部分表示;存储单元的地址由段基地址加上段偏移得到。
 在保护模式下,段基地址可长32位,并且无需是16的倍数,可以是内存内任意一个开始点,段的最大长度可达4GB。在8086/8088和80386实模式下,段寄存器用来表示段值。而在80386的保护模式下,段寄存器就成为选择子。选择子的作用就是指向对应的描述符(用来描述段的属性参数)。
 外部终端称为“中断”,内部中断称为“异常”。中断处理程序分为以下两种:
  (1) 当程序出现中断时,让中断自己进行处理,程序跳到中断点后继续运行。
  (2) 中断程序可能先在环1进行一些处理,然后再跳环2进行一些处理,还可能跳用户层(环3)进行处理。但是Windows中没有环1、环2的过程,所以这种情况一般发生在异常中。

2004年01月16日

第一章 程序点滴

1.1 程序≠软件
 1.1.1 商业软件门槛的形成
   1. 商业软件门槛的形成
 任何一个行业初始阶段时的门槛都非常低,但是,只要发展到一定的阶段后,它的门槛就必然抬高。
   2. 软件门槛对程序员的影响
 程序要编程软件,这其中是一个商业化的过程
 1.1.2 认清自己的发展
  机遇是从耐心中产生的,越有耐心,就约有机遇。要想做一个很好的软件,做通用软件,要从最底层开始做起,从最基本做起。


1.2 高手是怎样练成的
 
1.2.1 高手成长的六个阶段
 (1) 能熟练使用某种语言。
 (2) 能精通基于某种平台的接口以及所对应语言的自身的库函数。
 (3) 能深入地了解某个平台系统的底层。
 (4) 能直接在平台上进行比较深层次的开发。这时候,语言只是一种工具,思想一定要转变过来。
 (5) 能从全局上把握和设计一个比较大的系统体系结构,从内核到外层界面。
 (6) 此时任何问题就纯粹变成了一个思路的问题,不是涌什么代码就能表示的。
 每个阶段再向上发展时都要按一定的方法。第一、第二个阶段通过自学就可以完成,只要多用心去研究,耐心地去学习。要想从第二个阶段过渡到第三个阶段,就要有一个好的学习环境。例如有一个高手带领或公司里有一个好的练手环境。
 1.2.2 初级成员和高级程序员的区别
 高级程序员遇到问题考虑的绝对是什么才是具有最快效率,最稳定性能的解决问题的方法。
 程序员达到最高境界的时候,想的就是“我就是程序,程序就是我”。要以程序的思考方式来思考程序,而不是以我去设计程序的方式去思考程序。
 一个高级程序员应该具备开放性思维,从里到外的所有的知识都能了解。实际上,技术到达最高境界后,是没有分别的。
 程序员要达到这样的目标,就要有非常强的耐心和非常好的机遇才有可能。而机会都是出在耐心里。“雄心的一半是耐心”。
 1.2.3 程序员是吃青春饭的吗
 追求技术的最高境界的时候,实际上是没有年龄限制的。


1.3 正确的入门方法
 入门最基本的方法就是从C语言入手。BASIC每个所谓的命令在C语言里面都可以做成一个函数来实现。
 工欲善其事,必先利其器。要想成功,没有一个艰苦的过程是不可能的,所以一开始就要有耐心。如果你准备花5年的时间成为高手,那你根本不用等到5年,只要有这个耐心就足够了。但如果你想在一年时间内就成为高手,即使5年后,你还是成不了高手。
 到达高手的境界后,所有的事物都是触类旁通的。好的程序员必须具备开放性思维,也就是思考问题的方法。程序员,尤其现在很多的程序员,都被误导从MFC入手,这就很容易形成一种封闭式的思维模式。
 1.3.1 规范的格式是入门的基础
   1. 成对编码
 正确的程序设计思路是成对编码,先写上面的大括号,然后马上写下面的大括号。如果用成对编码,则程序任何时候都是可以调试的。代码一定不能乱,一定要格式非常清楚。
 读程序时要养成一种习惯,就是分块阅读程序,很明显两个大括号之间就是一块代码。
   2. 代码的注释
 真正要做一个有价值的程序,开发程序的思维就很重要,这种思维的具体体现就在注释及规范的代码本身。
 1.3.2 调试的重要性
 所有的程序都是调试出来的,不是写出来的。


1.4 开放性思维
 游离于平台之上的系统和实际的应用软件是不现实的。任何一个软件一定都是跟一个平台相关联的,脱离平台之上的软件几乎都是不能用的。
 一个很普通的程序员,如果他能够考虑倒将程序分成好几个动态库,那么她的思维方式就有点开放性了,就已经不是MFC那些思维方式。
 1.4.1 动态库的重要性
 有了动态库,当你要改进某一项功能的时候,你就可以不动任何其他的地方,只要改其中你拆出来的这一块。
 1.4.2 程序设计流程
 (1) 拆出模块。
 (2) 对操作系统所提供哪些功能,程序怎么跟操作系统接口考虑清楚。
 (3) 把它拆成一个个独立的模块。
 (4) 再进一步去实现,从小到大地进行设计。
 可预测性就是从症状就能判断出是哪些代码产生了问题,这就是可预测性。