Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Включение мультизадачности в i386  (Прочитано 27557 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« : 19-09-2007 04:45 » 

Пытаюсь переключить i386 в мультизадачный режим, использую следующий алгоритм:
1 - подготавливаю дескриптор задачи TSS в GDT;
2 - загружаю селектор дескриптора задачи в TR ("ltr");
3 - сбрасываю флаг занятости "B" в дескрипторе текущей задаче;
4 - делаю дальний переход на текущую задачу.

Так вот, после пункта 4 процессор становиться. Кто знает, как грамотно запустить мультизадачность на i386 подскажите.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 19-09-2007 12:17 » 

Serg79, Не совсем понятно. Виртуальный режим или мультизадачность? Для каких целей? Какая ОС? Какой исходный процессор?
Так как все это прерагатива самой ОС..

Мультизадачность на i386 не запускается, а эмулируется.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 19-09-2007 12:33 » 

Процессор семейства i386, ОС не использую, сам загружаю свой код с floppy по включению питания.

Я для переключения процессора в мультизадачность использую следующий алгоритм:
Код:
; Main_TSS - это селектор некоторого определённого дескриптора TSS.
   mov   ax,Main_TSS
   ltr   ax      ;    Загружаем в регистр TR селектор
            ; дескриптора TSS задачи Main. Теперь текущая
            ; задача - это Main_TSS.

; Чистим Busy flag Main_TSS - он установился после загрузки селектора в TR
   mov   bx,offset GDT + Main_TSS
   and   byte ptr [ bx + 5 ],11111101b

; Переход на Main_TSS
   db   0eah   ; Этот код эквивалентен команде FAR JMP Main_TSS:00
   dw   00
   dw   Main_TSS

;    Вот здесь процессор сохранил контекст текущей задачи, т.е. заполнил
; поля TSS текущими значениями.
; Main_TSS:

;    А теперь процессор загрузил те же самые значения из TSS в регистры.
; Теперь процессор в режиме мультизадачности.

;    Установка Busy flag Main_TSS - она нужна, потому что был переход с
; Main_TSS на Main_TSS командой JMP - эта команда сбрасывает флаг занятости
; старой задачи, т.е. Main_TSS.
   mov   bx,offset GDT + Main_TSS
   or   byte ptr [ bx + 5 ],10b
Дело в том, что включение мультизадачного режима работы процессора не обязывает при этом иметь несколько задач и обязательно переключаться между ними, можно иметь одну задачу которая будет все время выполняться, но в тоже время это будет задачей т.к. будут задействованы регистр "TR" и использоваться структура "TSS". Так вот, я пытаюсь пока просто перенести текущий выполняемый контекст в задачу.

Если не сбрасывать флаг занятости задачи "B" в дескрипторе задачи, пере дальним переходом на нее "FAR JMP TSS:0" то у меня генерируется исключение общей защиты, т.к. на рабочую задачу переключаться нельзя (рекурсивный вызов задач запрещен).

И так я дохожу до пункта 4 ("FAR JMP TSS:0") и у меня все становиться. У меня такое ощущение, что я гдето просто чегото не доделываю.
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 21-09-2007 06:59 » 

Грабли были в том, что при сохранении контекста задачи в сегменте "TSS", регистр "cr3" не сохраняется. И при переключении обратно на эту задачу в регистр "cr3" загружались нули и все сыпалось, даже исключения не выскакивали. И еще, дальний переход с помощью команды "ljmp" на задачу которая сейчас выполняется, даже при сброшенном флаге "busy" дескрипторе задачи, так же останавливает процессор и не генерирует исключения защиты процессора.
Записан
0xff
Гость
« Ответ #4 : 29-01-2009 00:18 » 

А кто знает как сбросить текущий контекст в TSS?
Допустим я переключился на задачу А, задача A хочет сделать форк. Логично было бы скопировать контекст задачи  А в контекст создаваемой задачи. Но в TSS контекст старый. Как его синхронизировать без того чтобы пальцAми запихивать каждый регистр в TSS?
В мануалах интела я такой команды не нашел. Там написано что контекст сохраняется в TSS при переключении задачи. Как быть с форком?
« Последнее редактирование: 29-01-2009 18:40 от 0xff » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 29-01-2009 07:14 » 

А что есть fork()? Новый процесс - новая таблица страниц. Т.ч. никакой мифической команды нет.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
0xff
Гость
« Ответ #6 : 29-01-2009 18:28 » 

Новый процесс также означает новый контекст. Контекст в х86 отслеживается в сегменте TSS. Можно его не использовать  и делать переключение контекста вручную как в линуксе, но это отдельный разговор. Если я создаю копию задачи, то неплохо бы иметь возможность просто скопировать контекст. Если уж разработчики процессора создали абстракцию задачи, то почему оставили в этой абстракции дырки куда надо лезть руками?

При чем тут таблица страниц в твоем ответе я вообще не понял. С таблицей страниц я проблемы не вижу - копируешь и все дела.
« Последнее редактирование: 29-01-2009 18:43 от 0xff » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 30-01-2009 06:47 » 

0xff, одним копированием TSS здесь не обойтись, во первых Тебе надо будет в новом TSS указать новые параметры для стека, не будут же два разных процесса использовать один стек. Во вторых, необходимо будет подготовить все дескрипторы, а это как минимум - дескриптор задач TSS, дескриптор кода, дескриптор данных, и дескриптор стека. Ну и в конце необходимо передать управление новой задаче, как ты это будешь делать (вручную, либо с помощью шлюза задач) это не важно.

Ну да, как правильно RXL заметил, если включено страничное преобразование, то надо еще позаботиться о правильном значении для регистра cr3 в структуре TSS.
« Последнее редактирование: 30-01-2009 06:49 от Serg79 » Записан
0xff
Гость
« Ответ #8 : 30-01-2009 18:22 » 

Я это все знаю и это все уже написано и работает, и переключение задач и страничная адресация. Просто в операционке которую я пишу я стартаюсь по минимуму использовать ассемблер. Поэтому не хочу писать уродливый кусок кода который будет  в fork()-e все текущие регистры скидывать в TSS. А поменять нужные поля в структуре TSS можно и из C.
« Последнее редактирование: 30-01-2009 18:27 от 0xff » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 31-01-2009 05:37 » 

0xff, пиши не уродливый кусок Улыбаюсь Тот же repne movsd.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 31-01-2009 09:02 » 

0xff, у Тебя возникают трудности при переходе исполняющего кода от 'Ассемблера' к 'C'?
« Последнее редактирование: 31-01-2009 09:04 от Serg79 » Записан
0xff
Гость
« Ответ #11 : 03-02-2009 00:30 » 

0xff, пиши не уродливый кусок Улыбаюсь Тот же repne movsd.
поясни как repne movsd может запомнить текущее состояние всех регистров

0xff, у Тебя возникают трудности при переходе исполняющего кода от 'Ассемблера' к 'C'?
нет не возникают
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 03-02-2009 07:47 » 

Вот (Процессор в защищенном режиме) 0xff, в данном ответе приложен архив с исходниками посмотри его может что интересное найдешь для себя.

Кстати, там в следующем ответе есть код который запускает 2 задачи и производит переключение между ними (используется TSS и все сопутствующее).

Да 0xff, если что будет непонятно, спрашивай.
« Последнее редактирование: 03-02-2009 07:54 от Serg79 » Записан
0xff
Гость
« Ответ #13 : 03-02-2009 19:25 » 

Спасибо за код, но он кажется не имеет никакого отношения к моему вопросу. Клонирования задач я там не нашел. Переход в защищенный режим и переключение задач как я уже писал проблем не вызывают.
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 03-02-2009 20:03 » 

0xff, ну Ты даешь. Если Ты смог реализовать аппаратное переключение задач (это второй архив), то реализация аналога fork у Тебя вообще не должна вызывать проблем.

Самое простое, это решить задачу в лоб:
1 - Создаешь копии сегментов кода, данных и стека, копируемого выполняемого потока.
2 - Добавляешь дескрипторы созданных сегментов в LDT.
3 - Создаешь копию TSS, копируемого выполняемого потока.
4 - В новой таблице TSS, исправляешь регистры ES, CS, SS, DS, FS, GS и LDTR таким образом, что бы они указывали на вновь созданные дескрипторы.

Вот и все. Теперь передаешь управление на вновь созданную таблицу TSS.

Кстати, во втором архиве весь код написан на 'C' и доступ к дескрипторам и TSS так же происходит на 'C'. Так что я не вижу проблем, что бы реализовать все это с использованием языка 'C'. Во втором архиве на ассемблере написан только загрузочный сектор и код переключающий процессор в PM, а все остальное написано на 'C'.
Записан
0xff
Гость
« Ответ #15 : 03-02-2009 22:05 » 

Serg79, пойми меня правильно, я ценю твою помощь, но прочитай пожалуйста мой вопрос внимательно. Oн был о шаге номер 3: как лучше скопировать текущий контекст в новый? Tо есть содержимое регистров eax, ebx и иже с ними. Если просто скопировать TSS копируемой задачи, то он боюсь не отражает текущее состояние. В нем будет состояние задачи ма момент последнего переключения.

Вопрос кстати не в том "обьясните чайнику как сделать", а в том как сделать красиво и оптимально. Критерий оптимальности это в том числе насколько код лаконичен и читаем.
« Последнее редактирование: 03-02-2009 23:59 от 0xff » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 04-02-2009 06:52 » 

Вопрос кстати не в том "обьясните чайнику как сделать", а в том как сделать красиво и оптимально.
0xff, Ты еще не одной строчки кода не показал. Ты покажи как Ты это сделал, и Тебе подскажут как это переделать красиво, оптимально и лаконичноАга
« Последнее редактирование: 04-02-2009 06:53 от Serg79 » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 04-02-2009 08:08 » 

0xff, пиши не уродливый кусок Улыбаюсь Тот же repne movsd.
поясни как repne movsd может запомнить текущее состояние всех регистров
Регистры у тебя сохраняет проц в TSS - вот его и копируй.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
0xff
Гость
« Ответ #18 : 04-02-2009 18:11 » 

0xff, пиши не уродливый кусок Улыбаюсь Тот же repne movsd.
поясни как repne movsd может запомнить текущее состояние всех регистров
Регистры у тебя сохраняет проц в TSS - вот его и копируй.
камрад не в теме? прочитай мой предыдущий пост пжалста

все умолкаю пока кто-нибудь скажет что то умное и по теме
« Последнее редактирование: 04-02-2009 18:13 от 0xff » Записан
barracudo
Гость
« Ответ #19 : 04-04-2009 19:02 » new

Код:
; Программа, выполняющая переход в защищенный режим и немедленный возврат.
; Работает в DOS в реальном режиме и в DOS-окне Windows 95 (Windows
; перехватывает исключения, возникающие при попытке перехода в защищенный
; режим из V86, и позволяет нам работать, но только на минимальном уровне
; привилегий)
;
; Компиляция:
; TASM:
;  tasm /m pm0.asm
;  tlink /x /t pm0.obj
; MASM:
;  ml /c pm0.asm
;  link pm0.obj,,NUL,,,
;  exe2bin pm0.exe pm0.com
; WASM:
;  wasm pm0.asm
;  wlink file pm0.obj form DOS COM
;

.model tiny
.code
.386p ; все наши примеры рассчитаны на 80386
org 100h ; это COM-программа
start:
; подготовить сегментные регистры
push cs
pop ds ; DS - сегмент данных (и кода) нашей программы
push 0B800h
pop es ; ES - сегмент видеопамяти
; проверить, находимся ли мы уже в защищенном режиме
mov eax,cr0 ; прочитать регистр CR0
test al,1 ; проверить бит PE,
jz no_V86 ; если он ноль - мы можем продолжать,
; иначе - сообщить об ошибке и выйти
mov ah,9 ; функция DOS 09h
mov dx,offset v86_msg ; DS:DX - адрес строки
int 21h ; вывод на экран
ret ; конец COM-программы
; (раз это защищенный режим, в котором работает наша DOS-
; программа, это должен быть режим V86)
v86_msg db "Running in V86 mode. Can't switch to PM$"

; сюда передается управление, если мы запущены в реальном режиме
no_V86:
; запретить прерывания
cli
; запретить немаскируемое прерывания
in al,70h ; индексный порт CMOS
or al,80h ; установка бита 7 в нем запрещает NMI
out 70h,al
; перейти в защищенный режим
mov eax,cr0 ; прочитать регистр CR0
or al,1 ; установить бит PE,
mov cr0,eax ; с этого момента мы в защищенном режиме
; вывод на экран
xor di,di ; ES:DI - начало видеопамяти
mov si,offset message ; DS:SI - выводимый текст
mov cx,message_l
rep movsb ; вывод текста
mov ax,0720h ; пробел с атрибутом 07h
mov cx,rest_scr ; заполнить этим символом остаток экрана
rep stosw
; переключиться в реальный режим
mov eax,cr0 ; прочитать CR0
and al,0FEh ; сбросить бит PE
mov cr0,eax ; с этого момента процессор работает в реальном
; режиме
; разрешить немаскируемое прерывание
in al,70h ; индексный порт CMOS
and al,07FH ; сброс бита 7 отменяет блокирование NMI
out 70h,al
; разрешить прерывания
sti
; подождать нажатия любой клавиши
mov ah,0
int 16h
; выйти из COM-программы
ret
; текст сообщения с атрибутом после каждого символа для прямого вывода на экран
message db 'H',7,'e',7,'l',7,'l',7,'o',7,' ',7,'f',7
db 'r',7,'o',7,'m',7,' ',7,'P',7,'M',7
; его длина в байтах
message_l = $-message
; длина оставшейся части экрана в словах
rest_scr = (80*25)-(2*message_l)
end start

У меня есть еше примеры, если надо, скину.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines