Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.08.2010, 17:21   #1
finny
 
Регистрация: 31.08.2010
Сообщений: 7
По умолчанию Переход в нереальный режим в загрузчике

Требуется написать загрузчик ОС Windows c подсчётом контрольной суммы ROM BIOS. ROM BIOS Расположен в верхних областях памяти, начинаясь с адреса 0xfff80000. Загрузчик работает в реальном режиме. В реальном режиме адресация - 16разрядная, и память выше 1-ого мегабайта недоступна. Для данной задачи необходим сегмент данных размером 4 гб. Поэтому резонно перейти в нереальный режим.
В примерах перехода в нереальный режим пишется, что при смене режимов работы процессора нужно применять дальние переходы (far jump) и задейстовать другой сегмент кода. Может быть это работает в ОС DOS, но в загрузчике это приводит к перезагрузке компьютера даже при запрете всех прерываний. С ближними переходами переход в нереальный режим вроде как происходит и можно использовать 32-разрядную адресацию, но при обращении по адресу 0xfff80000 и выше можно получить лишь 0xffffffff, что не похоже на данные bios. То есть похоже на то, что старшее слово 32-битного адреса просто вырождается. Таким образом контрольная сумма ес-но получается разной каждый раз при загрузке. Ниже приведён код на fasm:

Код:
org 7E00h

CMOS_ADDR      equ  0070h
CMOS_DATA      equ  0071h

start:
        
; Сохранить регистр флагов
        pushf
; Запретить прерывания, так как таблица прерываний IDT
; не сформирована для защищенного режима
        cli
; Запретить немаскируемые прерывания NMI
        in      al,CMOS_ADDR
        mov     ah,al
        or      al,080h      ;установить старший разряд
        out     CMOS_ADDR,al ;не затрагивая остальные
        and     ah,080h
        ; Запомнить старое состояние маски NMI
        mov     ch,ah
; Перейти в защищенный режим
        lgdt    fword [cs:GDTPtr]
        mov     bx,cs    ;запомнить сегмент кода

        mov     eax,cr0
        or      al,1   ;установить бит PE
        mov     cr0,eaX  ;защита разрешена

	jmp	SetPMode

SetPMode:
        ; Подготовить границы сегментов
        mov     ax,8
        mov     ss,ax
        mov     ds,ax
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
	

; Вернуться в реальный режим
        mov     eax,cr0
        and     al,11111110b ;сбросить бит PE
        mov     cr0,eax      ;защита отключена

        jmp	SetRMode

SetRMode:
        ; Регистры стека и данных
        ; настроить на сегмент кода
        mov     ss,bx
        mov     fs,bx
        
	xor	ax,ax
	mov	ds,ax
	mov	es,ax
        ; Возврат в реальный режим,
        ; прерывания снова разрешены
        in      al,CMOS_ADDR
        and     al,07fh
        or      al,ch
        out     CMOS_ADDR,al
        popf

	in	al, 0x92
    	or	al, 2
    	out	0x92, al


	; read BIOS ROM 0xfff80000 - 0xffffffff (512K)
    	mov	esi, 0xfff800b5		
    	mov	ecx, 0x80000
    
calc_crc32:
	 mov	edx, eax			; copy CRC into EDX
	 lodsb                              	; load next byte into AL
	 xor 	edx, eax                       	; put array index into DL
	 shr 	eax, 8                         	; shift CRC one byte right
	 shl 	edx, 2                         	; correct EDX (*4 - index in array)
	 xor 	eax, dword [cs:crc_tbl + edx] 	; calculate next CRC value
	 dec   	ECX
	 loop	calc_crc32
    
	 not   	eax
	 mov	dword [cs:csum_final], eax   

	xor	ecx, ecx
output:	
	mov	ah, [cs:csum_final + ecx]
	mov	ebx, 0xb8000
	mov	edx, 4
	imul	edx, ecx
	add	ebx, edx
A2C:
    	mov  	al, ah
    	shr  	ah, 4
    	and  	al, 0Fh
    	add  	ah, '0'
    	add  	al, '0'

    	cmp  	ah, '9'
    	jle  	ff
    	add  	ah, 7
ff:
	mov	byte [ebx], ah
	mov	byte [ebx + 1], 7	

    	cmp 	al, '9'
    	jle 	gf
    	add 	al, 7
gf:
	mov	byte [ebx + 2], al
	mov	byte [ebx + 3], 7	
	
	inc	ecx	
		
	cmp	ecx, 4
	jb	output

	mov  	ah, 0
        int	016h

