Diskuze: Zápis souborového systému na disk
V předchozím kvízu, Online test znalostí Assembler, jsme si ověřili nabyté zkušenosti z kurzu.




Domiy:15.6.2013 16:47
Disk je přeci tady:
mov [BootDev], dl
mov ah, 8h
int 13h
Později to snad nějak rozvětvím...
Já to s těma CHS adresama také moc neumím. Zkoušel jsem to cca před pěti lety a ani nevím, zda jsem to tehdy naprogramoval dobře, protože pár dní na to díky chybě v synchronizaci zmizela většina souborového systému z disku...
Myslím, že by bylo lepší se problémy s cylindry, hlavami, stopami a sektory vyhnout tím, že pro čtení využiješ funkci 42h (Extended Read) viz http://en.wikipedia.org/wiki/Int_13h#…. Pak se stačí jen zadat číslo sektoru a je hotovo.
U toho tvého kódu ještě nevidím nastavovaní registru ES, který bys mohl třeba vynulovat předtím, než načítáš ty sektory (aby ES:BX ukazovalo na nějaou rozumnou adresu).


Domiy:15.6.2013 17:59
Nevidím tam registr pro parametr sektoru a počtu sektorů k načtení do paměti... Paměť je mi jedno jaká to bude - prostě do ní pak skočím... (Jak sám jistě vidíš...)


Domiy:15.6.2013 18:03
Ale já tu adresu nastavil - ne?
mov si, 32768
mov bx, si
Nebo alespoň to jsem tam měl před změnou souborového systému a běželo to...


Domiy:15.6.2013 18:23
Vyčištěno:
BITS 16
jmp short Boot
nop
OEMLabel db "SMA-BOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per Cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for disk
VolumeID dd 00000000h
VolumeLabel db "SMA-OP "
FileSystem db "DSP "
SMA.Load:
mov ah, 42h
mov al, 37
mov cl, 2
mov si, 32768
mov bx, si
int 13h
ret
Boot:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
; NOTE: A few early BIOSes are reported to improperly set DL
cmp dl, 0
je NoChange
mov [bootDev], dl ; Save boot device number
mov ah, 8h ; Get drive parameters
int 13h
jc FataldiskError
NoChange:
mov eax, 0
mov cx, 32768
call SMA.Load
jc FataldiskError
mov ax, 0
mov bx, 0
mov cx, 0
mov dx, 0
mov di, 0
mov si, 0
jmp 32768
PrintString:
pusha
mov ah, 0Eh
.write:
lodsb
cmp al, 0
je .done
int 10h
jmp short .write
.done:
popa
ret
FataldiskError:
mov si, diskError
call PrintString
Reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h
diskError db "Disk error! Press any key...", 0
bootDev db 0 ; Boot device number
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
Buffer: ; Disk Buffer begins (8k after this, stack starts)
Jediné čím si nejsem jist - zda se správně nastaví buffer. To se
dozvím později...
Ten buffer pro načtená data je určen registry ES:BX. Nevidím tam nikde, že bys nastavoval registr ES. Ale je možné, že tento registr je ve výchozím nastavení nulový, takže není pořádně co nastavovat.
Ta funkce 42h (Extended Read) funguje jinak - parametry operace se ukládají do paměti, ne do registrů AFAIK.
Tohle je část mého MBR, která načítá originální MBR, který je uložen na sektoru 1 (druhý sektor).
mov ax, 04200h
push ax
mov dx, 80h
mov si, @data
add si, 6000h
push si
int 13h
pop si
jmp nekam_dal
data:
dw 10h ; structure length
dw 1 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 1 ; Secntor number (low 32 bits)
dd 0 ; Sector number (high 32 bits)
nekam_dal:


Domiy:15.6.2013 19:02
Nechceš mi poslat kód pro můj případ? (Jsem zničen z toho dorovnání kernelu. Vše je při stavění správně, ale výsledek je větší o 2 sektory - poslední navíc není plný...)


Domiy:15.6.2013 19:38
Je to tam! Ještě to
zobecním pro všechny vstupy a juknu se na toto...


Domiy:16.6.2013 6:46
SMA.Load:
mov ah, 42h
mov si, .SMA.Load.Params
mov dl, bootDev
int 13h
ret
.SMA.Load.Params:
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 1 ; Secntor number (low 32 bits)
dd 0 ; Sector number (high 32 bits)
Skáči tedy na 7c00h, jenže nic se nenačte... První věc - jedná se o
druhý, nebo první sektor? Tedy má myšlenka - když nastavím velikost
sektoru na 1024, tak VBR přeci bude pořád 512 - ne? Takže mám VBR
zahrnovat? Druhá věc - co znamená údaj "structure length"?
Děkuji.
Skáči tedy na 7c00h
Jakým způsobem to spouštíš a ladíš? Na jaké adrese se nachází tento boot. sektor?
První věc - jedná se o druhý, nebo první sektor?
Druhý sektor. U LBA se sektory číslují od nuly.
co znamená údaj "structure length"?
Velikost struktury s parametry služby 42h, předávané v DS:SI. Viz Wikipedie nebo třeba Ralph Brown's Interrupt List (či jiná dokumentace, kde se popisují přerušení BIOSu).


Domiy:16.6.2013 11:36
Pokud se čísluje od 0, tak je to 1. sektor - ne? (0 = BootSector, 1 = Kernel - kernel je hned za VBR) Jde mi o to, že když dám velikost sektoru 1024, VBR bude stejně 512 - ne? A jak by mohl číst 512byte sektor s nastaveným sektorem 1024... Nehádám se - jen si potřebuji udělat jasno. VBR se tedy počítá?
Aktuální stav:
BITS 16
SMA.Load.Params:
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 0 ; Secntor number (low 32 bits)
dd 2 ; Sector number (high 32 bits)
jmp short Boot
nop
OEMLabel db "SMA-BOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per Cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for disk
VolumeID dd 00000000h
VolumeLabel db "SMA-OP "
FileSystem db "DSP "
SMA.Load:
mov ah, 42h
mov si, SMA.Load.Params
mov dl, bootDev
int 13h
ret
Boot:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
cmp dl, 0 ; A few early BIOSes are reported to improperly set DL
je NoChange
mov [bootDev], dl ; Save boot device number
mov ah, 8h ; Get drive parameters
int 13h
jc FataldiskError
NoChange:
mov eax, 0
call SMA.Load
jc FataldiskError
mov ax, 0
mov bx, 0
mov cx, 0
mov dx, 0
mov di, 0
mov si, 0
jmp 7c00h
PrintString:
pusha
mov ah, 0Eh
.write:
lodsb
cmp al, 0
je .done
int 10h
jmp short .write
.done:
popa
ret
FataldiskError:
mov si, diskError
call PrintString
Reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h
diskError db "Disk error! Press any key...", 0xA, 0
bootDev db 0 ; Boot device number
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
Buffer: ; Disk Buffer begins (8k after this, stack starts)
Jak jsem psal již někde nahoře - chci jen ušetřit zbytečné hledání a přesně vytyčit co z BootSectoru načíst. (Kernel jen pro začátek.) Kernel si pak již přečte načtené atd.
A aktuálně skládám soubory do systému přeložením do binární podoby, dorovnáním do čísla dělitelného 512 a přilepením do fronty... Jak se mi podaří spustit kernel, přidám své vysněné soubory a systémové funkce... (Stejným způsobem.)


Domiy:16.6.2013 11:42
A mám na tebe ještě jeden dotaz. Jak si vezme počítač ty parametry nahoře:
OEMLabel db "SMA-BOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per Cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for disk
VolumeID dd 00000000h
VolumeLabel db "SMA-OP "
FileSystem db "DSP "
Nikde jsem nenašel jak to funguje. Záleží na čem? Na pojmenování? (minimálně case je všude jiné) Myslíš, že mám vše potřebné ke správnému čtení clusterů a hlavně sektorů?
Díky.
A mám na tebe ještě jeden dotaz. Jak si vezme počítač ty parametry nahoře
komponentě zodpovědné za práci se souborovými systémy FAT je srdečně jedno, jak si jednotlivé položky v boot. sektoru pojmenuješ. Klidně si můžeš vzít Erbenova Vodníka a jako názvy jednotlivých položek zvolit jeho úvodní vere. Operační systém názvy nevidí, vidí jen výslednou strukturu boot. sektoru po překladu. Takže pro něj je důležité, aby všechny položky byly na správném místě a aby obsahovaly správná data.
V tom kódu výše jsi předřadil ta data pro 13h Extended Read začátku toho boot. sektoru, takže se v tom FAT driver absolutně nevyzná. Ta data umisti někam do bootovacího kódu. A tak, jak jsi je upravil, tak se bude driver pokoušet načíst sektor s číslem 200000000h (číslováno od nuly), což asi nechceš. x86 je little-endian platforma.
Nechci se tě dotknout, ale doporučoval bych ti si přečíst nějakou knížku o obecných pricnipech, které se v operačních systémech používají (včetně souborových systémů). Docela dobrá knížka je třeba http://www.amazon.com/…p/0131429388. V mojí knize je toho také docela dost platného nejen pro Windows, ale ta cena za to je pro tebe moc vysoká.


Domiy:16.6.2013 13:13
Já si to myslel... (Že to bere jako celek.)
Pozice struktury parametrů jsem se snažil zařadit tak, aby to nevzalo co nemá... Takže:
BITS 16
jmp short Boot
nop
OEMLabel db "SMA-BOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per Cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
NumberOfDSPs db 2 ; Number of copies of the DSP
RootDirEntries dw 224 ; Number of entries in root dir
; (224 * 32 = 7168 = 14 sectors to read)
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerDSP dw 9 ; Sectors per DSP
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for disk
VolumeID dd 00000000h
VolumeLabel db "SMA-OP "
FileSystem db "DSP "
SMA.Load:
mov ah, 42h
mov si, .SMA.Load.Params
mov dl, bootDev
int 13h
ret
.SMA.Load.Params:
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 0 ; Secntor number (low 32 bits)
dd 2 ; Sector number (high 32 bits)
Boot:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
cmp dl, 0 ; A few early BIOSes are reported to improperly set DL
je NoChange
mov [bootDev], dl ; Save boot device number
mov ah, 8h ; Get drive parameters
int 13h
jc FataldiskError
NoChange:
mov eax, 0
call SMA.Load
jc FataldiskError
mov ax, 0
mov bx, 0
mov cx, 0
mov dx, 0
mov di, 0
mov si, 0
jmp 7c00h
PrintString:
pusha
mov ah, 0Eh
.write:
lodsb
cmp al, 0
je .done
int 10h
jmp short .write
.done:
popa
ret
FataldiskError:
mov si, diskError
call PrintString
Reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h
diskError db "Disk error! Press any key...", 0xA, 0
bootDev db 0 ; Boot device number
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
Buffer: ; Disk Buffer begins (8k after this, stack starts)
?
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 0 ; Secntor number (low 32 bits)
dd 2
bych upravil na
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 2 ; Secntor number (low 32 bits)
dd 0
pokud chceš načíst sektor s číslem 2 (který předcházejí sektory s číslem 0 a 1).


Domiy:17.6.2013 15:28
Už mi pomohl ten kamarád, co mi opravil disk. Sector a Secntor je jako AX a AL.
.SMA.Load.Params:
dw 10h ; structure length
dw 38 ; sector count
dw 7c00h ; buffer address (offset)
dw 0 ; buffer address (segment)
dd 1 ; Secntor number (low 32 bits)
dd 0 ; Sector number (high 32 bits)
Nejde. Kernel je hned za VBR a má 38 sektorů. (disk s VBR 39) Chci načíst
ten kernel. Tak jak? (zoufale)
Díky.
Jakým způsobem to spouštíš? Ono by to asi chtělo si rozchodit nějaké ladící prostředí pro tyto účely (nevím, zda bude stačit zkompilovat Bochs v debug módu).


Domiy:17.6.2013 16:52
Vždyť tu vše je - načtu to do adresy, na kterou pak skočím... Vše je napsané v Assembly - takže kernel překládám do binárního souboru. Když to bylo ve VFATu, vše jelo. Změnil jsem pouze to, že již nehledám hlavní adresář a kernel.
Vždyť tu vše je
Já se jen snažím naznačit, že je někdy dobré si ten kód odkrokovat, aby člověk věděl, co se opravdu děje. Zvláště v těchto případech. A to zastáncem používání debuggermu nejsem.
Napadá mě ještě pár věcí:
- na jaké adrese tvůj bootsektor předpokládá, že poběží? Na 0x7C00?
- Pe takovým způsobem opravdu kompilován (tzn. absolutní adresy jsou překládány na 7Cxxh? Zvláště u SMA.Load.Params)?
- Pokud je tvůj bootsector na adrese 0x7c00 a kernel načítáš také na adresu 0x7c00, nepřepíšeš si tím kód tvého bootsektoru, takže do kernelu nikdy neskočíš (když si třeba disassembluješ MBR, tak ten se hned během prvních několika instrukcí kopíruje (relokuje) z 0x7c00 na 0x600)?
- Není chybně nastavován zásobník (registry SS:SP)? Provádíš to kódem:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti
což znamená, že vrchol zásobníku je na 0x9e0:0x1000 = 0xAE00 (pokud dobře počítám). Přijde mi, že pokud má kernel 38 sektorů a jeho začátek je načten na 0x7c00, tak přepíše všechno až do adresy 0xC800, tedy i tvůj zásobník. Navíc případné pokusy o ukládání na zásobník přepisují kód kernelu.
Programování (zvláště v případech, kdy se těžko ladí) je podle mého názoru hodně o pokoře a o tom, že se snažíš nepředpokládat, že nejaká část tvého kódu je dobře, dokud to opravdu neověříš. Emoce sem nepatří.


Domiy:17.6.2013 17:44
Já jsem sem nepřivedl 7c00h. Ve VFAT verzi mám tu adresu 2000h. Kde píši, že je jaký kus kódu vpořádku? Copak se naopak neustále neptám, zda je to OK? Kde vidíš mé emoce?
I když ti já řeknu, že je to OK, tak to nic neznamená, protože jsem si ten kód nedal do VBR a nespustil. Což dělat nebudu, protože tu nemám připravené ladící prostředí (když jsem psal MBR, tak jsem to zkoušel bez ladění; stálo to více času, ale nakonec se to podařilo).
V poslední verzi tvého kódu jsem objevil ty věci, které jsem psal v minulém příspěvku. Pokud jsi je opravil a stále to nefunguje, je asi čas si to zkusit prokrokovat. Což není legrace, protože nainstalovat nějaké prostředí, ve kterém to půjde, asi nebude snadné.


Domiy:18.6.2013 7:16
Vzal jsem vše potřebné z VFAT a stejně k ničemu...
BITS 16
jmp short Boot
nop
db "SMA-BOOT" ; Disk label
dw 512 ; Bytes per sector
db 1 ; Sectors per Cluster
dw 1 ; Reserved sectors for boot record
db 2 ; Number of copies of the DSP
dw 0 ; Number of root directory entires
dw 39 ; Number of logical sectors
db 0F0h ; Medium descriptor byte
dw 0 ; Sectors per FAT
dw 63 ; Sectors per track
dw 2 ; Number of sides/heads
dd 0 ; Number of hidden sectors
dd 0 ; Number of LBA sectors
dw 0 ; Drive No: 0
db 41 ; Drive signature: 41 for disk
dd 00000000h ; Volume ID
db "SMA-OP " ; Volume label
db "DSP " ; File System
Boot:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
cmp dl, 0 ; A few early BIOSes are reported to improperly set DL
je NoChange
mov ah, 8h ; Get drive parameters
int 13h
jc FataldiskError
NoChange:
mov eax, 0 ; Prepare to enter loop
call SMA.Load
jc FataldiskError
jmp 2000h:0000h
PrintString:
pusha
mov ah, 0Eh
.write:
lodsb
cmp al, 0
je .done
int 10h
jmp short .write
.done:
popa
ret
SMA.Load:
mov ah, 42h
mov si, .SMA.Load.Params
int 13h
ret
.SMA.Load.Params:
dw 10h ; structure length
dw 38 ; sector count
dw Buffer ; buffer address (offset)
dw 2000h ; buffer address (segment)
dd 1 ; Secntor number (low 32 bits)
dd 0 ; Sector number (high 32 bits)
FataldiskError:
mov si, diskError
call PrintString
Reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h
diskError db "Disk error! Press any key...", 0
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
Buffer: ; Disk Buffer begins (8k after this, stack starts)
BITS 16
jmp short Boot
nop
OEMLabel db "SMA-BOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per Cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
NumberOfFATs db 2 ; Number of copies of the FAT
RootDirEntries dw 224 ; Number of entries in root dir
; (224 * 32 = 7168 = 14 sectors to read)
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerFAT dw 9 ; Sectors per FAT
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for disk
VolumeID dd 00000000h ; Volume ID: any number
VolumeLabel db "SMA-OP " ; Volume Label: any 11 chars
FileSystem db "FAT12 " ; File system type: don't change!
Boot:
mov ax, 07C0h ; Set up 4K of stack space above Buffer
add ax, 544 ; 8k Buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
; NOTE: A few early BIOSes are reported to improperly set DL
cmp dl, 0
je NoChange
mov [BootDev], dl ; Save boot device number
mov ah, 8 ; Get drive parameters
int 13h
jc FatalDiskError
and cx, 3Fh ; Maximum sector number
mov [SectorsPerTrack], cx ; Sector numbers start at 1
movzx dx, dh ; Maximum head number
add dx, 1 ; Head numbers start at 0 - add 1 for total
mov [Sides], dx
NoChange:
mov eax, 0 ; Needed for some older BIOSes
; First, we need to load the root directory from the disk. Technical details:
; Start of root = ReservedForBoot + NumberOfFATs * SectorsPerFAT = logical 19
; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14
; Start of user data = (start of root) + (number of root) = logical 33
DiskOK: ; Ready to read first block of data
mov ax, 19 ; Root dir starts at logical sector 19
call l2hts
mov si, Buffer ; Set ES:BX to point to our Buffer (see End of code)
mov bx, ds
mov es, bx
mov bx, si
mov ah, 2 ; Params for int 13h: read disk sectors
mov al, 14 ; And read 14 of them
pusha ; Prepare to enter loop
ReadRootDir:
popa ; In case registers are altered by int 13h
pusha
stc ; A few BIOSes do not set properly on error
int 13h ; Read sectors using BIOS
jnc SearchDir ; If read went OK, skip ahead
call ResetDisk ; Otherwise, reset disk controller and try again
jnc ReadRootDir ; Floppy reset OK?
jmp Reboot ; If not, Fatal double error
SearchDir:
popa
mov ax, ds ; Root dir is now in [Buffer]
mov es, ax ; Set DI to this info
mov di, Buffer
mov cx, word [RootDirEntries] ; Search all (224) entries
mov ax, 0 ; Searching at offset 0
NextRootEntry:
xchg cx, dx ; We use CX in the inner loop...
mov si, KernelFname ; Start searching for kernel filename
mov cx, 11
rep cmpsb
je FoundFileToLoad ; Pointer DI will be at offset 11
add ax, 32 ; Bump searched entries by 1 (32 bytes per entry)
mov di, Buffer ; Point to next entry
add di, ax
xchg dx, cx ; Get the original CX back
loop NextRootEntry
mov si, KernelMiss ; If kernel is not found, bail out
call PrintString
jmp Reboot
FoundFileToLoad: ; Fetch Cluster and load FAT into RAM
mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st Cluster
mov word [Cluster], ax
mov ax, 1 ; Sector 1 = first sector of first FAT
call l2hts
mov di, Buffer ; ES:BX points to our Buffer
mov bx, di
mov ah, 2 ; int 13h params: read (FAT) sectors
mov al, 9 ; All 9 sectors of 1st FAT
pusha ; Prepare to enter loop
ReadFAT:
popa ; In case registers are altered by int 13h
pusha
stc
int 13h ; Read sectors using the BIOS
jnc ReadFAT_OK ; If read went OK, skip ahead
call ResetDisk ; Otherwise, reset disk controller and try again
jnc ReadFAT ; Floppy reset OK?
FatalDiskError:
mov si, DiskError ; If not, print error message and Reboot
call PrintString
jmp Reboot ; Fatal double error
ReadFAT_OK:
popa
mov ax, 2000h ; Segment where we'll load the kernel
mov es, ax
mov bx, 0
mov ah, 2 ; int 13h disk read params
mov al, 1
push ax ; Save in case we (or int calls) lose it
; Now we must load the FAT from the disk. Here's how we find out where it starts:
; FAT Cluster 0 = media descriptor = 0F0h
; FAT Cluster 1 = filler Cluster = 0FFh
; Cluster start = ((Cluster number) - 2) * SectorsPerCluster + (start of user)
; = (Cluster number) + 31
LoadFileSector:
mov ax, word [Cluster] ; Convert sector to logical
add ax, 31
call l2hts ; Make appropriate params for int 13h
mov ax, 2000h
mov es, ax
mov bx, word [Pointer]
pop ax
push ax
stc
int 13h
jnc CalculateNextCluster
call ResetDisk
jmp LoadFileSector
CalculateNextCluster:
mov ax, [Cluster]
mov dx, 0
mov bx, 3
mul bx
mov bx, 2
div bx ; DX = [Cluster] mod 2
mov si, Buffer
add si, ax ; AX = word in FAT for the 12 bit entry
mov ax, word [ds:si]
or dx, dx ; If DX = 0 [Cluster] is Even; if DX = 1 then it's Odd
jz Even ; If [Cluster] is Even, drop last 4 bits of word
; with next Cluster; if Odd, drop first 4 bits
Odd:
shr ax, 4 ; Shift out first 4 bits (they belong to another entry)
jmp short NextClusterCont
Even:
and ax, 0FFFh ; Mask out final 4 bits
NextClusterCont:
mov word [Cluster], ax ; Store Cluster
cmp ax, 0FF8h ; FF8h = End of file marker in FAT12
jae End
add word [Pointer], 512 ; Increase Buffer Pointer 1 sector length
jmp LoadFileSector
End: ; We've got the file to load!
pop ax ; Clean up the stack (AX was pushed earlier)
mov dl, byte [BootDev] ; Provide kernel with boot device info
jmp 2000h:0000h ; Jump to entry point of loaded kernel!
Reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h ; Reboot the system
PrintString:
pusha
mov ah, 0Eh
.write:
lodsb
cmp al, 0
je .done
int 10h
jmp short .write
.done:
popa
ret
ResetDisk:
push ax
push dx
mov ax, 0
mov dl, byte [BootDev]
stc
int 13h
pop dx
pop ax
ret
l2hts: ; Calculate head, track and sector settings for int 13h
; IN: logical sector in AX, OUT: correct registers for int 13h
push bx
push ax
mov bx, ax ; Save logical sector
mov dx, 0 ; First the sector
div word [SectorsPerTrack]
add dl, 01h ; Physical sectors start at 1
mov cl, dl ; Sectors belong in CL for int 13h
mov ax, bx
mov dx, 0 ; Now calculate the head
div word [SectorsPerTrack]
mov dx, 0
div word [Sides]
mov dh, dl ; Head/side
mov ch, al ; Track
pop ax
pop bx
mov dl, byte [BootDev] ; Set correct device
ret
KernelFname db "SMA BIN"
DiskError db "HDD error! Press any key.", 0
KernelMiss db "Kernel file SMA.BIN missing.", 0
BootDev db 0 ; Boot device number
Cluster dw 0 ; Cluster of the file we want to load
Pointer dw 0 ; Pointer into Buffer, for loading kernel
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
Buffer: ; Disk Buffer begins (8k after this, stack starts)
První nejde, druhé ano - kde je rozdíl?
Podle mě načítáš data kernelu na 0x2000:0x0200, ne na 0x2000:0x0000, kam skáčeš.


Domiy:18.6.2013 15:23
Nic. Tedy obě verze způsobí vypsání písmene S do TTY, ale netuším, co
si o tom mám myslet...


Domiy:18.6.2013 15:31
Kernel:
BITS 16
%define InterpreterBAS.Version '6.0'
%define APIVersion 16
; This is the location in RAM for kernel disk operations, 24K
; after the point where the kernel has loaded; it's 8K in size,
; because external programs load after it at the 32K point:
DiskBuffer equ 24576
; The comments show exact locations of instructions in this section,
; and are used in programs/smadev.inc so that an external program can
; use a SMA-OP system call without having to know its exact position
; in the kernel source code...
OsCallVectors:
jmp Main
jmp InterpreterBAS.Run ; 0003h
jmp InterpreterBAS.Pause ; 0006h
jmp InterpreterBAS.FatalError ; 0009h
jmp System.ApiVersion ; 000Ch
jmp Console.WaitForKey ; 000Fh
jmp Console.WriteHline ; 0012h
jmp Console.PrintRegs ; 0015h
jmp Console.NewLine ; 0018h
jmp Console.ReadLine ; 001Bh
jmp Console.NibbleAL ; 001Eh
jmp Console.ReadKey ; 0021h
jmp Console.DigitAX ; 0024h
jmp Console.PrintAL ; 0027h
jmp Console.PrintAX ; 002Ah
jmp Console.Space ; 002Dh
jmp Console.Write ; 0030h
jmp Console.Clear ; 0033h
jmp Cursor.Location ; 0036h
jmp Cursor.Move ; 0039h
jmp Cursor.Show ; 003Ch
jmp Cursor.Hide ; 003Fh
jmp String.Join ; 0042h
jmp String.Strip ; 0045h
jmp String.Time ; 0048h
jmp String.Date ; 004Bh
jmp String.Parse ; 004Eh
jmp String.Copy ; 0051h
jmp String.Dump ; 0054h
jmp String.Upper ; 0057h
jmp String.Lower ; 005Ah
jmp String.Length ; 005Dh
jmp String.Chomp ; 0060h
jmp String.Reverse ; 0063h
jmp String.IndexOf ; 0066h
jmp String.TimeFmt ; 0069h
jmp String.DateFmt ; 006Ch
jmp String.Truncate ; 006Fh
jmp String.Tokenize ; 0072h
jmp String.Compare ; 0075h
jmp String.ReplaceChar ; 0078h
jmp String.SubCompare ; 007Bh
jmp Int.Parse ; 007Eh
jmp Int.ToString ; 0081h
jmp SInt.ToString ; 0084h
jmp LInt.ToString ; 0087h
jmp DialogBox.File ; 008Ah
jmp DialogBox.List ; 008Dh
jmp DialogBox.Plain ; 0090h
jmp DialogBox.Input ; 0093h
jmp DialogBox.DrawBlock ; 0096h
jmp Math.Random ; 0099h
jmp Math.BcdToInt ; 009Ch
jmp Math.LIntNegate ; 009Fh
jmp File.Size ; 00A2h
jmp File.Load ; 00A5h
jmp File.Save ; 00A8h
jmp File.Exists ; 00ABh
jmp File.Create ; 00AEh
jmp File.Remove ; 00B1h
jmp File.Rename ; 00B4h
jmp Disk.FileList ; 00B7h
jmp Port.SendByte ; 00BAh
jmp Port.SpeakerOn ; 00BDh
jmp Port.SpeakerOff ; 00C0h
jmp Port.ReceiveByte ; 00C3h
jmp Port.GetViaSerial ; 00C6h
jmp Port.SendViaSerial ; 00C9h
jmp Port.SerialPort.Enable ; 00CCh
jmp Gshell.DrawBack ; 00CFh
Main:
cli ; Clear interrupts
mov ax, 0
mov ss, ax ; Set stack segment and pointer
mov sp, 0FFFFh
sti ; Restore interrupts
cld ; The default direction for string operations will be 'up' - incrementing address in RAM
mov ax, 2000h ; Set all segments to match where kernel is loaded
mov ds, ax ; After this, we don't need to bother with
mov es, ax ; segments ever again, as SMA-OP and its programs
mov fs, ax ; live entirely in 64K
mov gs, ax
cmp dl, 0
je .NoChange
mov [bootdev], dl ; Save boot device number
push es
mov ah, 8 ; Get drive parameters
int 13h
pop es
and cx, 3Fh ; Maximum sector number
mov [SecsPerTrack], cx ; Sector numbers start at 1
movzx dx, dh ; Maximum head number
add dx, 1 ; Head numbers start at 0 - add 1 for total
mov [Sides], dx
.NoChange:
mov ax, 1003h ; Set text output with certain attributes
mov bx, 0 ; to be bright, and not blinking
int 10h
call Console.Clear
call Iterp
Fmt1224 db 0 ; Non-zero = 24-hr format
FmtDate db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D
; Bit 7 = use name for months
; If bit 7 = 0, second byte = separator character
%include "features/Iterp.asm"
%include "features/System.asm"
%include "features/InterpreterBAS.asm"
%include "features/Gshell.asm"
%include "features/Console.asm"
%include "features/Cursor.asm"
%include "features/DialogBox.asm"
%include "features/Disk.asm"
%include "features/File.asm"
%include "features/Int.asm"
%include "features/Math.asm"
%include "features/Port.asm"
%include "features/String.asm"
Zobrazeno 26 zpráv z 76.