|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Мар 12, 2004 00:48:05 Премного извиняюсь за столь идиотский вопрос (мне правда стыдно :((, но почему не работает следующее: PMSEG segment para public 'CODE' use32 ... mov edx, offset label call edx ; понятно, чего я хочу ... label: PMSEG ends ; Или как вариант: PMSEG segment para public 'CODE' use32 ... push offset label retn ... label: PMSEG ends Всё сие действо происходит в PM, но по-моему это не повод, чтобы не работать. При этом call label работает замечательтно. Кто предумает, заодно укажите как это будет в случае 1, если вместо регистра, нужный адрес хранится в переменной, которая находится в аналогичном сегменте, но только 'DATA' |
|
|
Дата: Мар 12, 2004 01:16:17 А что происходит-то? Ну сделал ты свой регистровый вызов, а что потом? GPF? |
|
|
Дата: Мар 12, 2004 01:54:56 Если верить моему обработчику ошибок, то Unknown command, хотя чего-то меняя (по-моему сегментные регистры) и GPF схлопатал. Код call edx : FF D2, в реальном работает превосходно, а тут чё-то совсем не понятное |
|
|
Дата: Мар 13, 2004 03:34:41 Вообще то всё правильно. call edx должен работать так, как ты хочешь. Вопрос в том, что идет после label: PMSEG ends Ты трассировал это под отладчиком? |
|
|
Дата: Мар 13, 2004 16:12:59 Дело в том, что на самом деле label - это процедура, причём вида label proc. Эта процедура читает физический сектор и входит в ядро моей ОС. Мне захотелось вызывать её не на прямую (call label), а так: call var, где var содержит смещение процедуры. Это надо для того, чтобы я всегда мог подменить реальную процедуру любой другой. Сначала я думал, что всё не работает только потому, что переменная находится в сегменте данных, а процедура - кода, но когда я написал: mov ebx,offset label call ebx то не получил ничего из того что хотел. Я не понимаю:(. Процедура лежит в том же сегменте, что и её вызов, т.е. тип near. В real'e работает идеально подобное действие. Может P-mode надо настраивать особо. Я даже записал сие в кодах, дабы проверить, не ошибся ли компилятор, но не помогло... Затем я нагрешил на COM-файл, но тоже зря - в exe-шниках тоже самое... |
|
|
Дата: Мар 13, 2004 17:35:37 Все равно ничего не понятно :-( Что не работает то?! Покажи весь кусок кода. |
|
|
Дата: Мар 13, 2004 19:01:25 И gdt. Может быть ты малость напутал с размерами операнда/адреса и тп Или заехал за границу сегмента. Неплохо бы вывести все данные в обработчике на экран. |
|
|
Дата: Мар 13, 2004 21:15:03 Во-первых, на счёт отладчика :). Мне который раз советают сие граждане посмотреть этот баг под отладчиком. Вынужден признаться, что не знаю как это сделать, ибо мне не известен отладчик который мог бы отладить ДОС com-файл, содержащий два вида режима работы проца. Ну да не об этом. Дабы далеко не ходить, пресылаю попросту немного переделанный код Зубкова (книга такая клёвая про асм, если кто не читал) который запарывается на том же самом, судите<:(
.model tiny
.code
.486p
org 100h
start: mov cs1,cs ; load real segment address
; Opening A20
in al,92h
or al,2
out 92h,al
; Count linear address of pm_entry
xor eax,eax
mov ax,cs
shl eax,4
mov ebx,eax
add eax,offset pm_entry
mov pm_entry_addr,eax
; Count base for gdt_16bit_cs_l
mov eax,ebx
mov word ptr gdt_16bit_cs_l+2,ax
shr eax,16
mov byte ptr gdt_16bit_cs_l+4,al
; Count linear address of gdt
mov eax,ebx
add eax,offset gdt
mov dword ptr gdtr+2,eax
; Load GDT
lgdt fword ptr gdtr
; Disable interrupts
cli
in al,70h
or al,80h
out 70h,al
; Start protected mode
mov eax,cr0
or al,1
mov cr0,eax
; Go to 32-bit flat code segment
db 66h
db 0EAh
pm_entry_addr dd ?
dw SEL_FLAT_CS
;********************************************************************* *******
; Return to real mode
pm_ret:
mov eax,cr0
and al,0FEh
mov cr0,eax
; Reset prefetch queue
db 0EAh ; jmp
dw $+4 ; next command
cs1 dw ? ; cs
; Enable interrupts
in al,70h
and al,07Fh
out 70h,al
sti
; Exit
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;
;; RM DATA ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;
gdt label byte
db 8 dup(0)
gdt_flat_cs db 0FFh,0FFh,0,0,0,10011010b,11001111b,0
gdt_flat_ds db 0FFh,0FFh,0,0,0,10010010b,11001111b,0
gdt_16bit_cs_l db 0FFh,0FFh,0,0,0,10011010b,0,0
gdtr dw $-gdt-1
dd ?
SEL_FLAT_CS equ 00001000b
SEL_FLAT_DS equ 00010000b
SEL_16BIT_CS_LOCAL equ 00011000b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;
;; PM ENTRY ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;
PMSEG segment para public 'CODE' use32
assume cs:PMSEG
pm_entry:
mov ax,SEL_FLAT_DS
mov es,ax
mov edi,0B8000h
; Эти две строки печатают две буквы 'p' на экране
call z
call z
; А эта строка запарывает всю систему
mov esi,offset z
call esi
; Exit PM
db 0EAh
dd offset pm_ret
dw SEL_16bit_CS_LOCAL
z: mov word ptr es:[edi],7070h
add edi,2
ret
PMSEG ends
END start
Компилится сие masm 6.11 или подобным. Смотрите, если я конечно в чём-нибудь не прав, сильно не ругайтесь. Я ещё юзер в PM (:<(, по крайней мере в исправление неизвестного мне. P.S. если кто действительно знает такие отладчики (см.выше), просьба указать место, где их взять за бесплатно (денег у меня вообще 0xFFFFFFFF+1) |
|
|
Дата: Мар 13, 2004 22:31:17 · Поправил: Valery Иисус Мария, а как вообще хоть один call без стека работает? У тебя же остался досовский стек! Замени call/ret на jmp/jmp и еще раз проверь. Может и не в этом дело, но все равно так нельзя. Попробуй еще для единообразия сделать все use 16 с префиксами. И еще раз проверь значения в дескрипторах - лень за тобой смотреть. Наконец, выведи на экран offset. PS Это и есть твоя ось? |
|
|
Дата: Мар 13, 2004 22:37:22 Это не ось :-) и даже не кусок, что касается стека, он остаётся досовым, ну и что??? |
|
|
Дата: Мар 13, 2004 22:56:16 Область памяти под него всеравно выделена. И ещё, ты сам то JMP проверял??? У меня не пашет. На счёт use 16 с префиксами вообще не понял причём здесь они, а вывести на экран offset (я так понял для проверки его правильности) то оно-то всегда правильное. В этом всё и дело, что инструкция правильная, но не работает. Вопрос: а этот исходник у тебя запустился? Если да, обязательно скажи, буду простреливать себе голову и обе руки :-) |
|
|
Дата: Мар 13, 2004 23:08:05 Kirk offset z это смещение относительно начала PMSEG (или CODEGROUP?), а дескриптор gdt_flat_cs описывает сегмент с базой = 0. Программа то не с нулевого адреса загружена! |
|
|
Дата: Мар 14, 2004 00:01:08 Большое человекское спасибо тебе, Black_mirror, действительно я не подумал об этом. Эту часть брал у Зубкова и мне даже в голову не пришло, что там сегмент кода может быть нулевым (правда там это было для EXE-файла и для тех примеров, которые там, данная проблема роли не играла). Хотя как АСМ'овец, я конечно каюсь, я должен был это предвидеть, но видимо я ещё духовно не вырос в свои 19 :-(. Пойду дзен-философию изучать и духовно совершенствоваться. Спасибо ещё раз, не знаю, когда бы я сам решил эту проблему :-) |
|
|
Дата: Мар 14, 2004 00:02:49 · Поправил: Valery Мда, давно не грузился я досовским загрузчиком... Kirk Если уж вычислять адрес кода в рантайме, то может тебе поможет вот этот тред: http://www.wasm.ru/forum/index.php?action=vthread&forum=3&topic=5192 ("Определение ip") Это как раз то самое - когда офсет неизвестен. Хотя настоящую jump table так делать накладно будет:) |
|
|
Дата: Мар 14, 2004 03:15:35 Kirk Можно очень сильно упростить себе жизнь сделав два дескриптора(для кода(32х-битный) и для данных),с базой там, куда загрузилась программа(перед переключением в PM придется их малось подправить), и лимитом 64К. А третий дескриптор пусть описывает всю память. Все сегменты(и 16, и 32 битные) объединяешь в одну группу. И пишешь: assume cs,ds,ss: mygroup. Вряд ли в ближайшее время размер твоей ОС превысит 64К. А так можно избежать головной боли с вычислением смещений. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.049 |