汇编语言如何读取大容量硬盘最大容量

《汇编语言》课件            王爽 著-清华大学出版社 第17章 使用BIOS进行键盘输入和磁盘读写 17.1 int 9中断例程对键盘输入的处理 17.2 使用int 16h中断例程读取键盘缓冲区 17.3 字符串的輸入 17.4 应用int13h中断例程对磁盘进行读写 引言 大多数有用的程序都需要处理用户的输入键盘输入是最基本的输入。 程序和数据通常需要长期存儲磁盘是最常用的存储设备。 BIOS 为这两种外设的I/O提供了最基本的中断例程在本章中,我们对它们的应用和相关的问题进行讨论 17.1 int 9中断例程对键盘输入的处理 我们已经讲过,键盘输入将引发9 号中断BIOS 提供了int 9 中断例程。 CPU 在9 号中断发生后执行int 9中断例程,从60h 端口读出扫描码并將其转化为相应的ASCII 码或状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中 17.1 int 9中断例程对键盘输入的处理 一般的键盘输入,在CPU 執行完int 9 中断例程后都放到了键盘缓冲区中。 键盘缓冲区中有16 个字单元可以存储15个按键的扫描码和对应的入ASCII 码。 17.1 int 9中断例程对键盘输入的處理 下面我们按照键盘缓冲区的逻辑结构来看一下键盘输入的扫描码和对应 ASCII 码是如何写入键盘缓冲区的。 注意 17.1 int 9中断例程对键盘输入的处悝 注意: 在我们的课程中仅在逻辑结构的基础上,讨论BIOS键盘缓冲区的读写问题 其实键盘缓冲区是用环形队列结构管理的内存区,但我們不对队列和环形队列的实现进行讨论因为那是另一门专业课《数据结构》的内容。 17.1 int 9中断例程对键盘输入的处理 下面我们通过下面几個键: A、B、C、D、E、shift_A、A 的输入过程,简要地看一下int 9 中断例程对键盘输入的处理方法: 处理键盘输入演示 17.2 使用int 16h中断例程读取键盘缓冲区 BIOS提供了int 16h Φ断例程供程序员调用 int 16h 中断例程中包含的一个最重要的功能是从键盘缓冲区中读取一个键盘输入,该功能的编号为0 17.2 使用int 16h中断例程读取鍵盘缓冲区 下面的指令从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除: mov ah,0 int 16h 结果:(ah)=扫描码 (al)=ASCII码。 17.2 使用int 16h中断例程读取键盘缓冲区 丅面我们接着上一节中的键盘输入过程,看一下 int 16h 如何读取键盘缓冲区 int 16h读键盘缓冲区演示 17.2 使用int 16h中断例程读取键盘缓冲区 从上面我们可以看出,int 16h 中断例程的 0 号功能进行如下的工作: (1)检测键盘缓冲区中是否有数据; (2)没有则继续做第1 步; (3)读取缓冲区第一个字单元Φ的键盘输入; (4)将读取的扫描码送入ah,ASCII 码送入al; (5)将己读取的键盘输入从缓冲区中删除 17.2 使用int 16h中断例程读取键盘缓冲区 可见,B1OS 的int 9 中斷例程和int 16h 中断例程是一对相互配合的程序int 9 中断例程向键盘缓冲区中写入,int 16h 中断例程从缓冲区中读出 它们写入和读出的时机不同,int 9 中断唎程在有键按下的时候向键盘缓冲区中写入数据; 而int 16h 中断例程是在应用程序对其进行调用的时候将数据从键盘缓冲区中读出。 17.2 使用int 16h中断唎程读取键盘缓冲区 我们在编写一般的处理键盘输入的程序的时候可以调用int 16h 从键盘缓冲区中读取键盘的输入。 编程接收用户的键盘输叺,输入“r”将屏幕上的字符设置为红色:输入“g”, 将屏幕上的字符设置为绿色;输入“b ”将屏幕上的字符设置为蓝色。 程序源码 特别提示 检测点17.1(page294) 没有通过此检测点请不要向下进行! 17.3 字符串的输入 用户通过键盘输入的通常不仅仅是单个字符而是字符串。 下面我們讨论字符串输入中的问题和简单的解决方法 17.3 字符串的输入 最基本的字符串输入程序,需要具备下面的功能: (1) 在输入的同时需要显礻这个字符串; (2)一般在输入回车符后字符串输入结束; (3)能够删除已经输入的字符。 对于这三个功能我们可以想象在DOS 中,输入命令行时的情况 17.3 字符串的输入 编写一个接收字符串的输入子程序,实现上面三个基本功能因为在输入的过程中需要显示,子程序的参數如下: (dh)、(dl)=字符串在屏幕上显示的行、列位置

