|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Апр 22, 2004 15:26:58 Доброго времени суток. Пытаюсь написать что нибудь работающее под защищенный режим. Но не могу в него попасть. :( Вроде старался все делать по статьям Сломаного Меча. Помогите определить в чем я ошибся. И еще вопрос - не у Сворда ни в Абеле не рассчитываеться размер лимита. там просто ставят 0fffffh. Как это сделать? И надо ли это делать? (мне кажеться что надо...)
.386p
RM_STACK segment stack 'STACK' use32
db 100h dup(?)
RM_STACK ends
DATA_S segment 'DATA' use32
GDT:
NULL_descr db 8 dup (0)
CODE_descr db 0FFh,0FFh,00h,00h,00h,10011010b,11001111b,00h
;base 00 00 00 00; limit f ff ff; type: code er; DPL: 0; P:1; G=1; S=1 (data/cod);
DATA_descr db 0FFh,0FFh,00h,00h,00h,10010010b,11001111b,00h
;base 00 00 00 00; limit f ff ff; type: data rw; DPL: 0; P:1; G=1; S=1 (data/cod);
VIDEO_descr db 0FFh,0FFh,00h,80h,0Bh,10010010b,01000000b,00h
;base 00 0b 80 00; limit 0 ff ff; type: data rw; DPL: 0; P:1; G=0; S=1 (data/cod);
GDT_size equ $-GDT
GDTR dw GDT_size-1
dd ?
DATA_S ends
RM_CODE segment para public 'CODE' use32
assume CS:RM_CODE,SS:RM_STACK,DS:DATA_S
start:
;prepare basees of code and data descr
mov ax,DATA_S
mov ds,ax
shl eax,4
or dword ptr DATA_descr+2,eax
mov ax,seg PM_CODE
shl eax,4
or dword ptr CODE_descr+2,eax
;write enter point to protected mode
xor EAX,EAX
mov AX,PM_CODE
shl EAX,4
add EAX,offset ENTRY_POINT
mov dword ptr ENTRY_OFF,EAX
xor EAX,EAX
mov AX,DATA_S;
shl EAX,4;
add AX,offset GDT
mov dword ptr GDTR+2,EAX
lgdt fword ptr GDTR
cli
in AL,70h
or AL,80h
out 70h,AL
mov EAX,CR0
or AL,1
mov CR0,EAX ;перезагрузка
db 66h
db 0EAh
ENTRY_OFF dd ?
dw 00001000b
RM_CODE ends
PM_CODE segment para public 'CODE' use32
assume CS:PM_CODE,DS:DATA_S
ENTRY_POINT:
mov AX,00010000b
mov DS,AX
mov AX,00011000b
mov ES,AX
PM_CODE ends
end start
С уважением. Ворон |
|
|
Дата: Апр 22, 2004 18:52:33 Raven Перед инструкциями mov ax,DATA_S и mov ax,seg PM_CODE поставь xor eax,eax , чтобы обнулить регистр eax. Это из-за того, что старшие 16 бит его совсем не обязаны быть нулевыми. К тому же, допустим у тебя вначале 16-31 биты равны нулю. После того как ты сделал shl eax,4 у тебя биты 16-23 уже ненулевые. Так что перед mov ax,seg PM_CODE надо-бы обнулять регистр eax (делать xor eax,eax). PS: Кстати говоря, совсем необязательно после перехода в защищенный режим делать безусловный переход (я так понял ты его делаешь (db 66h db 0eah ...)). И вообще необязательно инициализировать CS и SS(если конечно не используешь стек). Это в документации так пишут, что делайте безусловный переход. На самом же деле и без него все работает и так даже проще. Его надо делать если нужна инициалазация регистра CS. |
|
|
Дата: Апр 22, 2004 19:09:12 2Icebp: Спасибо. Уже исправил. (xor eax,eax) Про необходимость дальнего джампа - а как без него перейти в сегмент кода для защищенного режима ? Так или иначе это ничего не решило. Программа упорно перезагружает компьютер... Подскажите пожалуста возможную причину... |
|
|
Дата: Апр 22, 2004 20:08:45 Raven Я тут недавно одному человеку писал программу (на FASM-е) для перехода в защищенный режим с комментариями. Посмотри как я обычно делаю переход в защищенный режим и выход из него. Может этот исходник тебе поможет. У тебя перезагружает компьютер по моему мнению (у меня давно как то тоже такое было) из-за того, что ты не выходишь из защищенного режима. Подумай что будет после инструкций mov 00011000b mov es,ax. Я думаю, что после них выполняется какая-то хрень из области памяти после программы, которая приводит к перезагрузке. Если не хочешь выходить в конце из защищенного режима, то можешь сделать так: zavison: jmp zavison. Тогда у тебя вместо перезагрузки комп просто зависнет в защищенном режиме (если это будет так, то я был прав, нажми после этого RESET, так как CTRL-ALT-DEL не поможет). 1403134348__protmode.asm |
|
|
Дата: Апр 23, 2004 21:40:05 Грусно. Ничем не лечиться. Сократил программу до запрещения прерываний, перехода в защищенный режим. Все равно перегружает машину. В чем может быть дело??? |
|
|
Дата: Апр 24, 2004 09:26:57 · Поправил: Black_mirrorRM_CODE segment para public 'CODE' use32 - тут случайно не use16 должно стоять? |
|
|
Дата: Апр 24, 2004 11:39:45 Вот моя прога для перехода в РМ с комментариями. Может тебе это поможет понять что-то. ;программа иллюстрирует работу с 32 и 16 разрядными сегментами кода в РМ .386p mypm2 segment use16 begin: ;открыть линию А-20 -для работы с 1МБ+ in al,92h or al,10b out 92h,al xor eax,eax mov ax,cs mov ds,ax mov word ptr CORR,ax ;когда вернёмся из РМ мы используем это для сброса очереди ;команд-иначе не работает shl eax,4 ;теперь еах содержит физический адрес сегмента кода mov ecx,eax ;сохраним его ;загрузим регистр GDTR add eax,offset GDT ;в еах -физ. адрес таблицы ГДТ mov dword ptr GDTR_+2,eax mov word ptr GDTR_,31 lgdt fword ptr GDTR_ ;загрузим регистр GDTR mov eax,ecx add eax,offset backup ;куда прыгать из 32-битного сегмента кода mov dword ptr getto,eax mov eax,ecx add eax,offset code32 ;смещение 32х битного кода mov dword ptr goi,eax ;мы прыгнем сюда из 16-битного сегмента ;переключение в PM cli ;тормозим прерывания in al,70h or al,80h out 70h,al mov eax,cr0 or eax,1 mov cr0,eax ;мы в РМ!!!!!!!!!!!!!!!! ;ВАЖНО-хотя CS содержит глупости(из RM) проц на это не смотрит. ;он (проц) работает со значением из теневой части CS ;переходим в 32х битную зону db 066h db 0eah goi dd 0 ;здесь мы сохранили адрес code32 dw 10000b ;переход на сегмент с базой в нуле и смещением в code32 code32: mov eax,011000b ;можно загрузить DS-и поработать с данными mov ds,ax db 0eah ;прыгаем в 16-разрядный(=битный)сегмент getto dd 0 ;это необходимо,т.к. если перейти назад в реал dw 01000b ;сейчас то ДОС работать не будет-(во всяком случае у меня не работала) ; это связано с тем,что в теневом дескрипторе сегмент будет описан как 32х битный GDT: db 8 dup (0) db 0ffh,0ffh,0,0,0,10011010b,10001111b,0 ;16-bit code db 0ffh,0ffh,0,0,0,10011010b,11001111b,0 ;32-bit code db 0ffh,0ffh,0,0,0,10010010b,11001111b,0 ;32-bit data GDTR_ db 6 dup (0) backup: ;сейчас мы в 16и битном режиме mov eax,cr0 ;можно переключаться в реал and al,0feh mov cr0,eax DB 0EAH ;сброс очериди команд-без этого не работает DW $+4 CORR DW 0 in al,70h ;восстановить работу прерываний and al,7fh out 70h,al sti mov ah,0 ;подождать нажатия клавиши int 16h mov ah,4ch ;...и выйти int 21h mypm2 ends end begin |
|
|
Дата: Апр 24, 2004 12:16:01 Размер лимита и база.Я тоже долго не мог въехать как считается эти лимит и база,как он записывается-слева направа или наоборот. Важно(меня во вяком случае это долго путало)- запись битов.В байте самый маленький бит (по арифметическому значению)нулевой-крайний правый при традиционной записи (00100011b).Седьмой бит-крайний левый. Лимит.Если бит гранулярности (бит 8 байта 6)=0 то лимит равен тому чему он равен ;)(без изменений),если бит гранулярности =1 то лимит умножаем на 1000H (4K). Т.е. если бит Г. =0 то лимит от 0 и до 0fffffh (1048575). Если бит Г. =1 то лимит от 0*1000h и до 0fffffh*1000h(4GB). Запись в дескрипторе интеловская(а какая ж ещё?)-т.е. "не по человечески"-наоборот- лимит в 345567 байт (545dfh) пишем в дескрипторе так- 0dfh,45h,xxh,xxh,xxh,xxh,x5h,xxh где байт 0dfh в памяти имеет номер Z ,а байт x5h- Z+6. Вроде бы всё безошибок,хотя проверить не мешает. |
|
|
Дата: Апр 24, 2004 20:49:58 На мой взгляд, главное при написании первых программ с защищенным режимом - это не полениться написать обработчики исключений. В них нужно вывести номер исключения и crash-адрес с несколькими байтами. Часто бывает, что (например) должно зваться одно исключение, но неверный дескриптор стека составлен и возникает исключение 0D и прога нифига не понятно почему тухнет. В качестве примера кидаюсь своим исходником (по книге Финогенова) - в ней обрабатывается исключение:
.386p
;
; Common structures
;
descr struc
lim dw 0
base_l dw 0
base_m db 0
attr_1 db 0
attr_2 db 0
base_h db 0
descr ends
trap struc
offs1 dw 0
sel dw 16
rsrv db 0
attr_ db 8fh
offs_h dw 0
trap ends
intr struc
ioffs_l dw 0
isel dw 16
irsrv db 0
iattr db 8eh
ioffs_h dw 0
intr ends
data segment use16
gdt_0 label word
; GDT table
code_alias_sel equ 64
gdt_null descr <0,0,0,0,0,0> ; 0
gdt_data descr <data_size-1,0,0,92h,0,0> ; 8
gdt_code descr <code_size-1,0,0,98h,0,0> ; 16
gdt_stack descr <255,0,0,92h,0,0> ; 24
gdt_screen descr <4095,8000h,0bh,92h,0,0> ; 32
gdt_himem descr <1023,0,10h,92h,80h> ; 40
gdt_tss_0 descr <103,0,0,89h> ; 48
gdt_tss_1 descr <103,0,0,89h> ; 56
gdt_code_alias descr <code_size-1,0,0,92h,0,0> ; 64
gdt_size= $-gdt_null
idt label word
trap <exc_0>
trap <exc_1>
trap <exc_2>
trap <exc_3>
trap <exc_4>
trap <exc_5>
trap <exc_6>
trap <exc_7>
trap <exc_8>
trap <exc_9>
trap <exc_10>
trap <exc_11>
trap <exc_12>
trap <exc_13>
trap <exc_14>
trap <exc_15>
trap 16 dup(<exc_test>)
intr <new_08>
intr <new_09>
idt_size=$-idt
pdescr dq 0
save_sp dw 0
save_ss dw 0
save_ds dw 0
save_es dw 0
count db 0
sec dw 0
place dw 0
sym db 24
testt db 0
kode db ?
attr db 1eh
tabl db '0123456789'
TabHex db '0123456789ABCDEF'
ExitMsg db 'We are in DOS',13,10
ExitMsgLen equ $-ExitMsg
tss_0 db 104 dup(0)
tss_1 db 104 dup(0)
task1_offs dw 0
task1_sel dw 56
TrapMsg db 'trap (xxxx) raising !',0
TrapMsg0 db 'CS:IP-> xxxx bytes. Skip 2 bytes...',0
Trap1Msg db '#1 trap raising !',0
KeyPressed db 'Key: xxxx',0
TimeMsg db 'Time: xxxx',0
data_size equ $-gdt_null
data ends
text segment 'code' use16
assume cs:text,ds:data
begin label word
OutTrapMsg proc
pushad
; ax= num trap
mov di,offset TrapMsg+6
call HexWord_String
push 10*160
push offset TrapMsg
call Out_String
popad
ret
OutTrapMsg endp
exc_0 proc
push ebp
mov ebp,esp
pushad
push gs
mov ax,0
call OutTrapMsg
mov ax,code_alias_sel
mov gs,ax
mov eax,[ebp+4]
mov ax,gs:[eax]
; ax= CS:EIP->
mov di,offset TrapMsg0+8
call HexWord_String
push 6*160
push offset TrapMsg0
call Out_String
@@Skip:
add dword ptr [ebp+4],2 ; change eip
pop gs
popad
pop ebp
db 66h
iret
exc_0 endp
exc_1 proc
mov ax,1
call OutTrapMsg
db 66h
iret
exc_1 endp
exc_2 proc
mov ax,2
call OutTrapMsg
db 66h
iret
exc_2 endp
exc_3 proc
mov ax,3
call OutTrapMsg
db 66h
iret
exc_3 endp
exc_4 proc
mov ax,4
call OutTrapMsg
db 66h
iret
exc_4 endp
exc_5 proc
mov ax,5
call OutTrapMsg
db 66h
iret
exc_5 endp
exc_6 proc
mov ax,6
call OutTrapMsg
db 66h
iret
exc_6 endp
exc_7 proc
mov ax,7
call OutTrapMsg
db 66h
iret
exc_7 endp
exc_8 proc
mov ax,8
call OutTrapMsg
db 66h
iret
exc_8 endp
exc_9 proc
mov ax,9
call OutTrapMsg
db 66h
iret
exc_9 endp
exc_10 proc
mov ax,10
call OutTrapMsg
db 66h
iret
exc_10 endp
exc_11 proc
mov ax,11
call OutTrapMsg
db 66h
iret
exc_11 endp
exc_12 proc
mov ax,12
call OutTrapMsg
db 66h
iret
exc_12 endp
exc_13 proc
mov ax,13
call OutTrapMsg
db 66h
iret
exc_13 endp
exc_14 proc
mov ax,14
call OutTrapMsg
db 66h
iret
exc_14 endp
exc_15 proc
mov ax,15
call OutTrapMsg
db 66h
iret
exc_15 endp
exc_test proc
mov ax,666
mov gs:[0],ax
mov place,800
db 66h
iret
exc_test endp
new_08 proc
inc count
cmp count,18
jbe NO_time
cli
mov count,0
inc sec
mov ax,sec
; ax= time
mov di,offset TimeMsg+6
call HexWord_String
push 12*160
push offset TimeMsg
call Out_String
sti
NO_time:
mov al,20h
out 20h,al
db 66h
iret
new_08 endp
new_09 proc
cli
in al,60h
mov kode,al
xor ah,ah
; ax= key
mov di,offset KeyPressed+5
call HexWord_String
push 14*160
push offset KeyPressed
call Out_String
sti
in al,61h
or al,80h
out 61h,al
and al,7fh
out 61h,al
mov al,20h
out 20h,al
db 66h
iret
new_09 endp
main proc
mov ax,0003h
int 10h
xor eax,eax
mov ax,data
mov ds,ax
; save critical registers
mov save_ds,ds
mov save_es,es
mov save_ss,ss
mov save_sp,sp
; calculate liner address of data segment
shl eax,4
mov ebp,eax
mov bx,offset gdt_data
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; and command segment
xor eax,eax
mov ax,cs
shl eax,4
mov bx,offset gdt_code
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; and alias for command segment
xor eax,eax
mov ax,cs
shl eax,4
mov bx,offset gdt_code_alias
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; and stack segment
xor eax,eax
mov ax,ss
shl eax,4
mov bx,offset gdt_stack
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; tss_0
mov eax,ebp
add ax,offset tss_0
mov bx,offset gdt_tss_0
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; tss_1
mov eax,ebp
add ax,offset tss_1
mov bx,offset gdt_tss_1
mov [bx].base_l,ax
rol eax,16
mov [bx].base_m,al
; prepare psevdodescriptor
mov dword ptr pdescr+2,ebp
mov word ptr pdescr,gdt_size-1
lgdt pdescr
push ebp
;
cli
mov word ptr tss_1+4ch,16
mov word ptr tss_1+20h,offset himem
mov word ptr tss_1+50h,24
mov word ptr tss_1+38h,128
mov word ptr tss_1+54h,8
mov word ptr tss_1+48h,32
;fuck off all interrupts
cli
mov al,8fh
out 70h,al ;NMI off
jmp $+2 ;stop little bit
mov al,05h
out 71h,al
mov ax,40h
mov es,ax
mov word ptr es:[67h],offset return
mov word ptr es:[69h],cs
;change controller regim
mov dx,20h
mov al,11h
out dx,al
jmp $+2
inc dx
mov al,20h
out dx,al
jmp $+2
mov al,4
out dx,al
jmp $+2
mov al,1
out dx,al
mov al,0fch
out dx,al
mov dx,0a1h
mov al,0ffh
out dx,al
;load idtr table
pop ebp
mov word ptr pdescr,idt_size-1
xor eax,eax
mov ax,offset idt
add eax,ebp
mov dword ptr pdescr+2,eax
lidt pdescr
mov al,0d1h
out 64h,al
mov al,0deh
out 60h,al
; set the processor regim
mov eax,cr0 ;get mashine word
or eax,1 ;set PE bit
mov cr0,eax ;load mashine word
; load cs:ip
db 0eah ;jmp far
dw offset continue
dw 16 ;command selector
continue:
mov ax,8
mov ds,ax
mov ax,24
mov ss,ax
mov ax,32
mov es,ax
mov ax,40 ;massive selector
mov gs,ax
; Interrupts
mov al,0dh
out 70h,al
sti
;
mov ax,48
ltr ax
;
; Waiting for filler
;
@@MainLoop:
cmp kode,130
jb @@NoNumKey
cmp kode,139
ja @@NoNumKey
; Try to make exception #key
mov al,kode
sub al,130
cmp al,0
jnz @@NoExept0
xor bx,bx
div bx
jmp @@ExeptsDone
@@NoExept0:
@@ExeptsDone:
@@NoNumKey:
cmp kode,57
jnz @@MainLoop
; line A20 close
mov al,0d1h
out 64h,al
mov al,0ddh
out 60h,al
;
mov al,0feh
out 64h,al
hlt
; turn back DOS media
return:
mov ax,data
mov ds,ax
mov ax,stk
mov ss,ax
mov sp,save_sp
mov es,save_es
;interrupt on
mov al,0B8h
out 21h,al
mov al,9Dh
out 0a1h,al
mov al,0
out 70h,al ;NMI on
sti
; dos message
mov ah,40h
mov bx,01
mov cx,ExitMsgLen
mov dx,offset ExitMsg
int 21h
Exit:
mov ax,4c00h
int 21h
main endp
himem proc
pusha
mov ax,32
mov es,ax
mov ax,40
mov gs,ax
xor ebx,ebx
mov cx,gs:[ebx]
mov di,10000
mov bx,place
mov testt,0
@1:
mov ax,cx
xor dx,dx
div di
mov si,ax
mov dl,testt
and dx,1
cmp dx,1
je Good
cmp ax,0
je Ziro
Good:
mov testt,1
mov al,tabl[si]
mov ah,13h
mov es:[bx],ax
Ziro:
add bx,2
mov ax,di
mul si
sub cx,ax
mov ax,di
xor dx,dx
mov si,10
div si
mov di,ax
cmp di,1
jae @1
popa
iret
jmp himem
himem endp
Out_String proc near
push bp
cli
mov bp,sp
pushad
push es
mov ax,32
mov es,ax
mov si,[bp+4]
mov di,[bp+6]
mov ah,14
cld
@@OutString:
lodsb
test al,al
jz @@OutStringDone
stosw
jmp @@OutString
@@OutStringDone:
pop es
popad
pop bp
sti
retn 4
Out_String endp
HexWord_String proc near
pusha
push es
push ds
pop es
cld
mov bx,offset TabHex
mov cx,4
@@HexWordStr:
rol ax,4
push ax
and al,0Fh
xlat
stosb
pop ax
loop @@HexWordStr
pop es
popa
retn
HexWord_String endp
Hex_String proc near
pusha
push es
test cx,cx
jz @@ExitHexStr
cld
mov bx,offset TabHex
push ds
pop es
@@HexStr:
lodsb
mov ah,al
shr al,4
xlat
stosb
mov al,ah
and al,0Fh
xlat
stosb
loop @@HexStr
@@ExitHexStr:
pop es
popa
retn
Hex_String endp
code_size= $-begin
text ends
stk segment stack 'stack'
db 256 dup('~')
stk ends
end main
|
|
|
Дата: Апр 24, 2004 21:03:18 [офтоп] Ухххх!!! :))) надо было приаатачить его %))) [/офтоп] |
|
|
Дата: Май 2, 2004 03:10:50 · Поправил: getoff RM_CODE segment para public 'CODE' use32 - тут случайно не use16 должно стоять? use32 вызывает по крайней мере 2 типа ошибок в данном коде: 1. При вычислении адресов подставляються части 32х битного адреса 2. при прыганьи на PM код, ты изпользуешь префикс изменения разрядности адреса (db 66h), и потом прыгаешь в защищенном (уже) режиме по 16-битному(теперь) адресу. совокупность этого приводит к тому, что проц начинает исполнять совершенно левый код, который почти сразуже приведет к исключению -> resetу. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.062 |