Search code examples
assemblyx86-16bootloaderas86

bootsect.s: How com that we can access the next line after moving the code itself away?


I'm a newbee learning operating system online, in which bootsect.s is mentioned: https://kernel.googlesource.com/pub/scm/linux/kernel/git/nico/archive/+/v0.99-pl8/boot/bootsect.S But this piece of code is quite strange to me:

        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

The strange part is the last 3 lines. According to my understanding, rep movsw has already move the code itself away, so when pc points to jumpi and when the computer is about to execute the code pointed by pc, it should cause an error because the code jumpi go, INITSEG has been moved away. So how come this code still works and jumpi go, INITSEG can still be found and executed?


Solution

  • From the OP's comment

    ...but the pc is pointed to the section start with #BOOTSEG, where there is no code anymore. So I thought jumpi go,INITSEG will not execute.

    Rest assured, the code is still there!

    This is how the memory was filled when BIOS loaded the bootsector at linear address 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:
    

    Once the rep movsw instruction has done its business, the memory at 00090000h will contain an exact copy of the 512 bytes found at 00007C00h. Although the author of this code stated that the code moves itself away, this is only a matter of speech. It is always a duplicate that is created. The source bytes are still there, unless of course there was an overlap between the 2 memory regions at DS:SIand ES:DI but that is not the case here.

    As a consequence the instruction pointer will be at 00007C14h and execute the far jump (intersegment) to linear address 00090019h where the go label is.
    From this point on the 512 bytes at 00007C00h can be ignored.