通过硬盘最大容量控制器端口读扇区数据

使用LBA逻辑块编址中的LBA28步骤如下
1. 设置读取的扇区数量,这个数值要写入0x1f2端口这是一个8位端口

每读一个扇区这个值都将减1
2. 设置起始LBA扇区号
扇区都是连续的所以只需要提供开头扇区号,一共需要28位的扇区号超过端口的大小,需要分成4段分别是0x1f3,0x1f4,0x1f5,0x1f6,依次是0~7位8~15位…

out dx, al ;端口0x1f6, 在这个端口中只需要提供4位,高位的4位是设置位第6位表示1时为LBA,0为CHS第4位表示1时为从硬盘最夶容量,0为主硬盘最大容量高3位全为1,表示LBA模式

4.等待硬盘最大容量进行读写操作
端口0x1f7也可以作为状态监控它的最高位为1时表示硬盘最夶容量忙,第3位为1时表示硬盘最大容量做好了和主机交换数据第0位为1表示错误发生,具体错误通过端口0x1f1查看

0x1f0是硬盘最大容量接口的数据端口并且是一个16位端口,一旦硬盘最大容量控制器空闲且准备就绪,就可以连续的从这个端口写入或读取数据

光标嘚位置使用两个8位的寄存器控制显卡的VGA文本模式是25行,每行80个字符从0开始到1999个字符。因为显卡寄存器众多所以使用索引寄存器,端ロ号为0x3d4向其写入值用来指定端口,控制光标位置的高8位和低8位寄存器索引值分别为0x0e和0x0f指定了寄存器之后,对其进行读写使用**数据端ロ**0x3d5

  其实很久之前就学完了实模式了但是一直没有总结,感觉现在直接在书上做笔记的弊端就是有些知识点不能很很深刻地记下来(毕竟手写最明显的优点就是能深刻哋记住知识但是就是用太多的时间罢了)。一下内容都是一些这本书里面的知识和笔记

★PART1:进制计数:

  1.  二进制到十进制的相互转換(带权乘法)

  a. 二进制转十进制,只要把每一个位都乘以2的相应阶数就可以了(无论是整数部分还是小数部分)

比如:*27+0*26+1*25+1*24+0*23+0*22+0*21+1*20=293D,其他进制(八进制十六进制)转十进制也是一样的,比如八进制转成十进制只用把上式2的多少次方改成8的多少次方,前面系数还是按照八进制數来定

      整数部分,就是直接的短除法

  比如将十进制数26转成二进制数就是上面这个样子如果是转成八进制或者十六进淛也是同理,只是相应的要把除数改为8或者16从最后一个余数往前写即是答案。

  小数部分如图(一直对小数部分乘以2直到小数部分為0)

  十进制整数转换成小数,有时候不一定能完全能把小数部分全部转化为0不是所有的十进制的小数都能完全可以转化为二进制,仳如4.7就是不能所以为什么浮点数最后可能会出现float x=4.7,而储存的是4.7000...001这样的事情

  3.  十六进制数和二进制数相互转换(比较重要)

  学编程其实就是和二进制数在打交道,但是二进制数写起来太长了为了方便人们发明了十六进制数,如果你在VS调试的时候转去内存的时候會看到一大堆十六进制数,一开始我不会十六 进制转成十进制看被别人笑了很久其实这个也很简单,直接一张表记住就好了有些复杂嘚转换直接用windows自带的计算器。

  同理八进制和二进制也有差不多的关系其实就是十六进制的0-7的那一个子集,但是用的不是很多

  a. 處理器是一台电子计算机的核心,它会在振荡器脉冲的激励下从内存中获得指令,并发起一系列由该指令所定义的操作当这些操作结束后,它接着再取下一个指令通常情况下,这个过   程是连续不断循环往复的。

  b. 处理器实际上是一个集成电路在处理器的底部或鍺四周,有大量的引脚可以接受从外面来的电信号,或者向外发出电信号处理器内部有一个基本部件:寄存器(Register),当引脚会向   处理器传送一系列电信号(如果处理器需要处理这些电信号)那么这些高低电平的组合(实际上代表二进制数),会被寄存器锁住然后引脚和線路会马上被用于其他操作(如果存在)。这些内部线路被称为处理器的内部总线

  c. 寄存器内的数据只能临时储存,而且寄存器是有夶小的有4位,8位16位,32位64位寄存器等等,这些分别代表着他可以储存4比特8比特,16比特32比特,64比特大小的数据

  2.  内储存器(内存)

  内存按字节来组织,单次访问的最小单位是1字节这是最基本的储存单元。内存的每个字节都对应着一个地址第一个字节的地址是0001H,第二个字节的地址是0002H以此类推。为了访问 内存处理器需要给出一个地址,访问包括读和写为此,处理器还要指明本次访问昰读访问还是写访问,如果是写访问则还要给出待写入的数据(这个在以后访问硬件经常看到这种用法)。处理器可以只通过一次访问來处理8位16位,32位或者64位数而不是依次取出一个一个字节来组合

  a. 关于高端字节序和低端字节序其实这个我之前有收录过一篇文嶂,里面讲的比较详细。

  b. 数据和指令都是一堆二进制数指令和数据要分开储存(当然你可以用指令去跳过数据区,这是后话了)存放指令的区域叫代码区,存放数据的区域叫数据区每个处理器都能识别有限个   指令,一个处理器能够识别的指令的集合称为该处悝器的指令集

  a. 8086处理器内部有8个16位的通用寄存器分别被命名为AX,BXCX,DXSI,DIBP,SP这些处理器的首字母和他的功能密切相关,比如AX是累加器(Accumulator)(与他有     关的指令还会做指令长度上的优化(把它们弄短));CX是计数器(Counter);DX是数据(Data)寄存器除了作为通用寄存器使用外,还专门用于和外设只见进行数据传送(比如in和out指  令);SI是源索引寄存器(Source Index);DI是目标索引寄存器(Destination Index)用于数据传送操作(以后会在movsb囷movsw指令中看到)。

  b. 处理器的内部寻址是不会用绝对内存地址(物理地址的)因为这样系统上运行的程序将无法重定位,为此处理器在访问内存的时候使用了分段机制,实际上处理器会把内存分段在分段   之后,各个地址只能相对于它自己所处的段中然后加上偏移哋址,就可以找到实际的物理地址了为了实现这个分段的功能,处理器至少需要提供两个段寄存器他们是代码段寄存器(CodeSegment,CS)和数据段寄存器(Data SegmentDS)。对CS的内容的改变将导致处理器从新的代码段开始执行同样,在开始访问内存中的数据之前也必须首先设置好DS寄存器,使之指向数据段

8086是一个16位的处理器,它有AXBX,CXDX,SIDI,BPSP这八个通用寄存器,同时前四个寄存器的每一个,都可以当成两个八位寄存器来使用分别是AH,ALBH,BLCH,CLDH,DL在进行数据传送或者算术逻辑运算时,使用算术逻辑部件(ALU)比如,将AX的内容和CS的内容相加结果仍在AX中,那么在想加的结果返回AX之前,需要通过一个叫数据暂存器的寄存器中转为了加快指令执行速度,8086内部有一个6个字节的指令預存队列在处理器忙着执行那些不需要访问内存的指令时,指令预存部件可以趁机访问内存预取指令这6个指令流可以排队等候解码和執行。

  d. 8086内部有是个段寄存器其中,CS是代码段寄存器DS是数据段寄存器,ES是附加段(Extra Segment)寄存器(一般用来指向显卡的0xb8000段)如果程序需要访问数据段,没有指定的时候一般默认的是DS 段,SS段是栈段寄存器专门用来管理程序栈。

  e. IP(Instrcution Pointer)是指令指针寄存器它只和CS一起使用,而且只有处理器才能直接改变他的内容当一段代码开始执行时,CS指向代码段的起始地址IP则指向段内偏移。这样由CS和IP共同形成邏辑地址。并由总线接口部件转换成物理地址来获得指令然后,处理器会自动根据当前指定的长度来改变IP的值使它指向下一条指令。

  f. 访问内存单元时处理器也会将数据段寄存器(DS,ES或者SS)和偏移地址相加得到访问内存所需要的物理地址。

  a. 8086的段寄存器和IP寄存器都是16位的如果直接把段地址和偏移地址相加,只能得到16位的地址但是16位的物理地址只能访问64KB的内存,这个实在是太小了所以8086有20根哋址线,可以提供20位的物理地址

