Переход ассемблера в защищенном режиме с GDT

В настоящее время я играю с x86 Assember, чтобы отточить свои навыки программирования на низком уровне. В настоящее время у меня возникла небольшая проблема со схемой адресации в 32-битном защищенном режиме.

Ситуация следующая:

У меня загружена программа по адресу 0x7e0, которая переключает ЦП в защищенный режим и переходит к соответствующей метке в коде:

[...]
code to switch CPU in Protected Mode
[...]

jmp ProtectedMode


[...]

bits 32

ProtectedMode:
    .halt:
        hlt
        jmp .halt

Пока это работает абсолютно нормально. «Jmp ProtectedMode» работает без явного дальнего перехода для очистки очереди предварительной выборки - поскольку эта программа загружается со смещением 0 (org 0 в начале), что приводит к тому, что сегмент кода указывает на правильное место.

Моя текущая проблема заключается в том, что внутри метки «ProtectedMode» я хочу перейти к другой программе, которая загружается по адресу 0x8000 (я проверил это с помощью дампа памяти, функция загрузки работает правильно и программа загружается правильно. до 0x8000).

Поскольку ЦП теперь находится в ProtectedMode, а не в RealMode, схема адресации отличается. ProtectedMode использует селекторы дескрипторов для поиска базового адреса и ограничения в таблице дескрипторов, чтобы добавить заданное смещение и получить физический адрес (как я понял). Следовательно, перед входом в ProtectedMode необходимо было установить GDT.

Мой выглядит следующим образом:

%ifndef __GDT_INC_INCLUDED__
%define __GDT_INC_INCLUDED__

;*********************************
;* Global Descriptor Table (GDT) *
;*********************************
NULL_DESC:
    dd 0            ; null descriptor
    dd 0

CODE_DESC:
    dw 0xFFFF       ; limit low
    dw 0            ; base low
    db 0            ; base middle
    db 10011010b    ; access
    db 11001111b    ; granularity
    db 0            ; base high

DATA_DESC:
    dw 0xFFFF       ; data descriptor
    dw 0            ; limit low
    db 0            ; base low
    db 10010010b    ; access
    db 11001111b    ; granularity
    db 0            ; base high

gdtr:
    Limit dw 24         ; length of GDT
    Base dd NULL_DESC   ; base of GDT

%endif ;__GDT_INC_INCLUDED__

и загружается в регистр GDT через

lgdt [gdtr]

То, что я пока не понял, - как мне теперь перейти на физический адрес 0x8000 в ProtectedMode с помощью GDT?

Моей первой мыслью было выбрать дескриптор кода (CODE_DESC), который должен указывать на 0x7e00 (где текущая программа загружена), и использовать смещение, необходимое для перехода к 0x8000 (512 байт), в результате получилась инструкция перехода:

jmp CODE_DESC:0x200

Но это не работает.

jmp 0x7e0:0x200 

тоже не работает ...

Вы хоть представляете, что мне здесь не хватает? Возможно, я не понял чего-то существенного в схеме адресации 32-Bit ProtectedMode и использовании GDT.

[РЕДАКТИРОВАТЬ] Полный код:

bits 16
org 0                       ; loaded with offset 0000 (phys addr: 0x7e00)

jmp Start

Start:
    xor ax, ax
    mov ax, cs
    mov ds, ax              ; update data segment

    cli                     ; clear interrupts

    lgdt [gdtr]             ; load GDT from GDTR (see gdt_32.inc)

    call OpenA20Gate        ; open the A20 gate 

    call EnablePMode        ; jumps to ProtectedMode

;******************
;* Opens A20 Gate *
;******************
OpenA20Gate:
    in al, 0x93         ; switch A20 gate via fast A20 port 92

    or al, 2            ; set A20 Gate bit 1
    and al, ~1          ; clear INIT_NOW bit
    out 0x92, al

    ret

;**************************
;* Enables Protected Mode *
;**************************
EnablePMode:
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    jmp ProtectedMode ; this works (jumps to label and halts)
    ;jmp (CODE_DESC-NULL_DESC):ProtectedMode ; => does not work
    ;jmp 08h:ProtectedMode , => does not work

;***************
;* data fields *
;*  &includes  *
;***************
%include "gdt_32.inc"

;******************
;* Protected Mode *
;******************
bits 32

ProtectedMode:
    ;here I want to jump to physical addr 0x8000 (elf64 asm program)

    .halt:
        hlt
        jmp .halt
12
задан 1201ProgramAlarm 17 April 2019 в 23:14
поделиться