【OS学习笔记】八 实模式:编写主引导扇区代码-另一种更高效的写法

学习交流加

  • 个人qq:
    1126137994
  • 个人微信:
    liu1126137994
  • 学习交流资源分享qq群:
    962535112

上一篇文章,我们用比较原始的方法编写了主引导扇区的代码。点击链接查看上一篇文章:编写主引导扇区代码

本片文章将学习以下内容:

  • 用一种不同的分段方法,从另一个不同的的角度理解处理器的分段内存访问机制
  • 使用循环和条件转移指令来优化上一篇文章的主引导扇区代码

文章目录

  • 1、代码清单
  • 2、代码分析
  • 3、编译运行
  • 4、总结

1、代码清单

首先先贴上代码。50行代码,不长。看到汇编不要害怕!!!后面会一步一步分析这个汇编代码的每一条指令的意思。

		 ;代码清单6-1;文件名:c06_mbr.asm;文件说明:硬盘主引导扇区代码; jmp near startmytext db 'L',0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07,\'f',0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07number db 0,0,0,0,0start:mov ax,0x07c0  ;设置数据段基地址 mov ds,axmov ax,0xb800     ;设置附加段基地址,也就是将ES寄存器指向显存的起始地址 mov es,axcld                   ;方向清零标志,将DF标志位清零,代表传送是正向的mov si,mytext        ;SI与DS组成数据段的地址 DS:SI 代表数据的真实物理地址                mov di,0             ;DI与ES组成显存的物理地址 ES:DI 代表显存的真实物理地址mov cx,(number-mytext)/2   ;实际上等于 13rep movsw            ;循环movsw,直到cx寄存器内容为0(rep指令代表反复传送);得到标号所代表的偏移地址mov ax,number;计算各个数位mov bx,axmov cx,5               ;循环次数 mov si,10              ;除数 digit: xor dx,dxdiv simov [bx],dl            ;保存数位inc bx 				  ;使bx寄存器里的值加1loop digit;显示各个数位mov bx,number 		 ;将number的汇编地址传送给BX寄存器mov si,4              ;bx+si 得到字符串的每一个字符,SI从4递减到0,这是由于要先显示万位上的数字show:mov al,[bx+si]add al,0x30			;得到它对应的ASCII码mov ah,0x04		    ;对应的颜色属性mov [es:di],ax		;AX中是一个完整的字,前8位是显示属性值,后8位是字符的ASCII码add di,2	  ;DI寄存器在之前用过,现在在“Label offset:” 字符串后面,刚好我们想让number的汇编地址在这里显示dec si	      ;SI-1,从number代表的汇编地址的万位到个位,dec指令会影响SF标志位,当SI寄存器的值为0的时候,SF的标志位置1jns show	 ;判断SF标志位是否为0,当SF标志位不为0,继续执行show处的代码。当SF标志位为0,则跳过这条指令执行下一条指令。mov word [es:di],0x0744	;高字节0x07是黑底白字的属性,低字节0x44是字符‘D’的ASCII码jmp near $   				;相当于 infi: jmp near infitimes 510-($-$$) db 0           ; 计算512字节中,需要填满的字节有哪些。db 0x55,0xaa   ;一个有效的主引导扇区,最后两字节必须是0x55 0xaa

2、代码分析

坚持看完,一定能看懂!!!

  • 8行-9行:这里声明了非指令的数据。一般来说,所有处理器指令都是按顺序存放,在他们中间不允许夹杂非指令的数据。但是如果有办法让处理器不执行这些数据,则又另当别论。如第6行的代码。

这两行声明的是要在显示屏上显示的数据:"Label offset: ",其中0x07是每个字符的显示属性值。

  • 6行:它是一条转移指令。让处理器跳转到标号start处开始执行。这就避开了数据区。
  • 13-14行:设置数据段的基地址。DS代表数据段的基地址。

这里为什么是0x07c0呢?

由上几篇文章学过的知识知道,主引导扇区程序加载时,被加载到的位置是0x0000:0x7c00.也就是物理地址:0x07c00 这其实就是将整个物理地址空间看成是基地址0x0000,偏移地址0x7c00的分段方式。

这样的话,CPU每次访问内存的时候总是要加上0x7c00这个偏移地址。但是程序中一般访问内存的指令非常多,每一条都加上0x7c00很不现实。

但是Intel处理器的分段策略很灵活。逻辑地址0x0000:0x7c00对应的物理地址是0x07c00 ,而该地址又是另一个逻辑地址0x07c0:0x0000的地址。如下图是以两个逻辑段的视角看待同一个内存区域。

我们可以将512字节的区域看成是一个单独的段。段的基地址是:0x07c0 段长512字节。注意,该段的最大长度是64KB,但是这里我们实际上只用了512字节。尽管BIOS是将主引导扇区加载到物理地址0x07c00处,但是我们却可以认为它是从0x07c0:0x0000处开始加载的。

