4.跳出第一个扇区
2015-06-17 20:52
169 查看
背景:
上文讲到,把操作系统挤到一个扇区里面实在是太委曲了。所以要跳出第一个扇区的限制。实现方法就是:
(1)把部分代码放到其它扇区
(2)加载其它扇区到内存
(3)跳转到其它扇区中要运行的第一条指令
在3中已经实现了第(2)步,加载扇区2-18至内存0x9000:0x1000处,这一节将介绍(1)和(3)
需求:
1.写一段测试代码,测试代码中包含打印信息(第一行屏幕中间打印‘A’),可以明确知道该代码是否执行到了2.修改makefile,使测试代码经过编译、链接,最终放入img中从第二个扇区开始的位置
3.修改boot.S,在加载完其它扇区后,主动跳转到测试代码的第一条指令,并执行测试代码。
运行效果:
代码:
boot.S代码修改及说明:
第1处修改:修改上一节中的一个BUG。
两个值相加的同时把结果存入寄存器会导致编译失败。
应该先把其中一个值存入寄存器,然后让寄存器加另一个值。
第2处修改:
根据上文已知,2-18扇区的数据已经读入到内存上从0x9000:0x0100开始的位置了,所以直接跳转到这个位置就可以了。
第3处修改:
此处省略N行
把BaseOfLoader和OffsetOfLoader的定义移到最前面去了,否则
jmp $BaseOfLoader,$OffsetOfLoader会提示错误。
但是指令是从上往下执行的。真正的第一条可执行指令是
mov %cs, %ax这句,为了能正确找到第一条指令,在.set的前面加了一句跳转。
makefile代码修改及说明
第1处修改:新增加一个链接脚本文件,因为需求中说明要新写一个测试代码,这个链接脚本文件就是给测试代码使用的。
为了表示区分,同时将原脚本文件定义为LDFILE_BOOT
第2处修改:
这一部分没有做什么实质性的修改,只是把代码和注释移了一下位置。
第3修改:
此处增加了另一个文件loader.S的编译链接过程。
loader.S就是我们的测试代码。
loader.S的编译链接和boot.S是一样的,只是用的链接脚本不一样。
第4处修改:
第1个扇区仍然是存放boot.bin
第2-13个扇区存放的是loader.bin
剩余2866个扇区仍然为空
第5处修改:
这个makefile文件改好以后,很长一段时间内不会再去修改它了。
新增代码loader.S说明
完整源码:.code16 .text mov %cs, %ax mov %ax, %ds mov %ax, %es mov %ax, %ss mov $0xb800, %ax mov %ax, %gs mov $0xA, %ah mov $'A', %al mov %ax, %gs:((80*0+39)*2) jmp .
详细说明:
mov %cs, %ax mov %ax, %ds
此处的%cs已经不是0了,而是0x9000,也就是这段代码的代码段。
在这个文件中,代码段和数据段仍然属于同一个段,因此也要把%ds设置为0x9000。
不过其实这段代码在今天的应用中,所有的数据都是立即数,并没有用到数据段,同样也没有用到%es和%ss,不写也没有关系。
但为了避免以后用到了导致代码出错,这里先加上了。
mov $0xb800, %ax mov %ax, %gs mov $0xA, %ah mov $'A', %al mov %ax, %gs:((80*0+39)*2)
这一段是用于在屏幕上显示字符的,使用了与boot.S中不同的方法。
问:怎样显示字符?
答:屏幕文件字符显示的缓冲区位置内存物理地址0xb8000-0xb8fff的区间内。其中0xb8000和0xb8001分别存放的是左上角第一个字符的颜色值和ASCII值。
我们所采用的显示字符方法就是:把字符放到内存中对应屏幕显示的位置去。
问:怎么计算屏幕坐标(行:x,列:y)对应的内存地址?
在当前的显示模式中,一行宽度为80个字符,一个字符的宽度是8bit
屏幕位置(行:x,列:y)对应的内存地址就是0xb8000+(80*(x-1)+y-1)*2。
需求中所提到的第一行中间,就是0xb8000+(80*0+39)*2的位置了。
问:怎么访问这个地址呢?
答:我们把0xb800作为段基址,(80*0+39)*2作为段偏移,就刚好得到了这个地址。
新增代码wind_x86 _dos.ld说明
完整源码:SECTIONS { . = 0x0100; .text : { *(.text) } = 0 }
说明,这个脚本的内容和wind_x86.ld的内容几乎一样。只需要解释为什么起点是0x0100。
因为在DOS环境加调试汇编代码时要求起点是0x0100,这么写是为了兼容DOS中的汇编调试环境。
相关文章推荐
- Spring事务管理-使用注解配置事务
- 服务器开发的一点心得体会
- 【学习过程】拓扑排序
- 螺旋矩阵核心代码
- 为什么要用数据库?
- 新的征程,扬帆起航
- MapRecuce工作原理
- 机器夏娃
- bzoj 3924 点分
- UI数据库
- Hibernate和mybatis的区别
- 小球与盒子问题小结
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- alpha阶段总结
- LeetCode之Remove Duplicates from Sorted Array
- java开始
- Linux之必备软件安装(搜狗输入法、qq等)
- 如何学习:学习困难科目的实用思维(Coursera课程笔记,2015.6.17)
- 关于AndroidResideMenu开源项目的详解
- 2015东北四省赛 L题 线性筛+积性函数 求因子和