在那篇文章 Linux源码进修条记 day1 开机时若何加载系统?我们进修到开机后会修改段存放器ds为 0x07c0,便利之后操纵那个段基址停止内存寻址。

此次我们次要进修以下几行代码:

.equ INITSEG, 0x9000mov $INITSEG, %ax #将es段存放器设置为0x900mov %ax, %esmov $256, %cx sub %si, %si sub %di, %di rep movsw

第一行先 定义常量INITSEG 为0x9000。

然后取出INITSEG的值 给到通用存放器ax。

接着把ax给到了 段存放器es。那时候es里的值就是0x9000了。

然后把立即数 256 给到了 通用存放器 cx(一般cx 用做计数器)。

接下来2个 sub 指令,就是把 si 和 di都清零了。

如今ds, es, cx, si, di都有值了。

ds = 0x07c0es = 0x9000cx = 256si = 0di = 0

关键存放器就酿成了如许。

Linux源码学习笔记day2 开机后BIOS是怎么从硬盘复制到内存?  第1张

接下来的指令:

rep movsw

那里rep 是反复的意思,movsw是复造一个字。就是不竭地复造一个字。

那里扩展一下:

一个字节是8位一个字是16位Linux源码学习笔记day2 开机后BIOS是怎么从硬盘复制到内存?  第2张

MOVS 是串指令里的串传送:

MOVSB 传送字符MOVSW 传送字.MOVSD 传送双字

一般来说 cx里有值,就意味要有轮回了。

轮回的次数:就是cx的值256。退出前提就是cx == 0

从哪儿复造到哪儿:从ds:si 复造到es:di,也就是0x7c00 复造到0x90000。

一次复造2个字节,复造256次 正好是复造了512个字节!也就是说将内存地址 0x7c00 处起头往后的 512 字节的数据,复造到 0x90000 处起头的后面 512 字节的处所

也就是那里的第二步:

Linux源码学习笔记day2 开机后BIOS是怎么从硬盘复制到内存?  第3张

接下来是一个跳转指令:

ljmp $INITSEG, $go #段间跳转,那里INITSEG指出跳转到的段地址,解释了cs的值为0x9000go: mov %cs, %ax #将ds,es,ss都设置成挪动后代码所在的段处(0x9000) mov %ax, %ds

做者那里是8086的指令里是jmpi,我看的那个是AT&T指令,那里是ljmp。

归正意思都是段间跳转。那里因为INITSEG是0x9000 所以就是要跳转到0x9000:go的地址。段基址要左移4位,所以最初要跳转到0x90000 + go的内存地址。

那个go: 在那里是一个标签(label),编译成机器码的时候会酿成一个值,就是段内偏移地址。

那时候,假设偏移量是0x10,其实就是那一行代码

mov %cs, %ax

所在的内存地址就是 0x90000 + 0x10 = 0x90010 CPU最末就会跳转到0x90010处。

Linux源码学习笔记day2 开机后BIOS是怎么从硬盘复制到内存?  第4张

下一次,我们一路看看go里面又发作了哪些”出色“?

若是你觉得有点收成,欢送点个存眷, 也欢送分享给你身边的伴侣。

#头条创做挑战赛##法式员##Linux#