所以13-14行将数据段寄存器DS指向0x07c0

  • 16-17行:使附加段寄存器ES的内容指向显存的基地址0xb800
  • 19-23行:循环movsw,直到cx寄存器内容为0(rep指令代表反复传送)。这里是循环将DS:SI所指向的数据传送到ES:DI所指定的显示缓冲区。

循环movsw与movsb指令执行时,将DS:SI所指向的数据传送到ES:DI所指定地址。同时每传送一次 ,CX寄存器的内容减一。

rep代表循环movsw,直到寄存CX的内容为0为止。所以22行中,计算出数据的字节数,并将其传送到CX寄存器。

20行将SI指向数据区的首地址,SI与DS组成数据段的地址 DS:SI 代表数据的真实物理地址

21行将0给DI寄存器,DI与ES组成显存的物理地址 ES:DI 代表显存的真实物理地址。很明显,我们是从显存的0偏移地址开始存数据。

19行,方向清零标志,将DF标志位清零,代表传送是正向的。**正向的意思是传送操作的方向是从内存的低地址端到搞地质端。**很明显我们是正向传送。

  • 26行:我们还是想像上一篇文章一样,显示字符串后将number这个标号的数值显示出来。所以先将number标号的汇编地址传送给AX寄存器保存。后面会用。

  • 29-37行:还记得上一篇文章是如何分解number的各个数位的么?如果不记得,请点击链接查看:上一篇文章 上一篇文章是一个一个分解然后保存的。这里有所改变。使用了循环,可以让我们少写很多代码。这里就不多说了,不懂的看上一篇文章,这个循环也很好理解,loop这个指令将循环次数CX减一,指导CX等于0为止。

  • 40-49行:显示标号number的汇编地址的各个数位。同理,如何显示各个数位,可以查看上一篇文章。这里只是将重复的代码,写成了循环的形式。

jns这个指令判断SF标志位是否为0,当SF标志位不为0,继续执行show处的代码。当SF标志位为0,则跳过这条指令执行下一条指令。

dec指令会影响SF标志位,当SI寄存器的值为0的时候,SF的标志位置1

这里唯一需要注意的是低端字节序传送的时候,寄存器的低字节传送到显示缓冲区的低地址部分,寄存器的高字节传送到显示缓冲区的高地址部分。如下图所示:

  • 51行:显示字符‘D’
  • 53行:死循环
  • 55行:计算512字节中,空字节有多少,然后将这些空字节填满0

$ 代表当前行的汇编地址
$$ 代表当前段的起始地址。由于本程序没有定义段,所以自成一个段,并且起始地址是0地址。

  • 56行:一个有效的主引导扇区,最后两字节必须是0x55 0xaa

3、编译运行

将我们汇编代码编译好的二进制bin文件写到虚拟硬盘的主引导扇区中。启动虚拟机,就会运行我们写的代码,运行结果如下:

在这里插入图片描述

今天的程序运行的很顺利。

4、总结

了解汇编的运行机制,对以后深入学习高级语言,很有帮助:比如JVM。

笔记记得不是很全,像汇编的语法以及如何将代码写到虚拟硬盘的主引导扇区这些都没有写。如果又不懂的可以加我联系方式一起交流。

学习探讨加个人:
qq:1126137994
微信:liu1126137994

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OS学习笔记】九 实模式:从汇编的角度理解栈结构

上一篇文章以一种更加高效的方法编写了主引导扇区的代码。主要是引入了循环和跳转指令。点击链接查看上一篇文章:编写主引导扇区代码-另一种更高效的写法 本篇文章,继续上一篇文章的学习。同样还是编写汇编代码加载到主引导扇区让CPU直接执行。但是我们…

【OS学习笔记】十 实模式:实现一个程序加载器-程序加载器如何将用户程序加载到内存并执行

上一篇文章学习了以下内容: 用一种不同的分段方法,从另一个不同的的角度理解处理器的分段内存访问机制使用循环和条件转移指令来优化主引导扇区代码 点击链接查看上一篇文章:点击链接查看 对于主引导扇区部分。大概前几篇文章已经学的差不…

【OS学习笔记】十一 实模式:中断-软中断和硬中断基本原理

上一篇文章我们模拟操作系统的加载器程序,使用汇编语言实现了一个程序加载器:点击链接查看上一篇文章:程序加载器的实现原理 本篇文章,是实模式学习的结尾。在经过了那么多坎坷,终于学完了8086的实模式!&a…

配置节处理程序时出错,未能加载文件或程序集