fin:
	xor    	ax, ax
	push   	ax                                  ; PUSH 0x0000 - Segment
	mov    	di, 07c00h
	push   	di                                  ; PUSH 0x7C00 - Offset
        retf 	  	

;include "flat.inc"
GDTTable:
d_zero     db  0,0,0,0,0,0,0,0                 ; Null descriptor
d_data32   db  0ffh,0ffh,0,0,0,92h,0cfh,0      ; Loader data descriptor

GDTPtr:	
g_size    dw    15
g_base    dd    GDTTable

csum_init:
    dd		0xffffffff
csum_final:
    dd		0xdeadbeef
crc_tbl:
;    		Таблица для расчёта crc32

Внимание, вопросы! (Чтобы не писали потом: а в чём же вопрос и чего я хочу)
1. Правильно ли произведён переход в нереальный режим?
-Если правильно, то как правильно получить доступ к данным начиная с адреса 0xfff80000
-Если неправильно, то где ошибка
2. Как в реальном режиме в отсутствии ОС DOS получить доступ к данным по адресу 0xfff80000 и выше?

Последний раз редактировалось Stilet; 01.09.2010 в 17:11.
finny вне форума Ответить с цитированием
Старый 31.08.2010, 17:32   #2
Sparky
Участник клуба
 
Аватар для Sparky
 
Регистрация: 15.05.2009
Сообщений: 1,222
По умолчанию

я не смотрела ваш код, но быть может пригодиться, код загрузчика защищенного режима есть в книге Зубкова
Единственное, что ограничивает полет мысли программиста-компилятор
Sparky вне форума Ответить с цитированием
Старый 31.08.2010, 20:44   #3
finny
 
Регистрация: 31.08.2010
Сообщений: 7
По умолчанию

Я читал книгу Зубкова, но кода загрузчика там не встретил. Может разные издания? Уточните, пожалуйста, какое издание и если можно, то приведите этот код
finny вне форума Ответить с цитированием
Старый 01.09.2010, 17:00   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

надо перейти в защищенный, один из сегментных регистров поставить на линейный режим, потом вернутся обратно, и сегментный регистр не трогать(например fs)
Цитата:
Может быть это работает в ОС DOS, но в загрузчике это приводит к перезагрузке компьютера даже при запрете всех прерываний. С ближними переходами переход в нереальный режим вроде как происходит и можно использовать 32-разрядную адресацию, но при обращении по адресу 0xfff80000 и выше можно получить лишь 0xffffffff, что не похоже на данные bios. То есть похоже на то, что старшее слово 32-битного адреса просто вырождается.
GDT установлена?(вроде да)
сама GDT верна?(вам нужен кодовый сегмент и сегмент данных на все пространство(его селектор потом назначим fs))
линия A20 открыта?(помоему нет)
переход в защищенный, только через дальный прыжок по <селектор кодового сегмента>:<смещение(относительно начала сегмента)>
команда дальнего прыжка должна быть сразу после включение защищенного режима.

посмотрите sasm.narod.ru
(еще помню было в книге про аппаратное программирование, автора не помню)

то что мне не нравится я выделил смайлами.
посмотрите у нас темы про разработку ОС(две темы существует)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 02.09.2010, 00:12   #5
finny
 
Регистрация: 31.08.2010
Сообщений: 7
По умолчанию

А на каком участке включать 20-ый вентиль?
finny вне форума Ответить с цитированием
Старый 02.09.2010, 00:24   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

до попытки перехода в PM
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.09.2010, 14:08   #7
finny
 
Регистрация: 31.08.2010
Сообщений: 7
По умолчанию

Переработал код, используя при переключении режимов дальние переходы, но проблема чтения верхних областей памяти по-прежнему осталась, вдобавок прерывания (установка видеорежима или чтение клавиатуры) приводят к зависанию компьютера. Вот код:

Код:
org 07E00h

CMOS_ADDR      equ  0070h
CMOS_DATA      equ  0071h
	
USE16
start:		

	pushf

	cli

	in      al,CMOS_ADDR
        mov     ah,al
        or      al,080h      ;установить старший разряд
        out     CMOS_ADDR,al ;не затрагивая остальные
        and     ah,080h
        ; Запомнить старое состояние маски NMI
        mov     ch,ah

 
	lgdt    [cs:GDTR]               ; Загрузка адреса глобальной таблицы дескрипторов

; если мы собираемся работать с 32-битной памятью, стоит открыть А20
        in         al,92h
        or         al,2
        out        92h,al
 
	mov     eax, cr0                 ; Переключение в защищенный режим
	or      al,1
	mov     cr0,eax
 
	db 	0eah
	dw 	SetPMode
	dw 	8

