处理器依靠机器指令工作,
但机器指令从形式上看都是一些没有规律的数字.
这样就发明了汇编语言.
本章目标是
1.了解汇编语言的作用和"汇编"一词的由来
2.下载NASM编译器,并学会使用它来编译汇编语言源程序
汇编语言简介
指令和被指令引用的数据在内存中都是一些或高或低的电平,
每一个电平都可以看成是一个二进制位[0或者1],
8个二进制位形成一个字节.
要解读内存中的东西,最好的办法就是将它们按字节转换成数字的形式.
如,下面这些数字就是存放在内存中的Intel8086指令,我们用的是十六进制.
B8 3F 00 01 C3 01 C1
对大多数人来说,很难想象上面那一排数字对应着下面几条8086指令:
将立即数003FH传送到寄存器AX
将寄存器BX的内容和寄存器AX的内容相加,结果在BX中
将寄存器CX的内容和寄存器AX的内容相加,结果在CX中
在第一个处理器诞生后不久,如何使指令的编写更容易,就提上了日程
这就产生了汇编语言.
这样,上面那些指令就可以写成:
mov ax, 3FH
add bx, ax
add cx, ax
汇编语言对指令的大小写没有特别的要求
在很多高级语言中,
如果要指示一个数是十六进制数,
通常不采用在后面加"H"的做法,
而是为它添加一个"0x"前缀.像这样
mov ax, 0x3f
在汇编语言中,使用十进制数是最自然的.因为3FH等于十进制数63,所以可以写成
mov ax, 63
当然,如果你喜欢,也可以使用二进制数来这样写
mov ax, 00111111B
B表明它是一个二进制数.
用汇编语言提供的符号书写的文本,叫做汇编语言源程序.
还需将汇编语言源程序转换成机器指令,
这个过程叫做编译.
在编译的时候,汇编语言编译器的作用是将mov,add,ax,bx等这些符号组合起来,
转换成类似于数值的机器指令,这个过程叫做汇编.这就是汇编语言的由来.
编译肯定还需要依靠一个软件,称为编译器,或编译软件.
从字处理器软件生成的是汇编语言源程序文件.
编译软件的任务是读取这些文件,
将那些符号转变成二进制形式的机器指令代码.
它把这些机器代码存放到另一个文件中,
叫做二进制文件或可执行文件.
当需要用处理器执行的时候,再加载到内存里.
NASM编译器
每种处理器都可能会有自己的汇编语言编译器.
对同一款处理器来说,针对不同的平台也会有不同版本的汇编语言编译器.
现存的汇编语言编译器有多种,用的比较多的有
MASM,FASM,TASM,AS86,GASM等.
每种汇编器都有自己的特色和局限性.
有些还需付费才能使用.
本书中,用一款叫做NASM的汇编语言编译器.
NASM的全称是Netwide Assembler,
它是可免费使用的开源软件.
NASM支持多个平台,
比如为16位和32位DOS,Linux,OS/2等操作系统开发的版本
代码的书写和编译过程
NASM在运行之后并不会显示一个图形用户界面,
相反地,它只能通过命令行使用。
比如,可用windows记事本编写一个汇编语言源程序,
并把它保存到NASM工作目录下【安装NASM时所用的安装文件件】,
文件名为exam.asm。
作为惯例,汇编语言源程序文件的扩展名是".asm",不过,你可以使用其他扩展名。
一旦有了一个源程序,下一步就是将它的内容编译成机器代码。
打开Nasm Shell。
接着,在命令行提示符后输入"nasm -f bin exam.asm -o exam.bin",按Enter。
NASM需要一系列参数才能正常工作。
-f 作用是指定输出文件的格式
-f bin就是要求NASM生成的文件只包含"纯二进制"的内容。
换句话说,除了处理器能识别的机器代码外,别的任何东西都不包含。
这样一来,
因为缺少操作系统所需要的加载和重定位信息,
它就很难在Windows,Dos和Linux上作为一个普通的应用程序运行。
紧接着,exam.asm是源程序的文件名,它是将要被编译的对象。
-o 参数指定编译后输出的文件名。这里要求NASM生成输出文件exam.bin。
用HexView观察编译后的机器代码
尽管我们强调源文件和编译之后的文件具有不同的内容。
但如果能用工具看一看,
相信印象更为深刻。
虚拟机的安装和使用
和其他所有计算机语言一样,
汇编语言程序设计有很强的实践性。
当程序编译完成后,如何让处理器执行它呢?
如何才能知道执行的结果是否正确呢?
本章的目标是:
1.了解计算机的开机启动过程
只有这样,你才能知道我们应当把编译好的程序放到哪里才会被处理器执行到
2.了解硬盘的构造和作用
3.了解VritualBox虚拟机的功能,下载和安装VirtualBox虚拟机软件,
创建一台本书中要用到的虚拟机,学会往虚拟硬盘中写数据,
学会VirtualBox虚拟机的使用方法。
计算机的启动过程
如何将编译好的程序提交给处理器
对绝大多数编译好的程序来说,
要想得到处理器的光顾,
让它执行以下,必须借助于操作系统。
每种操作系统都对它所管理的程序提出了种种格式上的要求。
比如,它要求编译好的程序必须在文件的开始部分包含编译日期,
是针对哪种操作系统编译的,程序的版本,
第一条指令从哪里开始,数据段从哪里开始,有多长,
代码段从哪里开始,有多长,等等。
windows甚至建议你在文件中包含至少一个用于显示的图标。
如你不按它的要求来,运行时会报错。
每种编译器都有能力针对不同的操作系统来生成不同格式的二进制文件,
程序员所要做的就是在源程序中加入一些相关的信息,
比如指定每个段的开始和结束,并在编译时指定适当的参数。
在特定的操作系统上开发软件肯定不是一件容易的事情。
但换个角度考虑下,操作系统也是一个需要在处理器上运行的软件,
只不多比起一般程序而言,体积更庞大,功能更复杂。
如我们能绕过它,或代替它,让计算机一开机的时候直接执行我们自己的软件,
岂不是更简单?
计算机的加电和复位
在处理器的众多引脚中,有一个是RESET,用于接收复位信号。
每当处理器加电,或RESET引脚的电平由低变高时,
处理器都会执行一个硬件初始化,以及一个可选的内部自测试,
然后将内部所有寄存器的内容初始到一个预置的状态。
比如,对Intel8086来说,
复位将使代码段寄存器的内容为0xFFFF,
其他所有寄存器的内容都为0x0000,
包括指令指针寄存器。
8086之后的处理器并未延续这种设计,但毫无疑问,
无论怎么设计,都是有目的的。
处理器的主要功能是取指令和执行指令,
加电或者复位之后,
它就会立刻尝试去做这样的工作。
不过,在这个时候,内存中还没有任何有意义的指令和数据,
它该怎么办呢?
先看看内存的特点。
为节约成本,并提高容量和集成度,
在内存中,每个比特的存储都是靠一个极其微小的集体管,
外加一个同样极其微小的电容来完成的。
可以想象,
这样微小的电容,其泄漏电荷的速度当然也非常快。
所以,个人计算机中使用的内存需要定期补充电荷,这称为刷新。
所以,这种存储器也称为动态随机访问存储器。
随机访问的意思是,
访问任何一个内存单元的速度和它的位置【地址】无关。
对于内存,读写地址为0x00001的内存单元,和读写地址为0xFFFF0的内存单元,
所需要的时间是一样的。
在内存刷新期间,处理器将无法访问它。
最麻烦的是,在它断电之后,
所有保存的内容都会统统消失。
所以,每当处理器加电之后,它无法从内存中取得任何指令。
基本输入输出系统
Intel 8086可以访问1MB的内存空间,地址范围为0x00000到0xFFFFF。
由于各方面的考虑,
计算机系统的设计者将这1MB的内存空间从物理上分为几个部分。
8086有20根地址线,
但并非全部都用来访问DRAM,也就是内存条。
事实上,这些地址线经过分配,大部分用于访问DRAM,
剩余的部分给了只读存储器ROM和外围的板卡。
如00000~9FFFF属于DRAM,F0000~FFFFF给ROM。
与DRAM不同,只读存储器【ROM】不需要刷新,
它的内容是预先写入的,即使掉电也不会消失,但也很难改变。
利用这个特点,可以将一些程序指令固化在ROM中,
使处理器在每次加电时都自动执行。
处理器醒来后不能饿着,这是很重要的。
在以Intel8086为处理器的系统中,
ROM占据着整个内存空间顶端的64KB,物理地址范围是0xF0000~0xFFFFF,
里面固化了开机时要执行的指令;
DRAM占据着较低端的640KB。
地址范围是0x00000~0x9FFFF
中间还有一部分,分给了其他外围设备。
因为8086加电或者复位时,
CS=0xFFFF,IP=0x0000
所以,它取的第一条指令位于物理地址0xFFFF0,
正好位于ROM中,那里固化了开机时需要执行的指令。
处理器取指令执行的自然顺序是从内存的低地址往高地址推进。
如果从0xFFFF0开始执行,这个位置离1MB内存的顶端【物理地址0xFFFFF】
只有16个字节的长度,一旦IP寄存器的值超过0x000F,
比如IP=0x0011,则它与CS一起形成的物理地址将因为溢出而变成0x00001,
这将回绕到1MB内存的最低端。
所以,ROM中位于物理地址0xFFFF0的地方,通常是一个跳转指令,
它通过改变CS和IP的内容,
使处理器从ROM中较低地址处开始取指令执行。
在NASM汇编语言里,一个典型的跳转指令像这样:
jmp 0xf000:0xe05b
在这里,0xf000是要跳转到的段地址,用来改变CS寄存器的内容
0xe05b是目标代码段内的偏移地址,用来改变IP寄存器的内容。
因此,目标位置物理地址是0xfe05b。
一旦执行这条指令,处理器将开始从指定的"段:偏移"处开始重新取指令执行。
这块ROM芯片中的内容包括很多部分,
主要是进行硬件的诊断,检测和初始化。
所谓初始化就是让硬件处于一个正常的,默认的工作状态。
最后,它还负责提供一套软件例程,
让人们不必了解硬件细节的情况下从外围设备【比如键盘】获取输入数据,
或者向外围设备【比如显示器】输出数据。
设备当然是很多的,所以这块ROM芯片只针对那些最基本的,
对于使用计算机而言最重要的设备,
而它所提供的软件例程,也只包含最基本,最常规的功能。
正因为如此,这块芯片又叫做基本输入输出系统。【ROM-BIOS】
ROM-BIOS的容量是有限的,当它完成自己的使命后,
最后所要做的,就是从辅助存储设备读取指令数据,
然后转到那里开始执行。
基本上,这相当于接力赛中的交接棒。
硬盘及其工作原理
历史上,有多种辅助存储设备。
比如软盘,光盘,硬盘,U盘等,
相对于内存,它们就是人们常说的"外存",即外存储器。
从软盘启动计算机,已经是过去的事了。
在数据记录原理上和软盘很相似的设备是硬盘,而且它们几乎是同一个时代的产物。
但与软盘不同,
硬盘是多盘片,密封,高转速的,采用铝合金作为基片,
并在表面涂上磁性物质来记录二进制位。
这就使得它的盘片具有较高的硬度,故称为硬盘。
硬盘中间是用于记录数据的铝合金盘片,固定在中心的轴上,
由一个高速旋转的马达驱动。
附着在盘片表面的扁平锥状物,就是用于在盘片上读写数据的磁头。
硬盘可以只有一个盘片,也可能有好几个盘片。
但无论如何,它们都串在同一个轴上,
由电动机带动着一起高速旋转。
一般来说,转速可达每分钟3600转或7200转,有的能达到一万多转。
这个参数就是我们常说的"转/分钟"。
旋转运动,一个环形可划分为多个扇区。
磁头来回运动,用于在半径长度上分出多个磁道。
每个盘片都有两个磁头,上面一个,下面一个。
所以经常用磁头来指代盘面。
磁头都有编号,第一个盘片,上面的磁头编号为0,下面的磁头编号为1;
第二个盘片,上面的磁头编号为2,下面的磁头编号为3。以此类推。
每个磁头不是单独移动的。
相反,它们都通过磁头臂固定在同一个支架上,
由步进电机带动着一起在盘片的中心和边缘之间来回移动。
也就是说,它们是同进退的。
步进电机由脉冲驱动,每次可以旋转一个固定的角度,即可以步进一次。
可以想象,
当盘片高速旋转时,磁头每步进一次,
都会从它所在的位置开始,
绕着圆心"画"出一个看不见的圆圈,这就是磁道。
磁道是数据记录的轨迹。
因为磁头都是联动的,故每个盘面上的同一条磁道又可以形成一个虚拟的圆柱,称为柱面。
磁道或着柱面,也要编号。编号是从盘面最边缘的那条磁道开始,向着圆心的方向,
从0开始编号。
柱面是一个用来优化数据读写的概念。
初看起来,
用硬盘来记录数据时,
应该先将一个盘面填满后,再填写另一个盘面。
实际上,移动磁头是一个机械动作,看似很快,但对处理器来说,却很漫长,
这就是寻道时间。
为了加速数据在硬盘上的读写,最好的办法就是尽量不移动磁头。
这样,当0面的磁道不足以容纳要写入的数据时,应当把剩余的部分写在1面的同一磁道上。
如果还写不下,那就继续把剩余的部分写在2面的同一磁道上。
换句话说,
在硬盘上,数据的访问是以柱面来组织的。
实际上,磁道还不是硬盘数据读写的最小单位。
磁道还要进一步划分为扇区。
磁道很窄,也看不见。
但在想象中,它仍呈带状,占用一定的宽度。
将它划分许多分段之后,每一部分都呈扇形,这就是扇区的由来。
每条磁道能划分为几个扇区,取决于磁盘的制造者,但通常为63个。
而且,每个扇区都有一个编号,
与磁头和磁道不同,扇区的编号从1开始。
扇区与扇区之间以间隙【空白】间隔开来,
每个扇区以扇区头开始,
然后是512个字节的数据区。
扇区头包含了每个扇区自己的信息,主要有本扇区的磁道号,磁头号,扇区号。
用来供硬盘定位机构使用。
现代的硬盘还会在扇区头部包括一个指示扇区是否健康的标志,
以及用来替换该扇区的扇区地址。
用于替换扇区的,是一些保留和隐藏的磁道。
一切从主引导扇区开始
尽管我们使用硬盘的历史很长,但它一直没能退出舞台。
主要是因为它总是能通过不断提高自己的容量来打败那些竞争者。
前面说到,当ROM-BIOS完成自己的使命之前,
最后要做的一件事是从外存储设备读取更多的指令来交给处理器执行。
现实情况是,绝大多数时候,对于ROM-BIOS来说,
硬盘都是首选的外存储设备。
硬盘的第一个扇区是0面0道1扇区,或者说0头0柱1扇区,
这个扇区称为主引导扇区。
如果计算机的设置是从硬盘启动,那么,
ROM-BIOS将读取硬盘主引导扇区的内容,
将它加载到内存地址0x0000:0x7c00处【也就是物理地址0x07C00】,
然后用一个jmp指令跳到那里执行
jmp 0x0000:0x7c00
通常,主引导扇区的功能是继续从硬盘的其他部分读取更多的内容加以执行。
像windows这样的操作系统,就是采用这种接力的方法一步一步把自己运行起来的。
可以想象,如果我们把自己编译好的程序写到主引导扇区,
不也能让处理器执行吗?
好消息是,这是可以的。而且这几乎是在不依赖操作系统的情况下,
让我们的程序可以执行的唯一方法。
坏消息是,如果你改写了硬盘的主引导扇区,
那么,windows和linux,及任何你在用的操作系统会无法工作。
合适的方式是,在你现有的计算机上,再虚拟出一台计算机来。
创建和使用虚拟机
别害怕,虚拟机是软件
所谓虚拟机,就是在你的计算机上再虚拟出另一台计算机来。
这台虚拟出来的计算机,和真正的计算机一样,可以启动,可以关闭,
还可以安装操作系统,安装和运行各种各样的软件,或者访问网络。
总之,你在真实的计算机上能做什么,在它里面一样可以那么做。
使用虚拟机,你会发现,在windows操作系统里,居然又可以拥有另一套windows。
然而, 本质上,它只是运行在物理计算机上的一个软件程序。
虚拟机仅仅是一个软件,
运行在各种主流操作系统上。
它以自己运行的真实计算机为模板,虚拟出另一套处理器,内存和外围设备来。
它的处理能力,完全来自于背后那台真实的计算机。
尤其重要的是,
针对某种真实处理器所写的任何指令代码,
通常都可以正确无误地在该处理器的虚拟机上执行。
实际上,这也是虚拟机具有广泛应用价值的原因所在。
软件公司通常需要多台用于做实验的计算机。
采用虚拟机可以避免反复重装软件系统的麻烦,
当这些软件系统崩溃时,崩溃的只是虚拟机,
而真实的物理计算机丝毫不受影响。
虚拟机利用软件来模拟完整的计算机系统,无需添加任何新的设备。
而且与主计算机系统是隔离的,
在虚拟机上的任何操作都不会影响到物理计算机上的操作系统和软件。
下载和安装Oracle VM VirtualBox
主流的虚拟机软件包括VMWare,Virual PC和VirtualBox等,
但只有VirtualBox是开源和免费的。
参考下载,安装和配置VirtualBox软件的文档,完成安装,配置。
VirtualBox软件安装完毕之后,
你需要创建,或者说"虚拟"出一台计算机来,并设置"计算机"的相关参数。
包括为它配备一块硬盘。
和真实的计算机一样,
虚拟机也需要一个或几个辅助存储器【磁盘,光盘,U盘等】才能工作。
不过,为它配备的并非真正的盘片,而是一个特殊的文件,故称为虚拟盘。
这样,当一个软件程序在虚拟机里读写硬盘或者光盘时,
虚拟机将把它转换成对文件的操作,
而软件程序还以为自己真的是在读写物理盘片。
这样的一块磁盘,在需要的时候随时创建,不需要时随时删除。
本书配套源码和工具,解压后,在源代码和工具文件夹里有一个现成的虚拟硬盘文件。
文件名是LEECHUNG.VHD,这是额外准备的,且经过了测试。
可在无法创建虚拟硬盘时候派上用场。
不管是自己创建虚拟硬盘,还是用这个现成的。
都应当使虚拟硬盘文件位于源代码所在的文件夹,
将来往该虚拟硬盘写数据时比较方便。
市面上有好几种虚拟机软件,
每种虚拟机软件都企图制定自己的虚拟硬盘标准。
因为虚拟硬盘实际是一个文件,所以,所谓虚拟硬盘标准,
实际上就是该文件的格式。
正是因为这样,虚拟硬盘类似说白了就是你准备采用哪家的虚拟硬盘文件格式。
因为虚拟硬盘实际上是一个文件,所以,通常来说,
它的格式体现在它的文件扩展名上。
比如上面的LEECHUNG.VHD,采用的就是微软公司的VHD虚拟硬盘规范。
06年,微软公司正式发布了VHD虚拟硬盘格式规范。
本书配套的源代码和工具包里,有该规范的文档。
VDI是VirualBox自己的虚拟硬盘规范,VMDK是VMWare的虚拟硬盘规范。
采用哪个公司,哪个虚拟机软件的虚拟硬盘格式,
对于普通的应用来说,没什么关系。
但对于本书和本书配套的工具来说,
你必须选择VHD。
事实上,即使是VHD,也分为两种类型:固定尺寸的和动态分配的。
一个固定尺寸的VHD,它对应的文件尺寸和该虚拟硬盘的容量是相同的,
或者说是一次性分配够了的。
比如一个2GB的VHD虚拟硬盘,它对应的文件大小也是2GB。
注意,本书及本书配套工具仅支持尺寸固定的VHD。
一旦完成了全部的准备工作,
刚刚创建的虚拟机就会显示在VirtualBox控制台里。
基本上,你现在就可以单击控制台界面上的"开始"来启动这台虚拟机。
但是,别忙,你的虚拟硬盘里还没有东西呢。
虚拟硬盘简介
坦白地说,
之所以要采用固定尺寸的VHD虚拟硬盘,是因为其简单性。
我们知道,虚拟硬盘实际上是一个文件。
固定尺寸的VHD虚拟硬盘是一个具有".vhd"扩展名的文件,
它仅包括两个部分,前面是数据区,用来模拟实际的硬盘空间,
后面跟着一个512字节的结尾【2004年前的规范里只有511字节】。
要访问硬盘,
运行中的程序必须至少向硬盘控制器提供4个参数,
分别是磁头号,磁道号,扇区号,访问意图。
硬盘的读写是以扇区为最小单位的。
所以,无论什么时候,从硬盘读数据,向硬盘写数据,至少是1个扇区。
你需要自己跟踪和把握从扇区里读到的数据,哪些是你真正想要的。
换句话说,硬盘只是机械和电子的组合,它不会关心你都写了什么。
在VHD规范里,每个扇区是512字节。
VHD文件一开始的512字节,就对应着物理硬盘的0面,0道,1扇区。
然后,VHD文件的第二个512字节,对应着0面,0道,2扇区。
后面的以此类推,一直对应到0面,0道,n扇区。
这里,n等于每磁道的扇区数。
再往后,
因为硬盘的访问是按柱面进行的,
所以,在VHD文件中,紧接着前面的数据块,
下一个数据块对应的是1面,0道,1扇区。就这样一直往后排列。
当把第一个柱面全部对应完后,再从第二个柱面开始对应。
为了标志一个文件是VHD格式的虚拟硬盘,
并未使用它的虚拟机提供该硬盘的参数,
在VHD文件的结尾,包含了512字节的格式信息。
文件尾信息是以一个字符串"conectix"开始的。
这个标志用来告诉试图打开它的虚拟机,
这的确是一个合法的VHD文件。
该标志称为VHD创建者标识,
即【conectix公司】创建了VHD文件格式的最初标准。
从这个标志开始,
后面的数据包含了诸如文件的创建日期,VHD的版本,
创建该文件的应用程序名称和版本,创建该文件的应用程序所属的操作系统,
该虚拟硬盘的参数【磁头数,每面磁道数,每磁道扇区数】,
VHD类似【固定尺寸还是动态增长】,虚拟硬盘容量等。
为了学习汇编语言,我们不得不在硬盘上直接写入程序。
因为VHD格式简单,所以作者制作虚拟硬盘写入程序FixVhdWr也方便。
至于为什么要使用VirtualBox虚拟机,
因为它支持VHD,且免费。
练习使用FixVhdWr工具向虚拟硬盘写数据
通常,VHD是由虚拟机VirtualBox使用的。
应用程序像往常一样,直接针对硬盘进行操作,
而在底层,
虚拟机将这些硬件访问转化为对文件的读写。
为了在处理器加电或者复位之后能够执行我们写的程序,
势必要将这些程序写到硬盘的主引导扇区里,
也就是0面,0道,1扇区。
即使是在虚拟机工作环境中,也是这样。
FixVhdWr只针对固定尺寸的VHD。
当它启动后,
首先需要选择要读写的VHD文件。
一旦这是一个合法的VHD文件,它将读取该文件的结尾,并显示该虚拟硬盘的信息。
注意,
因为,FixVhdWr只针对固定尺寸的VHD,所以,
如果它检测到该VHD是一个动态虚拟硬盘,则禁止下一步。
最后,执行写入。
你应该选择第一种写入方式--LBA连续直写模式,并指定起始的逻辑扇区号。
通常,一个扇区的尺寸是512字节,可以看出一个数据块。
所以,从这个意义上来说,硬盘是一个典型的块设备。
采用磁头,磁道和扇区这种模式来访问硬盘的方法称为CHS模式,
但不是很方便,想想看,有一大堆数据要写,
还得注意磁头号,磁道号,扇区号不要超过界限。
所以,后来引入了逻辑块地址【LBA】的概念。
现在市场上销售的硬盘,无论哪个厂家的,都支持LBA模式。
LBA模式是由硬盘控制器在硬件一级上提供支持,所以效率很高,兼容性好。
LBA模式不考虑扇区的物理位置【磁头号,磁道号】,
而是把它们全部组织起来统一编号。
这种编址方式下,原先的物理扇区被组织成逻辑扇区,
且都有唯一的逻辑扇区号。
比如,某硬盘有6个磁头,每面有1000个磁道,
每磁道有17个扇区。
那么,
逻辑0扇区对应着0面,0道,1扇区。
逻辑1扇区对应着0面,0道,2扇区
。。。
逻辑16扇区对应着0面,0道,17扇区
逻辑17扇区对应着1面,0道,1扇区
逻辑18扇区对应着1面,0道,2扇区
。。。
逻辑33扇区对应着1面,0道,17扇区
逻辑34扇区对应着2面,0道,1扇区
。。。
扇区在编号时,以柱面为单位。
即,先是0面,0道。接着是1面,0道。
直到把盘面上的0道处理完,再接着处理下一个柱面。
之所以,这样做,
因为,要加快硬盘的访问速度,最好是尽可能不移动磁头。
因为这里总共有102000个扇区,故最后一个逻辑扇区的编号是101999。
它对应着5面,999道,17扇区。
也是整个硬盘上最后一个物理扇区。
LBA = C * 磁头总数 * 每道扇区数 + H * 每道扇区数 + (S - 1)
这里,LBA是逻辑扇区号,
C,H,S是想求得逻辑扇区号的那个物理扇区所在的磁道,磁头,扇区号。
对本书,VHD文件是按LBA方式组织的。
|