8086在形成物理地址时,先将段寄存器的内容左移4位(相当于乘以十六进制的10或者十进制16),形成20位的段哋址然后再同16位的偏移地址相加,得到20位的物理地址比如,对于逻辑地址F000H:052DH处理器在形成物理地址的时候,将段地址F000H左移4位变成F0000H,洅加上偏移地址052DH就形成了20位的物理地址F052DH。

这样8086就可以访问1MB的内存内容了,在段不重叠的情况下最多可以将1MB的内存分成65536个段,每个段囸好是16字节也可以把段的长度扩大,段最大的长度是64KB(偏移地址是16位的)最多能分16个段,8086分配段地址时一定要保证段地址是可以被┿六进制的10,或者十进制16整除否则就不能形成有效的偏移地址。也就是说8086的逻辑分段是16字节对齐的。这个在以后写段编程的时候会体會到

★PART3:基本输入输出系统,硬盘最大容量

  1. 计算机的加电和复位

  a. 在处理器的引脚中有一个是RESET,用于接受复位信号每当处理器加电,或者RESET引脚的电平由低变高的时候处理器都会执行一个硬件初始化,以及一个可选的内部测试(Biuld-in Self-TestBIST),然后将内部所有寄存器初始化到一个预置的状态比如8086在初始化的时候,CS的内容会变为0xFFFF其他寄存器的内容都是0x0000,包括IP

  b. 内存的每个比特的储存都是靠一个极其微小的晶体管,外加一个同样极其微小的电容组成的这样微小的电容的漏电速度会非常快,所以内存需要定期补充电荷补充电荷的過程称为刷新,这种储存器也成为动态随机访问储存器(Dynamic Random Access MemoryDRAM)。在内存上访问任何一个内存单元的速度和它的位置无关这称为随机访问。内存刷新的时候处理器将无法访问它,内存断电后其保存的内容都会消失,所以每当处理器加电的时候它无法从内存中获得任何指令。

  a.  Intel 8086可以访问1MB的内存这1MB可访问区域被划分为几个区域,其中大部分用来访问内存条(DRAM地址0xFFFF,一共640KB)剩余部分给了只读存储器(ROM,地址0xF0000-0xFFFFF)和外围的板卡只读存储器(Read Only Memory,ROM)不需要刷新内容是预先设定的,断电了也不会消失也很难改变(不可擦写)。处理器每佽加电后都会自动执行这一个区域的代码因为8086加电或者复位的时候,CS=0xFFFF IP=0x0000,所以取的第一条指令位于物理地址0xFFFF0刚好是ROM的区域。

处理器的執行指令的顺序是从内存的低地址到高地址如果从0xFFFF0开始执行,那么这个位置距离1MB内存的顶端(物理地址0xFFFFF)只有16个字节的长度一旦IP寄存器的值超过0x000F,比如为0x0011那么它与CS一起形成的物理地址因为溢出而变成0x00001,绕回1MB内存的最低端所以在位于物理地址0xFFFF0的地方,一般是一个跳转指令使处理器在ROM较低的位置处开始执行指令。

ROM芯片的内容包括很多部分主要是对硬件的诊断,检测和初始化他还可以提供一套软件唎程(也就是后面要说到的BIOS中断),让人们不必了解硬件细节的情况下从外围设备(比如键盘)获得输入数据或者向外围设备(比如显礻器)输出数据,这块ROM芯片只针对那些最基本的而又最重要的设备,它所提供的软件例程也只包含最简单最常规的功能。所以这块芯爿又叫基本输入输出系统(Base Input & Output SystemBIOS)ROM。(正确的理解应该是ROM是一块芯片上面搭载了BIOS,而BIOS又可以对其他设备进行参数设置比如CMOS RAM。)

  a. 软盘光盘,硬盘最大容量U盘这些设备被称为是“外存”(外存储器)。软盘(Floppy Disk)一块以塑料作为基片上面涂磁性物质来记录数据的一个設备。硬盘最大容量(Hard DiskHDD)的记录数据方式与软盘很像,也是由磁性物质来记录数据的不过硬盘最大容量是多盘片,密封高转速的,采用铝合金作为基片并且在表面涂上磁性物质来记录二进制数据的一个存储设备。

  d. 硬盘最大容量可以有多个盘片也可以只有一个(单碟),这些碟片都是共轴的由电机带动转动,可以打到每分钟3600转或者7200转甚至上万转(转/分钟,Round Per MinuteRPM)。每个盘片都有两个磁头(Head)上面一个,下面一个所以经常用磁头来代指盘面。磁头都编号第一个盘片的而上面磁头编号是0,下面编号是1第二个盘片上磁头编號是2,下磁头编号是3依次类推。每个磁头通过磁头臂固定在一个支架上由步进电机带动着在一起在盘片的中心和边缘来回移动。盘片高速转动的时候磁头每步进一次,都会绕着圆心在盘面上“画”出一个看不见的圆圈这就是磁道(Track)。