USE32
SetPMode:
	mov 	ax,10h		
	mov 	fs,ax
	mov	ax,18h
	mov 	gs,ax	 
	
	mov	[gs:0], byte 'R'
	mov	[gs:1], byte 7
	mov	[fs:0xb8002], byte 'M'
	mov	[fs:0xb8003], byte 7

	db      0EAh                    ; код дальнего jmp
        dd      RM_return        	; 32-битное смещение
        dw      20h	                ; селектор

RM_return:

; переключиться в реальный режим
        mov     eax,cr0
        and     al,0FEh
        mov     cr0,eax

USE16
	
rm:
	xor	ax, ax
	mov	fs, ax
	mov	gs, ax
; Возврат в реальный режим,
; прерывания снова разрешены
        in      al,CMOS_ADDR
        and     al,07fh
        or      al,ch
        out     CMOS_ADDR,al
        popf	

	
	xor	ecx, ecx
output:	
	mov	ah, byte [fs:0xfff80000 + ecx]
	mov	ebx, 0xb8004
	mov	edx, 4
	imul	edx, ecx
	add	ebx, edx
A2C:
    	mov  	al, ah
    	shr  	ah, 4
    	and  	al, 0Fh
    	add  	ah, '0'
    	add  	al, '0'

    	cmp  	ah, '9'
    	jle  	ff
    	add  	ah, 7
ff:
	mov	byte [fs:ebx], ah
	mov	byte [fs:ebx + 1], 7	

    	cmp 	al, '9'
    	jle 	gf
    	add 	al, 7
gf:
	mov	byte [fs:ebx + 2], al
	mov	byte [fs:ebx + 3], 7	
	
	inc	ecx	
		
	cmp	ecx, 4
	jb	output


	mov  	ah, 0
           int	016h       ;прерывание приводит к зависанию, без него загрузка происходит

gg:
	xor	ax, ax
	push	ax
	mov	di, 0x7C00
	push	di
	retf

	 
	var	dd	0xdeadbeef 

	GDTR:	                                      ; Global Descriptors Table Register
  		dw 6*8-1                              ; Размер GDT
	  	dd GDT                                ; Смещение GDT
 
	GDT:
	; нулевой дескриптор (обязательно должен присутствовать в GDT!)
		NULL_descr              db      8 dup (0)
	; дескриптор 32-разрядного сегмента кода:   база = 00000000h, размер = FFFFFFFFh
		CODE_descr              db      0FFh, 0FFh, 00h, 00h, 00h, 10011010b, 11001111b , 00h
	; дескриптор 32-разрядного сегмента данных: база = 00000000h, размер = FFFFFFFFh
		DATA_descr              db      0FFh, 0FFh, 00h, 00h, 00h, 10010010b, 11001111b , 00h
	; дескриптор сегмента видеопамяти:          база = 000B8000h, размер = 0000FFFFh
		VIDEO_descr             db      0FFh, 0FFh, 00h, 80h, 0Bh, 10010010b, 01000000b , 00h
	; дескриптор 16-разрядного сегмента кода:   база = 00000000h, размер = FFFFFFFFh
		CODE16_descr            db      0FFh, 0FFh, 00h, 00h, 00h, 10011010b, 00h , 00h
	; дескриптор 16-разрядного сегмента данных: база = 00000000h, размер = FFFFFFFFh
		DATA16_descr            db      0FFh, 0FFh, 00h, 00h, 00h, 10010010b, 00h , 00h
Что в этом коде некорректно? Жду ваших комментариев и советов

From Stilet: Некорректно в этом коде то что ты его не оправил форматированием, принятым здесь для кода по кнопке #

Последний раз редактировалось Stilet; 03.09.2010 в 14:22.
finny вне форума Ответить с цитированием
Старый 03.09.2010, 14:34   #8
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

странно, с виду все верно.
под Bochs проверяли?

http://sasm.narod.ru/docs/pm/pm_in/chap_10.htm это о возврате в режим реальных адресов.

советую всетаки скачать ту книгу что я сказал(помоему и есть Зубков)
это в разделе недокоментированных возможностей процессора(примерно так)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
режим отключения Neostryak Microsoft Office Access 0 24.05.2010 14:44
переход в реальный режим и обратно [Assembler] Айат Помощь студентам 8 11.04.2009 01:43
Полноэкранный режим Devoto Общие вопросы Delphi 4 05.12.2008 13:42
многопользовательский режим Nastay Помощь студентам 1 04.04.2008 19:57
переход в полноэкранный режим andrey4623 Общие вопросы Delphi 7 11.03.2008 09:28