assemblyx86bootloaderosdevgdt

Assempler - PC crashes after execution of LGDT instruction


Contents

I want to jump to diskette_initialisation with the jmp instruction after executing the lgdt instruction, but it crashes What is the cause? If the cause is known, why did the designers of the Intel cpu do it?

Environment

code

bits 16
org 0x7c00
  jmp boot_lodaer
  boot_lodaer:
    cli
    mov ax, 0
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov sp, 0x7c00

    call minimum_gdt_andidt
    bits 16
    call valid_A20
    call diskette_initialisation
    jmp  Protected_Mode

    minimum_gdt:
      bits 32
      lgdt [ndt_setup];https://wiki.osdev.org/GDT_Tutoria
   lidt [ndt_setup:
      ret
      ndt_setup:
        dw 23
        dd gdt_null
      ndt_null:
        dq 0x0:
      ndt_code:
        dw 0xffff
        dw 0x0
        db 0x0
        db 11001111b
        db 10011010b
        db 0x0
      ndt_date:
        dw 0xffff
        dw 0x0
        db 0x0
        db 11001111b
        db 10011010b
        db 0x0
   ndit_end:
    ;Only enable a20. Does not check for anything.
    valid_A20:
      in al, 0x60
      mov al, 0xad; key off
      out 0x60, al

      in al, 0x60
      mov   al,   0xfe; key initialisation
      out   0x60, al

      in al, 0x60
      mov   al,  0xae; key on
      out   0x60, al
      mov al, 0x00
    ret  

    diskette_error:
      mov ah, 0x0e
      mov al, 'E'
      int 0x10
    hlt
    
    diskette_initialisation:
      mov ah, 0x00
      mov dl, 0x00
      int 0x13
      jc diskette_error

      mov ah, 0x0e
      mov al, '2'
      int 0x10
    ret

    Protected_Mode:
      cli 
      mov eax, 1
      mov cr0, eax
    jmp eax:karnel
  kanel:
  hlt
  times   510-($-$$) db 0
dw  0aa55h

Solution

  • This is a hardware bug on the intel side, so it won't fix the problem. I couldn't even do it the same way as in the specification.Goodbye, for the time being, I will resent intel for the time I spent on it.

    The specifications I have referred to enter link description here

    9.9.1 Switching to Protected Mode

    Before switching to protected mode from real mode, a minimum set of system data structures and code modules must be loaded into memory, as described in Section 9.8, “Software Initialization for Protected-Mode Operation.” Once these tables are created, software initialization code can switch into protected mode. Protected mode is entered by executing a MOV CR0 instruction that sets the PE flag in the CR0 register. (In the same instruction, the PG flag in register CR0 can be set to enable paging.) Execution in protected mode begins with a CPL of 0. Intel 64 and IA-32 processors have slightly different requirements for switching to protected mode. To insure upwards and downwards code compatibility with Intel 64 and IA-32 processors, we recommend that you follow these steps:

    1. Disable interrupts. A CLI instruction disables maskable hardware interrupts. NMI interrupts can be disabled with external circuitry. (Software must guarantee that no exceptions or interrupts are generated during the mode switching operation.)
    2. Execute the LGDT instruction to load the GDTR register with the base address of the GDT.
    3. Execute a MOV CR0 instruction that sets the PE flag (and optionally the PG flag) in control register CR0.
    4. Immediately following the MOV CR0 instruction, execute a far JMP or far CALL instruction. (This operation is typically a far jump or call to the next instruction in the instruction stream.)
    5. The JMP or CALL instruction immediately after the MOV CR0 instruction changes the flow of execution and serializes the processor.
    6. If paging is enabled, the code for the MOV CR0 instruction and the JMP or CALL instruction must come from a page that is identity mapped (that is, the linear address before the jump is the same as the physical address after paging and protected mode is enabled). The target instruction for the JMP or CALL instruction does not need to be identity mapped.
    7. If a local descriptor table is going to be used, execute the LLDT instruction to load the segment selector for the LDT in the LDTR register.
    8. Execute the LTR instruction to load the task register with a segment selector to the initial protected-mode task or to a writable area of memory that can be used to store TSS information on a task switch.
    9. After entering protected mode, the segment registers continue to hold the contents they had in real-address mode. The JMP or CALL instruction in step 4 resets the CS register. Perform one of the following operations to update the contents of the remaining segment registers. — Reload segment registers DS, SS, ES, FS, and GS. If the ES, FS, and/or GS registers are not going to be used, load them with a null selector. — Perform a JMP or CALL instruction to a new task, which automatically resets the values of the segment registers and branches to a new code segment.
    10. Execute the LIDT instruction to load the IDTR register with the address and limit of the protected-mode IDT.
    11. Execute the STI instruction to enable maskable hardware interrupts and perform the necessary hardware operation to enable NMI interrupts. Random failures can occur if other instructions exist between steps 3 and 4 above. Failures will be readily seen in some situations, such as when instructions that reference memory are inserted between steps 3 and 4 while in system management mode.