2

我是新手在线学习操作系统,其中提到了bootsect.s: https ://kernel.googlesource.com/pub/scm/linux/kernel/git/nico/archive/+/v0.99-pl8/ boot/bootsect.S 但是这段代码对我来说很奇怪:

        mov ax,#BOOTSEG
        mov ds,ax
        mov ax,#INITSEG
        mov es,ax
        mov cx,#256
        sub si,si
        sub di,di
        cld
        rep
        movsw
        jmpi    go,INITSEG

奇怪的部分是最后 3 行。根据我的理解,rep movsw已经把代码本身移走了,所以当pc指向jumpi并且计算机即将执行pc指向的代码时,应该会导致错误,因为代码jumpi go, INITSEG已经被移走了。那么为什么这段代码仍然有效并且jumpi go, INITSEG仍然可以找到并执行呢?

4

1 回答 1

3

OP的评论

...但是 pc 指向以#BOOTSEG 开头的部分,那里没有代码了。所以我想 jumpi go,INITSEG 不会执行。

放心,代码还在!

这是 BIOS 在线性地址 00007C00h 处加载引导扇区时填充内存的方式:

00007C00    mov ax,#BOOTSEG     ; 07C0h
00007C03    mov ds,ax
00007C05    mov ax,#INITSEG     ; 9000h
00007C08    mov es,ax
00007C0A    mov cx,#256
00007C0D    sub si,si
00007C0F    sub di,di
00007C11    cld
00007C12    rep movsw
00007C14    jmpi    go,INITSEG  ; Far jump (EAh, 19h, 00h, 00h, 90h)
00007C19    go:

一旦rep movsw指令执行完毕,位于 00090000h 的内存将包含在 00007C00h 找到的 512 个字节的精确副本。尽管此代码的作者声明代码自行移开,但这只是口头上的问题。它始终是创建的副本。源字节仍然存在,除非当然在 2 个内存区域之间存在重叠DS:SIES:DI但这里不是这种情况。

因此,指令指针将位于 00007C14h 并执行远跳转(段间)到go标签所在的线性地址 00090019h。
从这一点开始,可以忽略 00007C00h 处的 512 个字节。

于 2019-06-16T19:16:54.120 回答