· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ASSEMBLER —› как оргонизовать процедуру в pmode

Посл.отвђт Сообщенiе


Дата: Окт 22, 2003 22:08:59

; dpmiex.asm
; Выполняет переключение в защищенный режим средствами DPMI
;
; Компиляция:
; TASM:
; tasm /m dpmiex.asm
; tlink /x /3 dpmiex.obj
; MASM:
; ml /c dpmiex.asm
; link dpmiex.obj,,NUL,,,
; WASM:
; wasm /D_WASM_ dpmiex.asm
; wlink file dpmiex.obj form DOS


.486 ; 32-битный защищенный режим появился в 80386

; 16-битный сегмент - в нем выполняется подготовка и переход в защищенный
; режим
RM_seg segment byte public use16
assume cs:RM_seg, ds:PM_seg, ss:RM_stack

; точка входа программы
RM_entry:
; проверить наличие DPMI
mov ax,1687h ; номер 1678h
int 2Fh ; прерывание мультиплексора,
test ax,ax ; если AX не ноль,
jnz DPMI_error ; произошла ошибка (DPMI отсутствует),
test bl,1 ; если не поддерживается 32-битный режим
jz DPMI_error ; нам тоже нечего делать

; подготовить базовые адреса для будущих дескрипторов
mov eax,PM_seg
mov ds,ax ; DS - сегментный адрес PM_seg
shl eax,4 ; EAX - линейный адрес начала сегмента PM_seg
mov dword ptr PM_seg_addr,eax
or dword ptr GDT_flatCS+2,eax ; дескриптор для CS
or dword ptr GDT_flatDS+2,eax ; дескриптор для DS

; сохранить адрес процедуры переключения DPMI
mov word ptr DPMI_ModeSwitch,di
mov word ptr DPMI_ModeSwitch+2,es

; ES должен указывать на область данных для переключения режимов
; у нас она будет совпадать с началом будущего 32-битного стека
add eax,offset DPMI_data ; добавить к EAX смещение
shr eax,4 ; и превратить в сегментный адрес
inc ax
mov es,ax

; перейти в защищенный режим
mov ax,1 ; AX = 1 - мы будем 32-приложением
ifdef _WASM_
db 67h ; поправка для wasm
endif
call dword ptr DPMI_ModeSwitch
jc DPMI_error ; если переключения не произошло - выйти

; теперь мы находимся в защищенном режиме, но лимиты всех сегментов
; установлены на 64 Кб, а разрядности сегментов на 16 битов. Нам надо подготовить два
; 32-битных селектора с лимитом 4 Гб - один для кода и один для данных

push ds
pop es ; ES вообще был сегментом PSP с лимитом 100h байтов
mov edi,offset GDT ; EDI - адрес таблицы GDT
; цикл по всем дескрипторам в нашей GDT,
mov edx,1 ; которых всего два (0, 1)
sel_loop:
xor ax,ax ; функция DPMI 00
mov cx,1
int 31h ; создать локальный дескриптор
mov word ptr selectors[edx*2],ax ; сохранить селектор в
mov bx,ax ; таблицу selectors
mov ax,000Ch ; функция DPMI 0Ch
int 31h ; установить селектор
add di,8 ; EDI - следующий дескриптор
dec dx
jns sel_loop

; загрузить селектор сегмента кода в CS при помощи команды RETF
push dword ptr Sel_flatCS ; селектор для CS
ifdef _WASM_
db 066h
endif
push offset PM_entry ; EIP
db 066h ; префикс размера операнда
retf ; выполнить переход в 32-битный сегмент

; сюда передается управление, если произошла ошибка при инициализации DPMI
; (обычно, если DPMI просто нет)
DPMI_error:
push cs
pop ds
mov dx,offset nodpmi_msg
mov ah,9h ; вывод строки на экран
int 21h
mov ah,4Ch ; конец EXE-программы
int 21h
nodpmi_msg db 'DPMI Error$'
RM_seg ends

; сегмент PM_seg содержит код, данные и стек для защищенного режима
PM_seg segment byte public use32
assume cs:PM_seg,ds:PM_seg,ss:PM_seg

; таблица дескрипторов
GDT label byte
; дескриптор для CS
GDT_flatCS db 0FFh,0FFh,0h,0h,0h,0FAh,0CFh,0h
; дескриптор для DS
GDT_flatDS db 0FFh,0FFh,0h,0h,0h,0F2h,0CFh,0h

; точка входа в 32-битный режим - загружен только CS
PM_entry:
mov ax,word ptr Sel_flatDS ; селектор для данных
mov ds,ax ; в DS
mov es,ax ; в ES
mov ss,ax ; и в SS
mov esp,offset PM_stack_bottom ; и установим стек

;============================================================
; отсюда начинается текст собственно программы
; программа работает в модели памяти flat с ненулевой базой
; база CS, DS, ES и SS совпадает и равна линейному адресу начала PM_seg
; все лимиты - 4 Гб


mov eax,0300h ; функция DPMI 0300h
mov ebx,0021h ; прерывание DOS 21h
xor ecx,ecx ; стек не копировать
mov edi,offset RM_regs ; ES:EDI - адрес v86_regs
int 31h ; вызвать прерывание

mov ah,4Ch ; Это единственный способ
int 21h ; правильно завершить DPMI-программу

hello_msg db "Hello from 32-bit protected mode!$"

RM_regs :
RM_EDI dd 0
RM_ESI dd 0
RM_EBP dd 0
RM_XXX dd 0
RM_EBX dd 0
RM_EDX dd offset hello_msg
RM_ECX dd 0
RM_EAX dd 0900h
RM_FLAGS dw 0
RM_es dw 0
RM_ds dw PM_seg
RM_fs dw 0
RM_gs dw 0
RM_ip dw 0
RM_cs dw 0
RM_sp dw 0
RM_ss dw 0


; различные временные переменные, нужные для переключения режимов
DPMI_ModeSwitch dd ? ; точка входа DPMI
PM_seg_addr dd ? ; линейный адрес сегмента PM_seg

; значения селекторов
selectors:
Sel_flatDS dw ?
Sel_flatCS dw ?

; стек для нашей 32-битной программы
DPMI_data: ; и временная область данных DPMI одновременно
db 16384 dup (?)
PM_stack_bottom:
PM_seg ends

; стек 16-битной программы, который использует DPMI-сервер при переключении
; режимов
; Windows 95 требует 16 байтов
; CWSDPMI требует 32 байта
; QDPMI требует 96 байтов
; мы выберем по максимуму
RM_stack segment byte stack 'stack' use16
db 96 dup (?)
RM_stack ends
end RM_entry ; точка входа для DOS - RM_entry
как выделеное сделать процедурой.


Дата: Окт 22, 2003 22:32:47

А так не пробовал?
myproc proc
mov eax,0300h ; функция DPMI 0300h
mov ebx,0021h ; прерывание DOS 21h
xor ecx,ecx ; стек не копировать
mov edi,offset RM_regs ; ES:EDI - адрес v86_regs
int 31h ; вызвать прерывание
endp
;
вызов: call myproc
или я чего-то не понял?


Дата: Окт 23, 2003 13:39:21

lazari
Я тоже не понимаю почему так не работает.


Дата: Окт 23, 2003 14:08:11

Все понил я нетуда текст процедуры прописал.


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.061