安装sql server2008时,出现下面的错误: 按照上面的提示,查看那个路径下的文件,根据文件名判断可能是临时文件,于是首先将上面的文件剪切出来,然后安装,成功。 转载于:https://www.cnblogs.com/x…

【软件开发底层知识修炼】六 Binutils辅助工具之- addr2line与strip工具

学习交流加 个人qq: 1126137994个人微信: liu1126137994学习交流资源分享qq群: 962535112 上一篇文章我们学习了gcc编译器的相关内容。点击查看上一篇文章:gcc编译器。本篇文章接着上一篇文章,学习GNU为GCC提供的辅助开…

Eboot 中给nandflash分区实现

提到分区就不得不提到MBR,不得不提到分区表。 什么是MBR 硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主…

kmp匹配算法

kmp匹配算法1.第一种方式是暴利匹配方式2.第二种方式采用kmp 方式进行匹配3. 相应的代码1.第一种方式是暴利匹配方式 暴利匹配规则 模型: str1 位源字符串下标为i,str2位匹配字符串,下标为j 。 假设 str1 匹配到i , str2 匹配到j 则有 (1)当 …

【软件开发底层知识修炼】七 Binutils辅助工具之- ar工具与nm工具

学习交流加 个人qq: 1126137994个人微信: liu1126137994学习交流资源分享qq群: 962535112 上一篇文章学习addr2line与strip工具。点击链接查看上一篇文章:点击查看 本篇文章学习两个工具:ar与nm工具。 文章目录1、ar工…

【软件开发底层知识修炼】八 Binutils辅助工具之- objdump工具 与 size,strings工具

上一篇文章学习了ar工具与nm工具,点击链接查看上一篇文章:点击链接 本片文章学习记录以下三个工具: objdumpsizestrings 1、objdump工具 用法: 反汇编目标文件,查看汇编到源码的映射(后面代码案例分析看具体区别&a…

【C++深度剖析教程39】实现C++数组类模板

上一篇文章在那个学习了多参数类模板与特化的分析:点击链接查看上一篇文章:类模板深度剖析 本篇文章学习记录: 数值型模板参数实现C数组类模板 1、模板中的数值型参数 模板参数可以是数值型参数。也就是非类型参数。如下图所示&#xff1…

前端学习(168)全局事件属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/ TR/html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>事件</ti…

【原】两个时间相加的运算符重载实现

要求&#xff1a;两个时间相加&#xff0c;得到的时间形如“xx时&#xff1a;xx分&#xff1a;xx秒” -------------------------------------------------------------------------------------------------------------- 解答&#xff1a; 首先编写时间处理类 时间类 1 ///&l…

IOT变现

IOT&#xff08;物联网&#xff09;变现1. IOT 设备基础结构2.IOT 组成元素3.从M2M扩展到IOT的世界4. 工业4.0最近在看IOT变现&#xff0c;记录一下核心的知识点概念&#xff1a;IOT 是利用无线标签&#xff0c;传感器&#xff0c;MEMS(micro-ElectroMechanical System&#xf…

【C++深度剖析教程40】使用数值型模板技术计算1+2+3+...+N的值

上一篇文章学习了数值型模板技术&#xff0c;并利用相关技术&#xff0c;实现了C的数组类模板。点击文章查看上一篇文章&#xff1a;点击链接查看 本篇文章&#xff0c;继续利用模板技术来解决一个问题。 如果想求123…N的结果&#xff0c;有很多种方法。可以循环遍历&#x…

前端学习(169):无语义元素

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>无语义标签&…

dubbo思维导图

dubbo思维导图之前总结的 后续持续更新中

前端学习(170):无语义元素二

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>DIVCSS布局&…

【软件开发底层知识修炼】九 链接器-可重定位文件与可执行文件

上几篇文章学习了Binutils辅助工具里面的几个实用的工具&#xff0c;那些工具对于以后的学习都是非常有帮助的&#xff0c;尤其是C语、C语言的学习以及调试是非常有帮助的。点击链接查看上一篇文章&#xff1a;点击查看 本篇文章开始一个新的知识的学习&#xff0c;链接器的学习…

【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数

上一篇文章&#xff0c;大概了解了链接器的工作内容就是&#xff1a;符号解析和重定位。点击上一篇文章查看&#xff1a;点击查看。 本片文章其实还是围绕链接器来学习。只不过不是很明显&#xff0c;当你学到下一篇文章时&#xff0c;就明白了。 本篇文章来弄明白一个问题&a…

分享博文摘要图标【11/16更新】

经常写文章&#xff0c;希望给朴素的浏览界面添加一些生动的图标&#xff0c;让浏览者直接通过图片来得知这篇文章讲的是什么&#xff1f; &#xff08;效果预览...&#xff09; 博主特意搜集并上传了一些大家可能会用到的图标&#xff0c;提供16、32、48、64、128、甚至256像素…