磁道是记录数据的轨迹每个盤面上的磁道可以形成一个虚拟的圆柱,称为柱面(Cylinder)磁道或者柱面从最边缘往圆心方向开始从0开始编号。柱面是用来优化读写的因為移动磁头是一个机械动作,对于处理器来说是很慢的一个操作这就是所谓的寻道,所用的时间被叫做寻道时间为了加速读写,最好嘚办法是尽量不移动磁头所以当0面的磁道不足以容纳所写入的数据,应当把剩余的部分写在1面的同一磁道上如果还写不下,就写到2面嘚同一磁道上也就是硬盘最大容量上的数据访问是以柱面来组织的。

磁道还可以进一步划分为扇区(Sector)磁道占据一定的宽度,把他划汾为很多个区域后这些区域就会呈现扇形,所以这就是扇区名字的由来通常硬盘最大容量的每个磁道都会被划分为63个个扇区,每个扇區都有一个编号但是扇区的编号是由1开始的,扇区与扇区之间用空白间隙隔开每个扇区头开始,然后是512个字节的占据区每个扇区头嘟包含着每个扇区自己的信息,主要有本扇区的磁道号磁头号和扇区号,用来硬盘最大容量定位机构使用现代的硬盘最大容量在扇区頭加一个指示扇区是否健康的标志,以及用来替换该扇区的扇区地址用于替换扇区的,是一些保留和隐藏的磁道

  a. 在大多数情况下,ROM-BIOS会从硬盘最大容量的某个位置读取更多的指令加载到内存供处理器读取让处理器跳出ROM的区域。这个扇区是硬盘最大容量的第一个扇区(0面0道1扇区或者0头0柱1扇区),也就是主引导扇区(MBR)ROM-BIOS将会读取硬盘最大容量主引导扇区的内容,将其加载到内存的0xc00处然后用一个jmp指囹跳转到这个地方执行。

  b. 为什么要使用0xc00这个地址其实这是有原因的。

  来源作者:薛磊链接:来源:知乎,著作权归作者所有

  操作系统或是bootloader开发者必须假设 他们的汇编代码被加载并从0x7C00处开始执行。0x7C00的定义对于这个地址它不属于Intel x86平台规范的,而是属于BIOS规范Φ定义的内容0x7C00第一次出现在IBM PC 5150的BIOS处理int 19(19号中断)的时候,IBM PC 5150是x86(32位)IBM PC/AT系列的祖先这款PC于1981年发布,使用了intel 8088(16位)的处理器和16KB的RAM内存BIOS和微软嘚基本指令均放在该内存中。当打开电源BIOS开始自检,然后出发19号中断在处理19号中断时,BIOS检测电脑是否具有软盘、硬盘最大容量或是固萣磁盘如果有任何可以使用的磁盘,BIOS就把磁盘的第一个扇区(512B)加载到内存的0x7C00地址处

  0x7C00的前身 0x7C00地址第一次出现在IBM PC 5150的ROM BIOS中,在此之前使鼡的地址是0x200使用该地址的原因主要有:当时8086中断向量使用地址为0x0-0x3FF;86-DOS从0x400处被加载;而它不使用0x200-0x3FF这段中断向量地址。因此这段0x200-0x3FF地址不能被其怹程序使用Tim

      0x7C00的意义他们想留下32kb内更多的空间给操作系统来加载自己;使用0x0-0x3FF作为中断向量,然后BIOS数据紧随之后;引导扇区是512字节但是用於引导程序的栈或数据区域需要多于512 字节;因此0x7C00,32kb中的最后1kb被选中一旦操作系统被引导并开始,引导扇区将一直不会被使用指导重启洇此操作系统和应用程序可以自由的使用32KB的最后1kb空间。

我要回帖

更多关于 硬盘最大容量 的文章

 

随机推荐