Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

проблемы с прерываниями при переходе из защищенного в реальный

4.8K
19 июня 2006 года
NeTxXx
21 / / 29.12.2003
вобщем, суть в следующем:
написал я вторичный загрузчик (в будущем), который грузится из фат-раздела по адресу 01000h и выполняет следующие операции:
отключает прерывания, сохраняет текущие значения ss,ds,es и др. в память для возврата в реальный режим, создает дескрипторы кода (4Gb), данных (по такому же адресу что и code), стэка (фиксирован), видеопамяти (по адресу 0B8000h, размер 4000) для защищенного режима и 2 дескриптора кода и данных (16 бит, лимит 0FFFFh) для реального, настаивает gdt и загружает ее.
потом в защищенном режиме выводит пару строк и переходит назад в реальный.
но проблема вот в чем.. при включении прерываний уже в реальном режиме, система попросту перезагружается (если запускать на реальной машине), а если на vmware (4.05) или Bochs (2.26) то все нормально, т.е. sti включает прерывания и далее выводится строка посредством int10h
см. строку 221

я если чесно понятия не имею почему так происходит и поэтому прошу помочь.

вот код загрузчика:
Код:
001 format binary
002 org 0
003 include 'kboot.inc'
004 include 'pmode.inc'
005 include 'routines.inc'
006
007 code_selector   =  8
008 stack_selector  = 16
009 data_selector   = 24
010 screen_selector = 32
011 rcode_selector  = 40
012 rdata_selector  = 48
013
014 use16
015
016 start:
017     ; load segment regs, set stack
018     cli
019     mov ax,cs
020     mov ds,ax
021     mov es,ax
022     mov ss,ax
023     mov sp,stacksize
024     sti
025    
026     ; show hello msg
027     mov si, szLoaderMsg
028     call kputzs_bios
029
030     ; msg about pmode entering
031     mov si, szMsgPMEnter
032     call kputzs_bios
033    
034 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
035     ; save real mode descriptors
036     mov [rmode_ss],ss
037     mov [rmode_ds],ds
038     mov [rmode_es],es
039     mov [rmode_fs],fs
040     mov [rmode_gs],gs
041    
042     ; set real mode return address
043     mov [rmode_seg],cs
044     lea ax,[rmode_entry]
045     mov [rmode_off],ax
046
047     mov bx,gdt+8 ; skip zero-descriptor
048
049     xor eax,eax
050     mov edx,eax
051
052     push cs
053     pop ax ; ax = cs = segment address of current code segment
054
055     shl eax,4 ; eax = physical address of beginning of code segment
056
057            
058     ; set limit-hi and GDXU bits
059     ; limit-hi = 0Fh (maximum), G=1 (4 kbyte pages), D=1 (32 bit),
060     ; X=0 (reserved, must be 0), U=0 (for system purposes)
061     mov dx,11001111b
062     shl edx,16 ; move them to edx-hi part
063     mov dx,0FFFFh ; set limit-low (here - maximum)
064     ; finaly we have 4Gbyte limit for code descriptor
065    
066     ; code segment access rights (P = 1,
067     ; DPL = 00b, S = 1, type = 100b, A = 0)
068     mov cl,10011000b
069
070     call gdt_set_desc ; build code descriptor
071
072     lea dx,[stack_seg_start] ; edx = dx = stack beginning
073
074     add eax,edx ; eax - beginning of code segment
075     ; set limit-hi and GDXU bits
076     ; limit-hi = 00h (zero), G=1 (4 kbyte pages), D=1 (32 bit),
077     ; X=0 (reserved, must be 0), U=0 (for system purposes)
078     mov dx,11001111b
079     shl edx,16 ; move them to edx-hi part
080     mov dx,1024 ; set limit-low (stack size)
081
082     ; stack segment access rights
083     ;  (P = 1, DPL = 00b, S = 1,
084     ;  type = 011b, A = 0).
085     mov cl,10010110b
086
087     call gdt_set_desc ; build stack descriptor
088
089     xor eax,eax ; eax = 0
090     mov ax,ds
091     shl eax,4 ; ecx = physical address of beginning of data segment
092     mov dx,11001111b ; set limit-hi and GDXU bits
093     shl edx,16
094     mov dx,0FFFFh ; limit - maximum
095     ; 4GB data segment is ready
096
097     ; data segment access rights (P = 1,
098     ;  DPL = 00b, S = 1, type = 001, A = 0).
099     mov cl,10010010b
100
101     call gdt_set_desc ; build data descriptor
102
103     mov eax,0B8000h ; physical address of videomem segment beginning
104                    
105     mov edx,4000 ; videomem segment size (80*25*2 = 4000).
106     mov cl,10010010b ; access rights (like data segment)
107     call gdt_set_desc ; build video memory segment
108
109     ; now set additional real mode selectors
110     xor eax,eax
111     mov edx,eax
112
113     push cs
114     pop ax
115
116     shl eax,4 ; eax - physical address of code segment
117
118     mov edx,0FFFFh
119     mov cl,10011010b
120     call gdt_set_desc ; rmode code
121
122     mov cl,10010010b
123     call gdt_set_desc ; rmode data
124
125
126 ; set gdtr:
127
128     xor eax,eax ; eax = 0
129     mov edx,eax ; edx = 0
130
131     mov ax,ds
132     shl eax,4 ; eax = physical address of beginning of data segment
133     lea dx,[gdt]
134     add eax,edx ; eax = physical address of gdt
135     mov [gdt_adr],eax ; save it in gdt address field
136
137     mov dx,55 ; gdt limit = 8 * (1 + 6) - 1
138     mov [gdt_lim],dx ; save it in gdtr limit field
139
140     cli ; disable interrupts
141
142     lgdt [gdtr] ; load gdtr
143    
144     mov [rmode_sp],sp ; save stack pointer at the end
145
146 ; go to pmode
147
148     mov eax,cr0
149     or al,1
150     mov cr0,eax
151
152 ; load code selector into cs register
153 ; using far jump to pmode code
154
155     jmp far code_selector:pmode_entry
156
157 ;--------------------- now we're in 32 bit PM-------------------------------
158 use32
159 pmode_entry:
160 ; cs - code segment selector
161     ; load segment registers
162     mov ax,screen_selector
163     mov es,ax
164
165     mov ax,data_selector
166     mov ds,ax
167
168     mov ax,stack_selector
169     mov ss,ax
170     mov sp,0
171
172     ; show what we are now in pmode
173     mov ebx,szMsgPM ; ds:ebx - msg pointer
174     mov edi,480 ; 3 string in video memory
175     call kputzs ; print msg from pmode
176
177     ; entering rmode
178     mov ebx,szMsgRMEnter ; ds:ebx - msg pointer
179     mov edi,640 ; 4 string in video memory
180     call kputzs ; print msg from pmode
181
182     jmp far rcode_selector:rmode_preentry
183
184 rmode_preentry:
185     mov ax,rdata_selector
186     mov ss,ax
187     mov ds,ax
188     mov es,ax
189     mov fs,ax
190     mov gs,ax
191
192     mov eax,cr0
193     and al,0FEh
194     mov cr0,eax
195
196     ; far jump to real mode
197     ; jmp far rmode_seg:rmode_off
198     db  0eah
199     rmode_off dw 0
200     rmode_seg dw 0
201
202 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
203 ; ---------------------------- routines ----------------------------------
204 init_kputzs ; printing routine (uses video memory)
205 use16
206 init_gdt_set_desc ; gdt setting routine
207 init_kputzs_bios ; printing routine (uses int10)
208 init_set_curpos_bios ; setting cursor routine
209
210 ; real mode now
211 rmode_entry:
212     ; restore ss,ds,es,gs,fs
213     mov ss,[rmode_ss]
214     mov ds,[rmode_ds]
215     mov es,[rmode_es]
216     mov gs,[rmode_gs]
217     ; restore stack pointer
218     mov sp,[rmode_sp]
219
220     ; allow interrupts
221     sti
222     jmp $
223
224     ; set cursor to the 5th line
225     mov dx,0500h
226     call set_curpos_bios
227
228     mov si,szMsgRM
229     call kputzs_bios
230
231     jmp $
232
233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
234
235 ; gdt register image:
236
237 gdtr:
238 gdt_lim     dw  0
239 gdt_adr     dd  0
240 ;--------------------------------------------------------------------------
241 gdt:
242     dd  0,0 ; 0 descriptor
243     dd  0,0 ; 1 descriptor (code)
244     dd  0,0 ; 2 descriptor (stack)
245     dd  0,0 ; 3 descriptor (data)
246     dd  0,0 ; 4 descriptor (videomem)
247     dd  0,0 ; 5 descriptor (realm code)
248     dd  0,0 ; 6 descriptor (realm data)
249 real:
250 rmode_sp    dw 0
251 rmode_ss    dw 0
252 rmode_ds    dw 0
253 rmode_es    dw 0
254 rmode_fs    dw 0
255 rmode_gs    dw 0
256
257 szLoaderMsg db 'HELLO FROM KLOADER!!',13,10,0
258 szMsgPMEnter    db 'ENTERING PMODE...',13,10,0
259 szMsgRM     db 'IN 16 BIT UNREAL MODE NOW!',13,10,0
260
261
262 ;--------------------------------------------------------------------------
263
264 szMsgPM     db 'IN 32 BIT PMODE NOW!',0
265 szMsgRMEnter    db 'ENTERING RMODE...',0
266
267
268 times 1024  db 0    ; reserved for stack
269 stack_seg_start:    ; stack beginning


