第八章 硬盘和显卡的访问与控制

过程调用

编写过程的好处是只用编写一次,以后只需要调用即可。
8-1的第24~27行用于读取app_lba_start扇区的内容,即用户程序在硬盘上的起始逻辑扇区号。
因为不知道用户程序到底多大,占了多少个扇区,所以可以先读第一个扇区。

8-1,79~131行是编写的过程。
过程的第一条指令需要一个标号,以方便引用过程。read_hard_disk_0

每次读硬盘时的起始逻辑扇区号和数据保存位置都不相同,就涉及参数传递。
通过寄存器,主程序起始逻辑扇区号的高16位存放在DI中(高4位为0),低16位存放在SI中。并约定读出来的数据存放到DS指向的数据段中,起始偏移地址在BX

在过程的开头,将本过程要用到的寄存器临时压栈,并返回到调用点以前出栈恢复。
后面的内容在上一节基本涉及

       mov dx,0x1f2mov al,1out dx,al                       ;读取的扇区数inc dx                          ;0x1f3mov ax,siout dx,al                       ;LBA地址7~0inc dx                          ;0x1f4mov al,ahout dx,al                       ;LBA地址15~8inc dx                          ;0x1f5mov ax,diout dx,al                       ;LBA地址23~16inc dx                          ;0x1f6mov al,0xe0                     ;LBA28模式,主盘or al,ah                        ;LBA地址27~24out dx,alinc dx                          ;0x1f7mov al,0x20                     ;读命令out dx,al.waits:in al,dxand al,0x88cmp al,0x08jnz .waits                      ;不忙,且硬盘已准备好数据传输 mov cx,256                      ;总共要读取的字数mov dx,0x1f0.readw:in ax,dxmov [bx],axadd bx,2loop .readw

然后调用过程前各个寄存器的内容从栈中恢复。

加载用户程序

每次往内存中加载一个扇区前,都重新在前面的数据尾部构造一个新的逻辑段,并把要读取的数据加载到这个新段内。

    ;以下判断整个程序有多大mov dx,[2]                    ;起始的大小高16位和低16位分别存mov ax,[0]mov bx,512                     ;512字节每扇区div bxcmp dx,0jnz @1                         ;未除尽,因此结果比实际扇区数少1 dec ax                         ;已经读了一个扇区,扇区总数减1
@1:cmp ax,0                     ;考虑实际长度小于等于512个字节的情况 jz direct;读取剩余的扇区push ds                        ;以下要用到并改变DS寄存器 mov cx,ax                      ;循环次数(剩余扇区数)
@2:mov ax,dsadd ax,0x20                   ;得到下一个以512字节为边界的段地址mov ds,ax  xor bx,bx                      ;每次读时,偏移地址始终为0x0000 inc si                         ;下一个逻辑扇区 call read_hard_disk_0loop @2                        ;循环读,直到读完整个功能程序

用户程序重定位

用于加载用户程序的物理地址phy_base是16字节对齐的,而用户程序中,每个段的汇编地址也是16字节对齐的。因此,每个段在内存中的起始地址也是16字节对齐的,将它们分别右移4位,就是它们各自的逻辑段地址。

55行,从栈中恢复数据段寄存器DS的内容,使其指向用户程序被加载的起始位置,也就是用户程序头部。

第58~62行用于重定位用户程序入口点的代码段。用户程序头部内,偏移为0x06处的双字,存放的是入口点代码段的汇编地址。加载器首先将高字和低字分别传送到DXAX,然后调用过程calc_segment_base来计算该代码段在内存中的段地址、

  direct:mov dx,[0x08]mov ax,[0x06]call calc_segment_basemov [0x06],ax                   ;回填修正后的入口点代码段基址
calc_segment_base:                       ;计算16位段地址;输入:DX:AX=32位物理地址;返回:AX=16位段基地址 push dx                          add ax,[cs:phy_base];将用户程序在内存物理其实地址的低16位加到AXadc dx,[cs:phy_base+0x02];高16位加到DX中,adc是带进位加法,将目的操作数和源操作数相加,然后再加上CF位的值。分两步完成32位数的加法运算。shr ax,4ror dx,4and dx,0xf000or ax,dxpop dxret

DX:AX中得到了入口点代码段的起始物理地址,只需要将32位数右移4位即可得到逻辑段地址。

需要分别移动两个寄存器然后拼接。使用shr逻辑右移指令。(shl是逻辑左移指令)

注意,源操作数为1的逻辑右移指令是特殊设计的优化指令。

代码使用ror循环右移(ROtate Right),循环右移指令执行时,每右移一次,移出的比特既送到标志寄存器的CF位,也送进左边空出的位。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2EIJSXK1-1678975958324)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20230316174812359.png)]

ror循环左移,与shl,shr的指令格式是相同的。
DX循环右移四位后,DX的低12位是我们不需要的用and将其清零。
or ax,dx。将其内容合并。
现在回到62行,将计算出来的逻辑段地址写到原处覆盖低16位,高16位不用理会。

处理了入口点代码段的重定位,还要处理在用户程序的所有段,它们位于用户程序头部的段重定位表中。
重定位表的表项数存放在用户程序头部偏移0x0a处,65行,将它传到CX,供循环指令使用。
段重定位表的首地址存放在用户用于将它从该内存地址处存放在用户程序头部偏移0x0c处,因此,第66行,将0x0c传送到BX中。以后每次只要将BX的内容加上4,就指向下一个重定位表项。
68~74行是循环体,每次循环开始后,BX总是指向需要重定位的段的汇编地址,而且都是双字,需要分别传送到寄存器DXAX。然后调用过程calc_segment_base计算相应的逻辑段地址,并覆盖到原来的位置(低字),最后将基址寄存器的内容化加4,以指向下一个表项。当CX为0吗,循环结束,所有段处理完毕。

将控制权交给用户程序

此时,用户程序在内存中就绪,76行,加载器通过一个16位间接绝对远转移指令,跳转到用户程序入口点。

jmp far [0x04]访问DS所指向的数据段,从偏移地址为0x04的地方取出两个字,并分别传送到CSIP于是,处理器自行转移到指定位置开始执行。

第八章 硬盘和显卡的访问与控制(2)相关推荐

  1. [书]x86汇编语言:从实模式到保护模式 -- 第八章 硬盘和显卡的访问与控制,mbr加载并重定位应用程序

    第八章 硬盘和显卡的访问与控制 mbr加载.重定位用户程序 PART 1 >> VirtualBox显示最终效果 ===================================== ...

  2. 硬盘和显卡的访问与控制

    离开主引导扇区,前方是操作系统.         和主引导扇区程序一样,操作系统也位于硬盘是上.操作系统安装到硬盘上,安装过程不但要把操作系统的指令和数据写入硬盘,通常还需更新主引导扇区内容.    ...

  3. 19、硬盘和显卡的访问与控制

    文章目录 01.离开主引导分区 02.给汇编程序分段 03.控制段内元素的汇编地址 04.加载器和用户程序头部段 05.加载器的工作流程和常数声明 06.确定用户程序的加载位置 07.外围设备及其接口 ...

  4. 硬盘和显卡的访问与控制(二)——《x86汇编语言:从实模式到保护模式》读书笔记02

    上一篇博文我们讲了如何看到实验结果,这篇博文我们着重分析源代码. 书中作者为了说明原理,约定了一种比较简单地用户程序头部格式,示意图如下(我参考原书图8-15绘制的,左边的数字表示偏移地址): 所以, ...

  5. 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01

    本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...

  6. 硬盘和显卡的访问与控制(三)(含多彩的Hello)——《x86汇编语言:从实模式到保护模式》读书笔记03

    上一篇博文我们用了很大的篇幅说了加载器,这一篇我们该说说用户程序了. 先看作者的源码吧. ;代码清单8-2;文件名:c08.asm;文件说明:用户程序 ;创建日期:2011-5-5 18:17;=== ...

  7. 第8章 硬盘和显卡的访问与控制

    首先声明,这一章非常重要,如果刚开始读不懂,读不下去,一定要坚持,还有读这本书的一个要求是王爽<汇编语言>看两遍,并做完所有的课后实验.这一章其实是操作系统的的加载和引导过程.其中涉及的有 ...

  8. ubuntu下查看电脑内存硬盘CPU显卡驱动等配置命令

    ubuntu16.04查看电脑内存硬盘CPU显卡驱动等配置命令 按Ctrl+Alt+T键,调出终端窗口. 1.内存总大小:free -m mem:后面的 total 栏显示你的内存总大小. 如图:内存 ...

  9. cpu,内存条,硬盘,显卡,主板,显示器之间的关系

    cpu不能直接处理硬盘上的数据,操作系统将硬盘上的数据传输到内存条上,cpu再处理内存条上的数据,如果是图像则通过显卡在显示器上输出,如果是声音数据则被发送到声卡. cpu,内存条,硬盘,显卡都是插在 ...

最新文章

  1. 《程序员跳槽全攻略》笔记
  2. ubuntu12.04安装KDevelop
  3. opencv学习(part1)--OpenCv框架介绍
  4. 分布式系统服务器要求,浅谈分布式系统
  5. 计算机关机键桌面,电脑桌面按钮关机关不了怎么办? 爱问知识人
  6. JavaScript 中遍历对象的属性 1
  7. 【git】前端使用git分支的开发流程
  8. open-falcon之query
  9. Windows 虚拟机介绍以及安装系统教程
  10. Pytorch总结十五之优化算法:AdaGrad、RMSProp、AdaDelta、Adam算法详解
  11. 创智播客微服务_传智播客黑马程序员首次对外发布JavaEE中级程序员学习路线图...
  12. 信号能量、功率、功率谱密度、自相关函数公式总结
  13. python爬饿了么数据_爬取饿了么区域商家分布
  14. java中412是什么错_412错误是什么 412错误怎么解决
  15. (Tekla Structures二次开发)将报表模板数据写入文本文件
  16. 机器学习规则学习_使用机器学习发现动作规则
  17. jquery填充列表内容
  18. 程序员辞职回老家山洞写代码,二年敲了 45 万行!
  19. 【Cocos2D-x 3.5实战】坦克大战(1)环境配置
  20. 成都拓嘉辰丰电商:拼多多全店推广的作用

热门文章

  1. 【Software-vscode】用vscode调试ruby 和 ruby for Sketchup
  2. 陈耀烨必将开启属于自己的围棋时代
  3. 一套采用ASP.NET开发的工作通OA协同办公系统源码 流程审批 公文流转 文档管理
  4. 机场精细化管理_新形势下机场强化精细化财务管理的有效措施
  5. 红旗Linux启动修复,红旗linux系统,重启后就进入grub,不能开启Linux,请教高手!!!!!!...
  6. MySQL适配达梦数据库注意事项
  7. 复合材料缠绕 matlab,基于热芯缠绕工艺的缠绕张力研究
  8. STM32单片机K型热电偶温度采集及控制温控模块MAX6675热电偶LCD1602
  9. 游戏的聊天小设计——弹幕聊天
  10. 三菱fx3u与三菱变频器modbus rtu通讯程序。程序有注释