先参阅 Bochs调试Linux内核 - 定位内核中的变量或数据结构_bcbobo21cn的专栏-CSDN博客
,运行到<bochs:1>,输入vbreak 0x0000:0x7c00,再输入c,执行到0x00007c00停住;
这个时候mov ax,0x7c0指令正好是linux启动程序bootsect.S的第一个有效指令,
(在bootsect.S中为 start:mov ax,#BOOTSEG);
说明BIOS在执行到0x7c00的时候,把控制权转移到了linux启动程序了;
Linux 启动程序包括三个文件。他们分别是:
Bootsect.S ,setup.S,head.s,他们都是由汇编写成的,这三个程序按一定的顺序执行各自不同的功能能来完成整个从引导到启动的整个过程;
启动顺序是:BIOS--Bootsect.S--setup.S--head.s---main.c
Bootsect.S代码是磁盘引导块程序。它的主要功能是:
1)把自己移到内存绝对地址0x90000的开始处,并跳到那里执行,也就是地址0x9000:0x0000处;
2)用13号BIOS中断来读磁盘的从第2个扇区开始的连续4个扇区内的内容,这部分内容就是setup程序模块,然后把这个内容放到bootsect紧接的后面。也就是地址0x90200.为什么是0x90200呢?后面要说道;
3)把system模块读到内存0x10000地方。这个system模块大小必须小于0x90000-0x10000=0x80000 也就是512k字节;
然后反汇编从现在开始的10条指令;
到0x00007c11的几条指令是把ds:[offset]开始的内容复制0x0100个字到es:0000开始的内存空间内。也就是从0x7c00处复制256字到0x9000.这就把bootsect搬家到了0x9000:0000地方了。长度是256个字,也就是 0x0200个字节。这就是为什么bootsect的后面是0x90200;
需要复制0x0100个字,cx是计数寄存器,把0x0100放入来cx中;
sub si, si:sub是减法指令,自己减自己,就是把si清零来;然后把di清零;
es是附加段寄存器;复制的目标是0x9000;把0x9000放入ax, 再把ax的值放入es;立即数不能直接放入段寄存器,参阅使用emu8086学习汇编mov指令_bcbobo21cn的专栏-CSDN博客;
,然后是rep指令;rep指令功能如下,
rep指令常和串传送指令搭配使用
功能:根据cx的值,重复执行后面的指令
串传送指令的说明如下;
串传送指令1: movsb
功能:(以字节为单位传送)
(1) ((es)×16 + (di)) = ((ds) ×16 + (si))
(2) 如果DF = 0则: (si) = (si) + 1
(di) = (di) + 1
如果DF = 1则: (si) = (si) - 1
(di) = (di) - 1
串传送指令2:movsw
功能:(以字为单位传送)
(1) ((es)×16 + (di)) = ((ds) ×16 + (si))
(2) 如果DF = 0则: (si) = (si) + 2
(di) = (di) + 2
如果DF = 1则: (si) = (si) - 2
(di) = (di) - 2
rep的执行示意如下图,
这里重复执行了 movsw 来进行复制;
先学这么多;