1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Переход в защищенный режим

Тема в разделе "WASM.OS.DEVEL", создана пользователем GLEB, 20 мар 2011.

  1. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    Добрый день, пытаюсь переключиться в защищенный режим, но переход на pmode_entry не происходит, комп перезагружается.

    Подскажите что не так?

    Код (Text):
    1. ;=============== REAL MODE =============;
    2. use16
    3.  
    4. start:
    5.         mov ax, cs
    6.         mov ds, ax
    7.         mov es, ax
    8.  
    9.         ; clear screen ;
    10.         mov  ax, 3
    11.         int 10h
    12.  
    13.         ;enable A20
    14.         mov ax, 0x2401
    15.         int 0x15
    16.        
    17.         ; включать a20 пробовал разными способами, может в этом дело?
    18.  
    19.         jnc err1 ; тут CF = 0 как бы все ок
    20.  
    21.         ; disable interrupts
    22.         cli
    23.  
    24.         in al, 70h
    25.         or al, 80h
    26.         out 70h, al
    27.  
    28.         ; load GDT register
    29.         lgdt fword [GDTR]
    30.  
    31.         ; enable protected mode
    32.         mov eax, cr0
    33.         or al, 1
    34.         mov cr0, eax
    35.  
    36.         jmp 00001000b:pmode_entry
    37.  
    38. err1:
    39.        ;ошибка открытия а20
    40.        jmp $
    41.  
    42. gdt:
    43.         dw 0, 0, 0, 0  
    44.  
    45.         db 0xFF        
    46.         db 0xFF        
    47.         db 0x00
    48.         db 0x00
    49.         db 0x00
    50.         db 10011010b
    51.         db 11001111b
    52.         db 0x00
    53.        
    54.         db 0xFF        
    55.         db 0xFF        
    56.         db 0x00
    57.         db 0x00
    58.         db 0x00
    59.         db 10010010b
    60.         db 11001111b
    61.         db 0x00
    62.  
    63. GDT_size     equ $-gdt
    64. GDTR         dw GDT_size-1
    65.              dd gdt
    66.  
    67.  
    68. ;=============== PROTECTED MODE =============;
    69. use32
    70. pmode_entry:
    71.  
    72.         jmp $ ; сюда не доходит
    73.  
    74.         mov  ax, 00010000b
    75.         mov  ds, ax
    76.         mov  es, ax
    77.  
    78.         ; enable interrupts
    79.         in  al, 70h
    80.         and al, 7Fh
    81.         out 70h, al
    82.         sti
    83.  
    84.         jmp $
    85.  
    86.         mov  edi, 0xB8000
    87.         mov byte[edi], 'A'
    88.  
    89.         jmp $
     
  2. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Попробуй так:
    Код (Text):
    1. start:
    2.         xor ax, ax
    3.         mov ds, ax
    4.         ...
    5.         jmp fword 8:pmode_entry
    Такое открытие линии A20 почти не используется из-за слабой поддержки данной функции в BIOS. Запрещать NMI лучше так:
    Код (Text):
    1.         mov al, 1???????b
    2.         out 70h, al
    3.         in al,71h
    Эта последовательность команд является более законченной, чем твой вариант.
     
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    GLEB
    0-ой дескриптор = 0. К нему обращаться вообще ни как нельзя.
    1-ый дескриптор для GDT, любое обращение к нему кроме чтения дескриптора процессором - #GP
    2-ой дескриптор для IDT, но на практике от может читаться/писаться и выполняться (на борще)
    3..8191-ый дескрипторы для системы.
     
  4. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Что за бред? Какие дескрипторы GDT и IDT!?
    Нулевой дескриптор - NULL. К нему обращаться нельзя.
    Все остальные заполняйте как хотите, но для PM вам потребуется как минимум один дескриптор сегмента данных и один дескриптор для сегмента кода. IDT и GDT не требуют для себя отдельных дескрипторов. Главное, чтобы они были доступны в текущем линейном адресном пространстве (об этом надо думать только при включённой страничной адресации). При этом совсем не обязательно, чтобы к ним можно было даже обратиться (например, они лежат вне всех сегментов программы из GDT) из кода.
     
  5. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    GLEB, я извиняюсь за возможно допущенную неточность. Как запускается твоя программа (что это исполняемый файл com, exe, просто бинарный файл или код бутсектора)?
     
  6. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    Вроде разобрался у меня этот код загружался в 0x7E0:0, поэтому нужно было вычислять адреса всех меток
    приведенный код тоже работает если загружен в 0:0x7E00 и с директивой org 0x7E00

    Phantom_84
    теперь хочу уточнить по поводу A20

    она получается включена по умолчанию?
    если ничего не делать, 20й бит адесной шины не сбрасывается, проверял и на виртуалке и на реальном железе

    Как правильно ее включать?

    Код (Text):
    1.  
    2. in al, 92h
    3. or al, 2
    4. out 92h, al
    Кто-то говорит, что данные код может не сработать на новом железе

    это не мой вариант ), код запрета NMI взят со статьи о защищенном режиме c форума )

    а что не закончено?
    имеется ввиду обращение к порту in al,71h ?
     
  7. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.395
    Адрес:
    Fryazino
    Забей на тех кто это пишет.
    90% рынка ПК это intel. Intel это не только ЦП, но и набор чипов для материнок. А она пока поддерживает совместимость.
    Вот когда в сети появятся данные, что такой-то такой-то производитель не поддерживает. И будет известно ID данного железа. А пока ID нет это всё на воде вилами писано.
     
  8. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.395
    Адрес:
    Fryazino
    Раньше как то не задумывался. Сейчас подумал. Мы же выбираем первой командой ЧИП, а значит просто обязаны прочитать данные? И так наверно надо делать со всем устарелым и не очень железом.
     
  9. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Сомневаюсь. Хотя в частном случае такое возможно. Как ты проверяешь открытость адресной линии?

    А кто-то говорит, что этот код прежде всего может не сработать на старом железе.

    Хороший вопрос. Я использую открытие через контроллер клавиатуры совместно с этим способом (с собой сейчас исходников нет, попробую поискать в сети). Функцию 24h не использую. Когда-то пробовал это делать, но быстро понял, что это бесперспективно.

    Да. Если в дальнейшем понадобится обращаться к CMOS, то могут возникнуть проблемы.
     
  10. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Я тоже какое-то время не задумывался над этим. Но потом где-то случайно подсмотрел этот вариант и задумался ))) Перед in al,71h возможно имеет смысл выполнить небольшую задержку.
     
  11. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    Код (Text):
    1. mov byte[1000000000000000000000b], 65  ; пишем по адресу 2097152 букву A
    2. mov byte[1100000000000000000000b], 66  ; пишем по адресу 3145728 букву B
    3.  
    4. mov al, byte[1000000000000000000000b]   ; читаем
    5. mov dl, byte[1100000000000000000000b]
    6.  
    7. mov byte[0xB8000], al ; выводим в видеопамять
    8. mov byte[0xB8002], dl
    по умолчанию на экране AB

    если отключить A20 этим кодом:

    Код (Text):
    1. in al, 92h
    2. and al, 0FDh
    3. out 92h, al
    то на экране BB

    как я понимаю из-за сброса 20-го бита запись происходит в 1000000000000000000000 а не 1100000000000000000000
    в итоге B затирает А
     
  12. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Лучше использовать не 3-й и 4-й мегабайт, а 1-й и 2-й. Также твой порядок обращения к памяти один из худших вариантов в плане противодействия кэшированию данных.
     
  13. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    Phantom_84
    А почему лучше первый и второй?
    Если A20 не включена, то 20 бит будет сброшен в любом случае (адресе) или нет?

    Ты имеешь ввиду то, что я записал данные и тут же их прочитал, а в реальную память они так и не попали и остались в кэше?
    Согласен, но по идее в данном случае результат должен быть одинаков, хоть с кэшем хоть без.

    Для чистоты эксперимента, отключал кэш

    Код (Text):
    1. mov eax, cr0
    2. or eax, 040000000h
    3. mov cr0, eax
    4. wbinvd
    Взято с исходников Memtest86.

    Результат тот же.
     
  14. abcd008

    abcd008 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2009
    Сообщения:
    616
    на всем железе которое сертифицировано под windows(а биосы обычно сертифицируют)
    открытие A20 через 92h порт будет работать.
    у них в стандартах Legacy pnp и PC98... описан этот порт. и все порты до 100h останутся стандартными)

    скорее ps/2 уберут. они и так не везде есть. только в эмуляции(если не включена).
     
  15. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Закрытие "линии" может быть реализовано таким образом, что запрещается доступ ко всей памяти выше первого мегабайта, а не только к "четным" мегабайтам. Т.е. при закрытой "линии" обращение к 3-му и 4-му мегу может приводить к обращению к первому мегу. К тому же при использовании 1-го и 2-го мега можно выполнять проверку, оставаясь в RM (как у меня это реализовано).

    Да.

    Это уже интересно. Приведенный код возьму на заметку.

    Я не утверждаю, что у тебя линия изначально закрыта, а детект дает неправильные результаты. Просто для надежности детект нужно сделать максимально достоверным.

    Жалко, что у меня нет с собой исходников (я сейчас нахожусь в другом городе). Если не ошибаюсь (давно это было), при включении линии A20 я первым делом вызывал процедуру проверки, а значит я тоже допускал возможность открытости линии изначально. В целом алгоритм примерно такой:
    - проверка;
    - попытка открытия через контроллер клавиатуры;
    - проверка;
    - попытка открытия через порт 92h;
    - проверка.

    Для первого способа на wiki osdev.ru есть код, который претерпел не слишком много изменений относительно моего оригинального кода (если не ошибаюсь, у меня в оригинале было xor cx,cx, а не mov cx,0FFFFh :), комментарии тоже скорее всего не мои).

    Для второго способа на wiki код не мой. У меня вроде бы перед отправкой измененного значения обратно имеется проверка, не был ли установлен соответствующий бит изначально (я где-то читал, что такую проверку делать нужно).
     
  16. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    По идее все это нужно делать с запрещенными прерываниями.
     
  17. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    То есть из real mode надо записать, например, по адресу FFFF:FFFF (1114095) если A20 открыта запишется, если нет 20-й бит будет сброшен и попадем в область 65519.

    Получается у меня изначально открыта, а при закрытии сбрасывается только 20-й бит, а не все что старше. Иначе бы при попытке записи в 1100000000000000000000 запись бы происходила в адрес 0?
     
  18. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Да.

    А ты уверен, она не происходит? Обработчик деления на ноль вызывается не так часто, поэтому ты мог и не заметить повреждение вектора, находящегося по нулевому адресу.
     
  19. GLEB

    GLEB New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2007
    Сообщения:
    83
    Я после записи символа B по адресу 1100000000000000000000 (с отключенной A20) вывожу на экран содержимое по адресу 0 и оно отличается от содержимого по адресу 1000000000000000000000
     
  20. abcd008

    abcd008 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2009
    Сообщения:
    616
    а разве можно писать по адресу ffffh:ffffh. там же rom bios?