вот код процедуры создания дескрипторов gdt_set_desc:
Код:
001 ; gdt descriptor setting subroutine
002
003 ; creates descriptor
004 ; DS:BX = descriptor in gdt  
005 ; EAX = segment address
006 ; EDX = segment limit
007 ; CL = access rights byte                      
008 macro init_gdt_set_desc {
009 gdt_set_desc:              
010
011     push eax ecx edx ; we use eax, ecx, edx
012
013
014     push cx ; temporary save access rights
015
016     mov cx,ax ; copy lower part of address to cx,
017     shl ecx,16 ; and shift it to higher part
018
019     ; copy lower part of limit to cx
020     ;  now ecx contains lower part of
021     ;  the descriptor
022     mov cx,dx
023
024     mov [bx],ecx ; write lower part of descriptor to gdt
025
026     shr eax,16 ; now shift higher part of address to lower (ax)
027
028     mov ch,ah ; address bits 24 - 31
029     shr edx,16 ; working with higher part of limit (limit hi+GDXU)
030     mov cl,dl ; limit bits 16-19 + GDXU
031     shl ecx,16 ; shift it to higher part of ecx
032     mov cl,al ; and address bits 16 - 23 - lower byte
033
034     pop ax ; restore access rights to ax
035     ; and copy them into the second byte (of 4 available)
036     ; of ecx
037     mov ch,al
038
039     ; write the second part of
040     ; descriptor into gdt
041     mov [bx+4],ecx
042
043     add bx,8 ; move gdt poiner to next descriptor
044     pop edx ecx eax
045 ret
046 }
047


буду очень благодарен за помощь
заранее спасибо
350
19 июня 2006 года
cheburator
589 / / 01.06.2006
Попробуй по-человечьи настроить IDT. Желательно как при переходе в защищенный режим, так и обратно. Хотя это потребует немало дополнительной работы - перепрограммирования микросхем управления аппаратными прерываниями. Но оно тебе все равно будет нужно, я думаю. Ведь не собираешься же ты и дальше грузить систему с запрещенными прерываниями.
4.8K
19 июня 2006 года
NeTxXx
21 / / 29.12.2003
[QUOTE=cheburator]Попробуй по-человечьи настроить IDT. Желательно как при переходе в защищенный режим, так и обратно. Хотя это потребует немало дополнительной работы - перепрограммирования микросхем управления аппаратными прерываниями. Но оно тебе все равно будет нужно, я думаю. Ведь не собираешься же ты и дальше грузить систему с запрещенными прерываниями.[/QUOTE]

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

выкладываю полный исходник+образ дискеты на всякий случай
349
19 июня 2006 года
Phantom-84
656 / / 27.10.2005
[QUOTE=cheburator]Попробуй по-человечьи настроить IDT...[/QUOTE]Он в защищенном режиме работает с запрещенными прерываниями, поэтому ничего настраивать не нужно!

NeTxXx, а что по твоему делает инструкция "jmp $" после разрешения прерываний в реальном режиме :)
4.8K
19 июня 2006 года
NeTxXx
21 / / 29.12.2003
дык.. в данном случае она не имеет значения ) эт я так проверял где баг.. если запускать на реальной машине до jmp $ дело не доходит и система уходит в ребут )))
может пример есть перехода в pmode а потом обратно? посоветуйте пожалуйста
349
19 июня 2006 года
Phantom-84
656 / / 27.10.2005
[QUOTE=NeTxXx]дык.. в данном случае она не имеет значения ) эт я так проверял где баг.. если запускать на реальной машине до jmp $ дело не доходит и система уходит в ребут )))
может пример есть перехода в pmode а потом обратно? посоветуйте пожалуйста[/QUOTE]дык для того, что делает твоя программа, код у тебя слишком сложный... Это же ассемблер! Пиши предельно прозрачно, иначе потом разгребать замучаешься... А вообще есть множество примеров перехода в PM и обратно! Если хочешь, можем разобрать твой код по шагам...
4.8K
20 июня 2006 года
NeTxXx
21 / / 29.12.2003
хмм.. куда прозрачнее то? комментариев же много ) а вот от разбора я бы не отказался.. только как это будет выглядеть?
и еще, я смотрел примеры перехода в pmode и назад, сделано все как у меня.. никаких настроек контроллера прерываний не производится, однако сброса после sti не возникает? странно, почему? и больше всего меня мучает вопрос почему в виртуальной среде эмуляторов такое не происходит? может обратиться к их разработчикам? мол почему этот код не работает на реальной машине, а на виртуальной все ок? )) причем сразу в обоих эмуляторах!
349
21 июня 2006 года
Phantom-84
656 / / 27.10.2005
[QUOTE=NeTxXx]хмм.. куда прозрачнее то?[/QUOTE]Я не совсем точно выразился... представленный код слишком большой для той задачи, которую он решает...
Цитата:
...а вот от разбора я бы не отказался.. только как это будет выглядеть? ...больше всего меня мучает вопрос почему в виртуальной среде эмуляторов такое не происходит?

Элементарно! Напишем заново :) С эмуляторами такое постоянно случается, поэтому я их редко использую... Но возможно, что у тебя все-таки есть ошибка, связанная с отличиями между исходным контекстом эмулятора и тем реальным контекстом, который остается после передачи управления твоему коду...

12K
24 июня 2006 года
Allium
2 / / 17.05.2005
По-видимому, причина неработоспособности заключается в нарушении рекомендации Intel переходить в реальный режим из 32-бит защищенного через 16-бит защищенный... Можно ненароком получить 32-битный реальный режим, в котором DOS/BIOS работать не будет...
4.8K
24 июня 2006 года
NeTxXx
21 / / 29.12.2003
[QUOTE=Allium]По-видимому, причина неработоспособности заключается в нарушении рекомендации Intel переходить в реальный режим из 32-бит защищенного через 16-бит защищенный... Можно ненароком получить 32-битный реальный режим, в котором DOS/BIOS работать не будет...[/QUOTE]
спасибо всем за советы, но я кажется разобрался Ж)
проблема в стеке, а точнее в его дескрипторе.
я использовал expand-down тип сегмента, а при смене на нормальный все стало ок..
а вообще щас стал загружать ss селектором дескриптора данных.. так проще.. и легче имхо
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог