Linux0.11第2回从0x7c00到0x90000
上一次,上一次,我们说CPU执行操作系统的前两行代码。
movax,0x07c0movds,ax
数据段寄存器ds的值更改为0x07c0,以便以后访问存储器时使用该段基址进行寻址。
接下来,我们就拿这两行代码,继续往下看几行。
movax,0x07c0movds,axmovax,0x9000moves,axmovcx,#256subsi,sisubdi,direpmovw
此时,ds寄存器的值为0x07c0,然后es寄存器的值以相同的方式更改为0x9000,然后cx寄存器的值更改为256。
往下看,有两个子指令。这条子指令非常简单,例如
苏巴湾
这意味着
a=a—b
所以在代码中
子si,si
这意味着
硅=硅—硅
所以如果sub后面的两个寄存器相同,就相当于清除了这个寄存器里的值这是一个基本的游戏
那很简单在这些指令之后,下面的寄存器分别附加指定的值让我们把它们分类
ds = 0x07c0
es = 0x9000
cx = 256
si = 0
di = 0
还记得上节课画的CPU寄存器总图吗就这样了
为什么要给这些不相关的寄存器赋值呢。实际上,它服务于下一个指令,也就是
雷普莫夫
其中rep表示重复执行以下指令。
下面这个指令movw的意思是复制一个单词,其实就是反复复制一个单词。
下面自然有三个连续的问题:
重复了多少次是cx寄存器中的值,即256倍
从哪里复制到哪里是从ds:si复制到es:di
一次复印多少份刚才说了,复制一个字,16位,也就是两个字节
以上是直译,把这段话翻译成更人性化的语言的方法是把内存地址0x7c00的512字节数据原封不动的复制到0x90000。
这是下图中的第二步。
没错,就是这么回事现在,操作系统的初始代码已经移到了0x90000
然后就是跳转命令。
jmpigo,0x9000movax,csmovds,ax
仔细想想,也许你能猜到它想要什么。
Jmpi是段间跳转指令,意思是跳转到0x9000:go执行。
还记得上节课怎么计算段基址:偏移地址格式的内存地址吗段的基址还是需要先左移四位,所以结论是跳到内存地址0x90000+go执行如果忘了,赶紧回去看看只发生过一次稳扎稳打
况且go是一个标签,最终编译成机器码的时候会翻译成一个值这个值是文件中go标签的偏移地址
这个偏移地址加上0x90000就是go标签后面代码mov ax,cs的存储地址。
如果代码mov ax,cx位于最终编译的二进制文件的0x08,那么go等于0x08,CPU最终跳转到的地址是0x90008。
到目前为止,前两次的内容其实是一个512字节的代码和数据,先从硬盘的引导区移到内存0x7c00,然后马上移到内存0x90000,跳到这里再稍微移位到标签go代表的偏移地址,也就是mov ax,cs的位置。
还是要保持每次都简单本文到此为止希望大家能跟上下次让我们把目光放在go标签后面的代码上,看看他有什么好折腾的
我们身后的世界越来越精彩欲知后事如何,且听下回分解
财经排行榜
-
2022-09-30 18:40
-
2022-09-30 18:17
-
2022-09-30 18:08
-
2022-09-30 17:35
-
2022-09-30 17:34
-
2022-09-30 17:00
-
2022-09-30 15:47
-
2022-09-30 15:43
-
2022-09-30 15:14
-
2022-09-30 15:06
大家都在看
行业要闻
-
2022-09-30 14:53
-
2022-09-30 14:44
-
2022-09-30 14:19
-
2022-09-30 12:57
-
2022-09-30 12:40
-
2022-09-30 12:37
-
2022-09-30 10:07
-
2022-09-30 09:26
-
2022-09-30 08:44
-
2022-09-30 08:12