org 7C00h
...
rb 7DFEh-$
dw 0AA55h
...
GDTR:
dw GDT_SIZE-1
dd GDT_BASE
align 8
GDT_BASE:
dq 0
desc 0, 0FFFFFh, DF_CODE or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента кода
desc 0, 0FFFFFh, DF_DATA or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента данных
GDT_SIZE=$-GDT_BASE
use32
entry32:
...
virtual ; 32-разрядный стек, под который нужно распределить память
align 1000h
rb 4000h
end virtual
Помогите с загрузчиком
IDEAL
model tiny
codeseg
start:
xor ax,ax
cli
mov ax,cs
mov ss,ax
mov ds,ax
lea sp,[start]
sti
mov si,offset msg
mov ah,0eh
lodsb ;здесь должны
int 10h ;были вывестись
lodsb ;три символа
int 10h ;
lodsb ;
int 10h ;
cli
hlt
msg:
db 'abs'
end start
но почему он выводит вообще другую инфу
Сейчас обычно используется FLAT-модель памяти - это когда все сегменты имеют нулевую базу и размер 4 Гб. В этом случае тебе в начале бинарника нужно указать директиву org 7C00h и, если ты собираешься свой образ загружать в память последовательно (т.е. след. сектор по адресу 7E00h и т.п.), то тебе больше директиву org использовать не нужно, а нужно просто указать во всех дескрипторах сегментов нулевую базу и максимальный лимит, а также страничную гранулярность. В этом случае тебе нужна такая разметка:
Код:
Если ты хочешь использовать свой вариант, то лучше все-таки код и данные хранить в одном адресном пространстве, т.е. сделать базы сегмента кода и сегмента данных/стека одинаковыми, чтобы внутрисегментные адреса внутри этого пространства были одинаковыми вне зависимости от того, какой сегментный регистр ты используешь для доступа к памяти. В этом случае разметка может быть такой:
Код:
org 7C00h
...
rb 7DFEh-$
dw 0AA55h
...
GDTR:
dw GDT_SIZE-1
dd GDT_BASE
align 8
GDT_BASE:
dq 0
desc S_BASE, (S_SIZE+0FFFh)/1000h-1, DF_CODE or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента кода
desc S_BASE, (S_SIZE+0FFFh)/1000h-1, DF_DATA or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента данных
GDT_SIZE=$-GDT_BASE
align 1000h ; так лучше
S_BASE: org0
use32
entry32:
...
virtual ; 32-разрядный стек, под который нужно распределить память
align 1000h
rb 4000h
S_SIZE=$
end virtual
org S_BASE+$ ; если нужно вернуться к прежней адресации
...
rb 7DFEh-$
dw 0AA55h
...
GDTR:
dw GDT_SIZE-1
dd GDT_BASE
align 8
GDT_BASE:
dq 0
desc S_BASE, (S_SIZE+0FFFh)/1000h-1, DF_CODE or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента кода
desc S_BASE, (S_SIZE+0FFFh)/1000h-1, DF_DATA or DF_DUALACTION or \
DF_PRESENT or DF_USE32 or DF_PAGED ; для сегмента данных
GDT_SIZE=$-GDT_BASE
align 1000h ; так лучше
S_BASE: org0
use32
entry32:
...
virtual ; 32-разрядный стек, под который нужно распределить память
align 1000h
rb 4000h
S_SIZE=$
end virtual
org S_BASE+$ ; если нужно вернуться к прежней адресации
Писал от руки без проверки. Может, где-нибудь и ошибся. Если нужен текст макроса desc и определение используемых констант, напиши мне.
Цитата:
а что вы имели ввиду, говоря что org работает иначе?
org не выравнивает текущий адрес на заданное значение, а просто выставляет текущий адрес, равным заданному значению (надеюсь, что ты меня понял :))
Цитата:
чтобы найти какие либо файлы на дискете мне нужно изучить FAT12?
Я тебе (если конечно на wasm.ru писал ты) дважды писал, что ты можешь свободно использовать мой дискетный загрузчик. Нужно лишь изменить основные имена (не расширения) загружаемых файлов. В противном случае, естественно, нужно изучать FAT12, причем досконально.
P.S я так пониамю align - выравнивание на границу 1000h или нет?
например
align 8 - выравнивание на границу 8
align 256 - выравнивание на границу 256
все байты которые будут пропущены будут запонятся нулями, либо командами nop
я лично гуглем нарыл
http://stormdos.narod.ru/the_oldest/osbk/fs.htm
мне этого хватило для того, чтобы написать загрузку ядра с дискеты, правда на си
Цитата:
P.S я так пониамю align - выравнивание на границу 1000h или нет?
да.
[quote="~ArchimeD~"]мне этого хватило для того, чтобы написать загрузку ядра с дискеты, правда на си[/quote]Ты что загрузчик из бутсектора на Си писал? :D
Цитата: Phantom-84
Ты что загрузчик из бутсектора на Си писал? :D
млин, чет я ступил :) . бутсектор конечно на асме, но про него как-то уже забыл, настолько ядром щас занят :D частично на асме, частично на си второй загрузчик.
вопрос про опкоды
сразу говорю читал инфу на wasm'е понятно, но ест один вопрос, а если я использую 16 или 8 битный регистр, то что нужно сделать, а то на wasme не было примера, также читал в справочнике Юрова, там это тоже как-то неподробно написано, плиз помогите
и откуда взять индексы 8 и 16 битных регистров, что бы вписать их в modr/m
то что надо напишет компилятор .
mov al,6 - работа с восьмибитным регистром .
mov ax,6 - с шестнадцатибитным .
mov eax,6 - с тридцатидвухбитным .
0 - al/ax
1 - cl/cx
2 - dl/dx
3 - bl/bx
4 - ah/sp
5 - ch/bp
6 - dh/si
7 - bh/di
fasm немного иначе транслирует команды вида opcode reg, reg, нежели другие компиляторы.
По теме... кто надумает писать буткод для CD, можно скооперироваться... Мне интересен формат CDFS.
koderAlex, хочу сказать, что я не собираюсь писать в опкодах, я же написал, что вопрос не потеме
Извините за такой вопрос, но у меня не получается загрузить второй сектор в память, моя прога весит 1024 байта, в память загружается только первый сектор, но в коде есть jmp на метку которая находится в самом начале второго сектора, так вот как правильно его загрузить через функцию 02h прерывания int 13h ( и если можно скажите, как считать сектора на каком-либо цилиндре и сколько их на каждом целиндре)
Лучше сделай отдельно программу и отдельно загрузчик.
Evgeni, у тебя же вроде дискета была. Там не цилиндры, а треки или по другому дорожки. Диски логически представляются так, что на всех цилиндрах одинаковое число секторов. Навряд ли тебе нужно количество всех секторов на отдельно взятом цилиндре. Скорее всего тебе нужно количество секторов на одной поверхности цилиндра. Так вот и у дискет, и у жестких дисков это значение может быть различным. Однако для стандартных 1,44-мегабайтных дискет количество секторов на одной стороне дорожки равно 18, а у большинства современных жестких дисков число секторов на одной поверхности цилиндра устанавливается равным 63. В любом случае, чтобы прочитать второй по счету сектор диска, нужно увеличить только координату "сектор", оставив другие координаты прежними, т.е. использовать тройку координат C=0, H=0, S=2.
плиз, подскажите, что не так
вот кусок рабочего кода на nasm:
Код:
...
jmp dword 0x8:Pm
[BITS 32]
Pm:
...
jmp dword 0x8:Pm
[BITS 32]
Pm:
...
use32
protected_code:
но все равно vmware ругается
во-первых, возьми в привычку писать, как и на что ругается, во вторых нужно ещё прыжок сделать
Код:
db 0xea
dw protected
dw 0x8
dw protected
dw 0x8
Надо:
Код:
db 0x66
db 0xea
protected:
dd 0
dw 0x8
db 0xea
protected:
dd 0
dw 0x8
protected еще и считать надо к твоему сведению!
Посмотри на wasm.ru!
Код:
if entryproc < 10000h
jmp KCODE:entryproc
else
jmp fword KCODE:entryproc
end if
jmp KCODE:entryproc
else
jmp fword KCODE:entryproc
end if
Кроме того, я заметил в исходнике одно несоответствие. Сигнатура бутсектора естественно должна находиться в конце первого сектора, а не в конце второго, т.е. правильно для твоих двух секторов так:
Код:
org 7C00h
; код для первого сектора
rb 7DFEh-$
db 55h, 0AAh
; код для второго сектора
rb 8000h-$
; если нужно явно заполнить второй сектор до конца,
; то можно написать так: times 8000h-$ db 0
; код для первого сектора
rb 7DFEh-$
db 55h, 0AAh
; код для второго сектора
rb 8000h-$
; если нужно явно заполнить второй сектор до конца,
; то можно написать так: times 8000h-$ db 0
Ну и далее по мелочам:
Код:
;--вычисляем размер GDT----
mov cx,4
shl cx,3
dec cx
;--------------------------
mov [GDT_limit],cx
mov cx,4
shl cx,3
dec cx
;--------------------------
mov [GDT_limit],cx
Код:
mov [GDT_limit], 4*8-1
Код:
GDTR:
dw 4*8-1
dd GDT
dw 4*8-1
dd GDT
Кстати, даже в прикладных программах никто стек в исполняемом файле не хранит, а в данном случае тем более этого делать не нужно. В твоем распоряжении вся доступная память. На первых порах можешь организовать стек под адресом 7C00h.
Код:
gdt:
.word 0, 0, 0, 0 # dummy
.word 0, 0, 0, 0 # unused
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9A00 # code read/exec
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
.word 0, 0, 0, 0 # dummy
.word 0, 0, 0, 0 # unused
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9A00 # code read/exec
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
У меня еще проще:
Код:
DFLAGS = DF_DUALACTION or DF_PRESENT or DF_USE32 or DF_PAGED
align 8
INIT_GDT_BASE: dq 0
desc 0, 0, DF_DATA or DF_EXTENDED or DFLAGS
desc KIMAGE_BASE, (GDT+0FFFh)/1000h-1, DF_CODE or DFLAGS
desc KIMAGE_BASE, (GDT+0FFFh)/1000h-1, DF_DATA or DFLAGS
INIT_GDT_SIZE = $-INIT_GDT_BASE
align 8
INIT_GDT_BASE: dq 0
desc 0, 0, DF_DATA or DF_EXTENDED or DFLAGS
desc KIMAGE_BASE, (GDT+0FFFh)/1000h-1, DF_CODE or DFLAGS
desc KIMAGE_BASE, (GDT+0FFFh)/1000h-1, DF_DATA or DFLAGS
INIT_GDT_SIZE = $-INIT_GDT_BASE
не protected: а dw protected, но при этом все равно не пашет.
vwware выдает следующую ошибку
И еще слышал про линию A20, но я ее не использовал, может кто скажет зачем она нужна
З.Ы. а флоп то есть? попробуй комп со своей дискеты загрузить - что тебе скажет...
Когда линия A20 отключена, можно обращаться только к 1, 3, 5 и т.п. мегам памяти. Пока используешь физическую память в пределах первого мега, насчет A20 можно не париться.
А какой это тогда за битик на адресной линии???
А разве из названия не ясно, что 20-ый???
Цитата: Phantom-84
А разве из названия не ясно, что 20-ый???
Блин точно!
но подскажите как точно нужно совершить прыжок: в моем случае код начинается с метки protected_code:, плиз ответте
Код:
if protected_code < 10000h
jmp code_selector:protected_code
else
jmp fword code_selector:protected_code
end if
jmp code_selector:protected_code
else
jmp fword code_selector:protected_code
end if
все равно при этом вылазиет эта ошибка, может быть это потому что я пытаюсь выйти в защищенный режим в vmware? я даже в самом начале кода для PM написал бесконечный цикл, что бы хоть проверить, зашел ли я в PM, однако ошибка не устраняется
Кроме того, я так и не понял, как у тебя обстоят дела с сегментами. Покажи обновленный исходник.
А стек не забыл инициализировать перед прыжком в защищенный режим? В ss селектор данных нужно загнать.
Такие вещи лучше бочсем запускать, так как он выводит регистры и ошибочную ситуацию при крахе!
Там много чего не так. Например, уже в PM после вывода строки будут выполняться данные. Хотя бы jmp $ напиши. Стек размером 265 байт - это круто. Может, ты хотел написать 256. И даже если так, то его лучше все-таки выровнять на границу слова.
Код:
[CPU0 ] branch_far: RIP > limit
[CPU0 ] interrupt(): gate descriptor is not valid sys seg
[CPU0 ] interrupt(): gate descriptor is not valid sys seg
[CPU0 ] protected mode
[CPU0 ] CS.d_b = 16 bit
[CPU0 ] SS.d_b = 16 bit
[CPU0 ] | EAX=00000011 EBX=00007d50 ECX=00007e92 EDX=00000fa0
[CPU0 ] | ESP=00007c00 EBP=00000000 ESI=00007d28 EDI=0000ffde
[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
[CPU0 ] | SEG selector base limit G D
[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
[CPU0 ] | CS:0000( 1e00| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | DS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | SS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | EIP=00007cdd (00007cdd)
[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
[CPU0 ] | CR3=0x00000000 CR4=0x00000000
[CPU0 ] >> jmp far 0008:7e00 : EA007E0800
[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
[CPU0 ] interrupt(): gate descriptor is not valid sys seg
[CPU0 ] interrupt(): gate descriptor is not valid sys seg
[CPU0 ] protected mode
[CPU0 ] CS.d_b = 16 bit
[CPU0 ] SS.d_b = 16 bit
[CPU0 ] | EAX=00000011 EBX=00007d50 ECX=00007e92 EDX=00000fa0
[CPU0 ] | ESP=00007c00 EBP=00000000 ESI=00007d28 EDI=0000ffde
[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
[CPU0 ] | SEG selector base limit G D
[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
[CPU0 ] | CS:0000( 1e00| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | DS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | SS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
[CPU0 ] | EIP=00007cdd (00007cdd)
[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
[CPU0 ] | CR3=0x00000000 CR4=0x00000000
[CPU0 ] >> jmp far 0008:7e00 : EA007E0800
[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Код:
include "desc.inc"
VIDEOSEL equ 8
CODESEL equ 10h
DATASEL equ 18h
org 7C00h
start: xor ax, ax
cli
mov ss, ax
mov sp, start
sti
jmp 0:@f
@@: lgdt [ss:GDTR]
cli
mov eax, cr0
or al, 1
mov cr0, eax
jmp CODESEL:@f
@@: mov ax, DATASEL
mov ds, ax
mov fs, ax
mov gs, ax
mov ss, ax
push VIDEOSEL
pop es
xor di, di
cld
mov ax, 3320h
mov cx, 80*25
rep stosw
jmp $
GDTR: dw 4*8-1
dd GDT
align 8
GDT: dq 0
desc 0B8000h, 7FFFh, DF_PRESENT or DF_DATA or DF_DUALACTION
desc 0, 0FFFFh, DF_PRESENT or DF_CODE or DF_DUALACTION
desc 0, 0FFFFh, DF_PRESENT or DF_DATA or DF_DUALACTION
rb 7DFEh-$
dw 0AA55h
VIDEOSEL equ 8
CODESEL equ 10h
DATASEL equ 18h
org 7C00h
start: xor ax, ax
cli
mov ss, ax
mov sp, start
sti
jmp 0:@f
@@: lgdt [ss:GDTR]
cli
mov eax, cr0
or al, 1
mov cr0, eax
jmp CODESEL:@f
@@: mov ax, DATASEL
mov ds, ax
mov fs, ax
mov gs, ax
mov ss, ax
push VIDEOSEL
pop es
xor di, di
cld
mov ax, 3320h
mov cx, 80*25
rep stosw
jmp $
GDTR: dw 4*8-1
dd GDT
align 8
GDT: dq 0
desc 0B8000h, 7FFFh, DF_PRESENT or DF_DATA or DF_DUALACTION
desc 0, 0FFFFh, DF_PRESENT or DF_CODE or DF_DUALACTION
desc 0, 0FFFFh, DF_PRESENT or DF_DATA or DF_DUALACTION
rb 7DFEh-$
dw 0AA55h
Гораздо более большая проблема это работа с флоппом и ФС, ИМХО!
Читай выше. Я уже обращал на это внимание. Аффтар принципиально не хочет юзать чужие загрузчики, но зато побыстрее хочет перейти в PM. К слову, PM c 16-разрядными сегментами, без страничной переадресации вообще не очень-то и от RM отличается. Вопрос про 32-разрядный код был поднят давно, но в исходнике он вообще не представлен.
Вопрос к Phantom-84, не можешь ли ты скинуть файл desc.inc, ато у меня его нет, и еще не можешь ли сказать как запустить свой бинарник в bochs( у меня версия 2.3.5)