I'm writing my own kernel and used this code to override global descriptor table set by bootloader. This is done in 32 bit protected mode.
flush_gdt:
lgdt [gdtr]
jmp 0x08:complete_flush
complete_flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
The code works fine however I'm not able to understand why next instruction after lgdt is executed properly.
As far as I understand values of segment registers (especially CS) remain unchanged. Therefore CPU will use old register and new table to resolve address of instruction jmp 0x08:complete_flush
. Chances are that entry in my table pointed by value of old CS is not a valid code segment and this would lead to crash. However nothing like this happens. Why?
EDIT: Asking this because my understanding is that CPU resolve linear addresses using CS:EIP registers pair. Now after lgdt
CS would suddenly point to diffrent entry so why next instruction executed is the jmp instruction