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

上一篇文章以一种更加高效的方法编写了主引导扇区的代码。主要是引入了循环和跳转指令。点击链接查看上一篇文章:编写主引导扇区代码-另一种更高效的写法

本篇文章,继续上一篇文章的学习。同样还是编写汇编代码加载到主引导扇区让CPU直接执行。但是我们以一个简单程序,实现1加到100,来引出8086中的结构。了解处理器访问栈需要哪些支持。

1、回顾

还记得前几篇文章,我们学会了编写主引导扇区代码,在显示屏显示字符串。最开始我们的做法是一个字符一个字符的传送给显存。后来发现可以先将所有需要传送的字符先存放到一块内存中,然后使用movsw连续传送这些字符串到显存更加方便。

今天我们的目的是,我们将我们想要显示的数字,先暂时存放到一种称为的结构中。最后我们再从栈中取出这些数字发送给显存。

2、代码清单

与前几篇文章一样,我们先提供汇编代码。遇到汇编代码不要害怕,脑子里将CPU,寄存器,内存这三个结构与他们的关系都勾勒出来,然后分析指令的执行,就会很清晰。

如果不懂,看后面的分析,如果你有一点基础,就一定能够学会!!!

         ;代码清单7-1;文件名:c07_mbr.asm;文件说明:硬盘主引导扇区代码;jmp near startmessage db '1+2+3+...+100='start:mov ax,0x7c0           ;设置数据段的段基地址 mov ds,axmov ax,0xb800          ;设置附加段基址到显示缓冲区mov es,ax;以下显示字符串 mov si,message          mov di,0mov cx,start-message@g:mov al,[si]mov [es:di],alinc dimov byte [es:di],0x07inc diinc siloop @g;以下计算1100的和 xor ax,axmov cx,1@f:add ax,cxinc cxcmp cx,100jle @f;以下计算累加和的每个数位 xor cx,cx              ;设置堆栈段的段基地址mov ss,cxmov sp,cxmov bx,10xor cx,cx@d:inc cxxor dx,dxdiv bxor dl,0x30     ;实际上应该是add指令,但是这可以是or指令,因为dl高四位为0,0x30低四位位0push dxcmp ax,0jne @d;以下显示各个数位 @a:pop dxmov [es:di],dlinc dimov byte [es:di],0x07              ;显示字符的颜色属性inc diloop @ajmp near $ times 510-($-$$) db 0db 0x55,0xaa

代码不长,大部分内容,在前几篇文章都学过。

3、代码分析

强烈建议先将上一篇文章学会,再阅读下面的代码解释会更加轻松:点击链接查看上一篇文章

这里分析会比较简洁,因为大部分代码的意思跟前几篇文章内容是一个意思,无非就是设置代码段数据段基地址与偏移地址,设置显存的基地址与偏移地址。然后将要显示的字符串经过计算得出结果并存起来。最后将这些字符串传送到显示缓冲区。

那么下面就开始分析:

  • 8行:就是想要显示‘1+2+3+…+100’,只不过这里先要将它存储在这里,好方便下面的循环传送。message是标号,代表它当前位置的汇编地址

  • 11-14行:设置数据段基地址与附加段基地址(也就是显存的基地址),这里前几篇文章已经讲了很多,不懂的可以回头看前面的文章。

  • 18-28行:将字符串‘1+2+3+…+100’显示出来。这里同样使用了循环的方法将字符串循环传送到显存。CX这里代表计数器,表示要传送的字符串的字节数。inc指令代表加1的意思。

  • 31-37行:计算1-100的和。这里将计算结果存到AX寄存器。CX每次加1是代表下一次要加的数。

  • 40-53行:计算累加和的各个数位。毕竟我们要显示这个累加和嘛,又不能直接将它发送到显示缓冲区直接显示,直接将它的各个数位拆解出出来显示。这几行,是我们今天要重要研究的汇编代码。它涉及到一个新的概念----栈

得到了累加和之后,前两篇文章,是将各个数位保存在数据段中。现在我们将各个数位保存在一个叫做栈的地方。

栈----是一种特殊的数据存储结构,数据的存取只能从一端进行。这样先进去的数据只能最后出来。后进去的数据倒是最先出来。

如下图:

和代码段,数据段和附加段一样,栈也是一种内存段,叫做栈段。由栈寄存器SS指向。

针对栈有两种操作方式:push和pop。这个应该大家都理解。压栈和出栈只能在一端进行。所以需要用栈指针寄存器SP来指示下一个数据应当压入到什么位置,或者数据从哪里弹出。

定义栈需要两个步骤。即指定SS和SP寄存器。为此40-42行,设置了SS和SP。他们都是指向0地址。

到目前为止,我们已经定义了3个段。如下图是我们当前程序的内存布局:

总内存容量是1MB,物理地址范围是0x00000-0xFFFFF

其中数据段长度是64KB(实际上它的长度无关紧要)占据的物理地址范围是0x07C00-0x17BFF,对应的逻辑地址为范围为 0x07C0:0x0000-0x7C00:0xFFFF;

代码段和栈段是同一个段,占据着物理地址0x00000-0x0FFFF,对应的逻辑地址的范围是0x0000:0x0000-0x0000:0xFFFF

虽然代码段和栈段在本质上指向同一块内存区域,但是通过后面的学习我们会知道,他们互不干扰。

分解各个数位还是要靠除法来做,44行将除数10传送给寄存器BX。

由于每次分解得到的数位都是压栈的,所以后面再出栈的时候,我们需要记住总共有多少个。这里用CX寄存器记录个数。所以45行,先将CX寄存器清零。

源程序第47-53行也是一个循环体,没执行一次,分解出一个数位。每次分解时,CX加1,表明数位又多了一个,这是源程序47行所做的事。其他指令较为简单治理不再赘述。

  • 57-62行:出栈,并显示各个数位。

这几行都比较简单。pop指令的意思是将逻辑地址SS:SP处的一个字弹出到寄存器DX中,然后将寄存器SP的内容加上操作数的字长(2)。

  • 64行:为了让我们看到显示屏的显示效果,这里是一个死循环,防止程序退出。

  • 67-68行:填充空的字节区间。然后最后的0x55和0xaa是主引导扇区的有效标志。

4、进一步认识栈

上述我们从代码层面第一次接触到栈这种结构。那么下面我们就来总结一下,做几点说明。

  1. push指令的操作数可以是16位寄存器或者16位内存单元。push指令执行后,压入栈中的仅仅是该寄存器或者内存单元中的数值
  2. 栈在本质上也只是普通的内存区域,之所以用push和pop指令来访问,是因为你把它看成栈而已。引入栈和push、pop只是方便程序开发而已。
  3. 要注意保持栈平衡。push多少,pop多少。
  4. 在编写程序时,必须充分估计所需的栈空间,以防止破坏有用的数据。
  5. 尽管不能完全阻止程序中的错误,但是,通过将栈定义到一个单独的64KB内存段,可以使错误仅局限于栈段,而不破坏其他段的有用数据。

5、运行程序

运行结果如下;

在这里插入图片描述

本次程序运行很顺利!!!

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

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

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

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

相关文章

【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像素…

【OS学习笔记】十二 现代处理器的结构和特点

本文是一个衔接点&#xff0c;上一篇文章以前都是学习8086实模式的知识。本文开始学习80386这种现代处理器的编程架构。由此进入保护模式的学习。点击链接查看上一篇文章&#xff1a;上一篇文章 1、现代处理器的结构和特点 1 流水线技术 处理器可以做很多事情&#xff0c;能…