NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: Anonymous on July 21, 2014, 08:27:35 PM
-
I have been following this tutorial in programming your own OS but for now I wanna just focus on the bootloader how it works what tools I need to create one etc.. So Now I have created the first part of the bootloader and I have modified it from the tutorial by adding my own itoa and atoi functions and creating my own version of the print string function here is my code for stage 1 and the link to the tutorial : Link: http://www.brokenthorn.com/Resources Code :
[BITS 16]
[ORG 0x7c00]
jmp Start
Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax
mov sp, 0x9c00
mov es, ax
;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint
xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax
call itoa
.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
.Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
mov ch, 1 ; we are reading the second sector past us, so its still on track 1
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector
jmp 0x1000:0x0 ; jump to execute the sector!
cli;clear interrupts
hlt;halt the system
%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0
;vars
bpbOEM db "My OS "
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xF0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "MOS FLOPPY "
bsFileSystem: DB "FAT12 "
;vars
times 510 - ($-$$) db 0
dw 0xAA55
Stage 2 boot loader :
; Note: Here, we are executed like a normal
; COM program, but we are still in Ring 0.
; We will use this loader to set up 32 bit
; mode and basic exception handling
; This loaded program will be our 32 bit Kernel.
; We do not have the limitation of 512 bytes here,
; so we can add anything we want here!
org 0x0 ; offset to 0, we will set segments later
bits 16 ; we are still in real mode
; we are loaded at linear address 0x10000
jmp main ; jump to main
;*************************************************;
; Second Stage Loader Entry Point
;************************************************;
main:
cli ; clear interrupts
push cs ; Insure DS=CS
pop ds
mov si, Msg
call sPrint
cli ; clear interrupts to prevent triple faults
hlt ; hault the system
;*************************************************;
; Data Section
;************************************************;
%include "itoa_atoi.asm"
Msg db "Preparing to load operating system...",13,10,0
Here is the include file don't know why I didn't put it here in the first place
itoa:;number is passed into ax
jmp .beggining
.negate:
neg ax
push ax
mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor bx , bx
mov cx, 10;mov into cx 10
cmp ax, 0
jl .negate
.top:
;divide by 10 and push remainder onto stack
xor dx, dx;clear out remainder
div cx ;divide ax by 10
push dx;push the remainder onto the stack for later
inc bx;count the number of digits
test ax,ax;if ax = 0 then stop
jne .top
.loop:
pop ax;restore the remainder
add ax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec bx;get ready for the next digit
cmp bx, 0;if not zero then jump to .loop
jne .loop
ret
atoi:
xor ax, ax;clear out ax for the result
mov cx, 10;mov into cx 10
add bx, 80
mov byte[bx], 0;null terminate the number
sub bx, 80
xor dx, dx;clear out dx for use
.top:
mov dl, byte[bx]
cmp dl, 0;if end of string then out
je .done
sub dl, '0';convert to number
push dx;save the number
xor dx, dx
mul cx;multiply by ten
pop dx;restore the number
add ax, dx;add to the result
inc bx;get ready for the next digit
jmp .top
.done:;finished
ret
sPrint:
.loop:
lodsb;move to the next letter in the string
mov ah, 0xe;print it
int 0x10
test al, al;if the register al is not equal to zero then jump back to the top
jne .loop
ret; return back to after where you where called
Where I run into a problem is I have no idea how to run the second stage, Also I am using Virtual box instead of bochs and VFD and I assemble the file as a .img for floppy disks
-
Well... first, your link to BrokenThorn doesn't work because of the semicolon. I could edit that for you, but I'll leave it for you. (that cryptic icon just above "report to moderator" if you haven't figured that out)
What's the problem? You jump to stage2 at the end of stage1 - it should just run. Contrary to the comment in stage2, you only load 1 sector in stage1, so you're limited to 512 bytes. I don't think that's a problem. I don't know why your BPB is in stage2 - shouldn't that be in stage1?
While I do have a real floppy in my current machine, I can't easily test this - no include file. I could probably write my own - I think I see what it needs to do, but not in the mood right now. I have no experience with emulators, so can't help you with that part...
Best,
Frank
-
Sorry about that I changed the icon I thought that icon just ment' question and I am trying to copy the file to the floppy image without overwriting the image in the tutorial it says to do this
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS A:\STAGE2.SYS
The problem with that is that I only have the .img file not a Drive at all and I am not using Bochs or VFD and I wan't to avoid using them unless There is no other way to do so, Instead I do this :
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS Boot.img
And then it asks me if I wan't to overwrite it and I say no because if I do it won't boot it will just try to run at 0x0 and it will give me a fatal error.(I edited the code to have the BPB in Stage 1)
-
I think copying stage2 to "A:stage2.bin" would require a filesystem to load it - that's where the BPB would come in. Your stage1 seems to assume stage2 is in the second sector. I think what I used to do is something like "copy /b stage1.bin + stage2.bin img.bin" and then write "img.bin" to floppy with... "rawrite" or John Fine's "partcopy" or DEBUG will do it, or it's easy to write your own. ASSuming that stage1 is exactly 512 bytes, that should put stage2 in the second sector, where stage1 expects it. Your stage1 loads the second sector to segment 1000 offset 0 and jumps to it. Your "push cs / pop ds" in stage2 should fix up ds so it can find your message. I don't know how all this would work out in an emulator.
Best,
Frank
-
I try to copy both onto the image file but for some reason it only copies one of the files. This is what I have tried.
copy /b Boot.bin + Boot2.bin BootLoader.bin
copy /b BootLoader.bin BootLoader.img
-
Perhaps I misremember. What's the size of the presumed combined file look like? Maybe, with the include file now, I'll give it a shot. Not right this minute...
Best,
Frank
-
Well Boot.asm which is the first stage is 2kb and Stage2.asm is 2kb so 4kb
-
That seems way too big. Oh, wait - size of the binary, not the source.
Best,
Frank
-
1kb each so 2kb
-
If stage1 doesn't assemble to 512 bytes exactly, something is dreadfully wrong! Lemee download your files and see what I can see. After I eat. Maybe before I sleep, but no promises...
Best,
Frank
-
Okay...
[BITS 16]
[ORG 0x7c00]
jmp Start
Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax
mov sp, 0x9c00
mov es, ax
;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint
xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax
call itoa
.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
.Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
; mov ch, 1 ; we are reading the second sector past us, so its still on track 1
mov ch, 0 ; sectors start with 1, tracks start with 0!
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector
jmp 0x1000:0x0 ; jump to execute the sector!
cli;clear interrupts
hlt;halt the system
%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0
;vars
bpbOEM db "My OS "
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xF0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "MOS FLOPPY "
bsFileSystem: DB "FAT12 "
;vars
times 510 - ($-$$) db 0
dw 0xAA55
I think that's your main problem. Confusing that cylinders and heads start with 0 but sectors start with 1!
Initially, I was getting your message (from stage1) and the number three times(!) so I fiddled with your include file, too (wrongly, the first two times!). You were/are checking for zero (end of string) after the interrupt - I'm not sure al will still be zero after the interrupt, so I put the test first (and then forgot to jump back to ".loop"!). That may or may not have been the problem there. I think the main thing was the wrong cylinder/track number.
What I did, for the record, was:
nasm -f bin stage1.asm -o stage1.bin
nasm -f bin stage2.asm -o stage2.bin
cat stage1.bin stage2.bin>img.bin
dd if=img.bin of=/dev/fd0
"copy /b" ought to work the same as "cat". Dunno what you do then to get it to work with VirtualBox instead of a real floppy. I should check out that or some emulator - all that rebootin' gets old quick!
Best,
Frank
-
Well What I tried to do was to cat in Linux in virtual box email it to myself then copying the img.bin to my Boot.img and then try and run but still no luck will keep trying though I know I am close
-
Any help here?
https://forums.virtualbox.org/viewtopic.php?t=1426
Best,
Frank
-
Here's a crazy thought:
; nasm -f bin fakeflop.asm -o fakeflop.img
bits 16 ; just for clarity
incbin "stage1.bin"
incbin "stage2.bin"
times (512 * 2880) - ($ - $$) db 0
Makes a big file - 1474560 - is that right? - that you might be able to persuade VirtualBox is a bootable floppy?
Best,
Frank
-
Wow It worked How does that work exactly It looks like a file with just two includes but it works like copy or cat
-
Yeah, that's about right. "%include" essentially does a "cut and paste" of the included file - right where the "%include" occurs - and Nasm assembles it as if it were all one file. You already use this. If we'd done "%include 'stage1.asm'" and "%include 'stage2.asm'" Nasm would have complained about duplicate symbols. (I didn't even try this - "experience" is the ability to recognize mistakes when you make 'em again). But "incbin" (equivalent to "%incbin" I think) pastes a file in "as is" without any attempt to assemble it. Since I had the two files already assembled, I figured it would work better here. (you can specify a starting point and how much to include, too - doesn't have to be the whole file)
What got me started thinking about it was the references in the VirtualBox forum about using "/dev/zero" to fill a file with zeros. Nasm will do that without "/dev/zero" - we already use it to pad the bootsector out to 510 bytes before the signature. (incidentally, that signature isn't "supposed" to be required for a floppy boot sector - only for a hard drive - but some "buggy" BIOSes look for it, so we have to put it in).
After reading a little more about VirtualBox, I didn't see where we tell it "boot from this". Glad to hear you got it to work!
If, by any chance, you have further problems, feel free to ask!
Best,
Frank
-
I don't know if its better to make another topic for this or not so I will be posting here I have gone through and created the first stage with a FAT32 file system but the thing is when it boots it does nothing except print the welcome message I have the full code right here:
BITS 16
ORG 0x0
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
%DEFINE BLUE 0x03
Start:
jmp main
;BIOS Paramater Block for the File Allocation Table(F.A.T. For short)
OEM_ID db "OS-Z"
BytesPerSector dw 0x0200
SectorsPerCluster db 0x08
ReservedSectors dw 0x0020
TotalFATs db 0x02
MaxRootEntries dw 0x0000
NumberOfSectors dw 0x0000
MediaDescriptor db 0xF8
SectorsPerFAT dw 0x0000
SectorsPerTrack dw 0x003D
SectorsPerHead dw 0x0002
HiddenSectors dd 0x00000000
TotalSectors dd 0x00FE3B1F
BigSectorsPerFAT dd 0x00000778
FSVersion dw 0x0000
RootDirectoryStart dd 0x00000002
FSInfoSector dw 0x0001
BackupBootSector dw 0x0006
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TIMES 13 DB 0 ;jumping to next offset
DriveNumber db 0x00
Signature db 0x29
VolumeID dd 0xFFFFFFFF
VolumeLabel db "OS-Z BIN"
SystemID db "FAT32 "
sPrint: ; Routine: output string in SI to screen
.repeat:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
xor bh, bh ;Must be set to zero
mov bl, BLUE ;The Color
mov cx, 01h ;The counter I guess QQ
lodsb ; Get character from string
test al, al ;If end of string jump to done
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
mov ah, 02h
mov bh, 00h
inc dl ;Cursor Position maybe?????
int 10h ;takes ah and bh and acts on their values
jmp .repeat
.done:
ret
;*************************************************************************
; PROCEDURE ClusterLBA
; convert FAT cluster into LBA addressing scheme
; FileStartSector = ((X ? 2) * SectorsPerCluster(0x08))
;*************************************************************************
Cluster_TO_LBA:
sub ax, 0x02
xor cx, cx
mov cl, BYTE[SectorsPerCluster]; move the Sectors per cluster into cl to multiply by
mul cx;convert to LBA
add ax, WORD[datasector];add the offset to the register ax
ret
;*************************************************************************
; PROCEDURE LBACHS
; convert ?ax? LBA addressing scheme to CHS addressing scheme
; absolute sector = (logical sector / sectors per track) + 1
; absolute head = (logical sector / sectors per track) MOD number of heads
; absolute track = logical sector / (sectors per track * number of heads)
;*************************************************************************
;ax == logical sector
LBA_TO_CHS:
xor cx, cx;clear out cx
xor dx, dx;clear out dx for arithmetic
mov cx, ax;mov the logical sector into cx
Absolute_Sector:
;calculate the absolute sector
div WORD[SectorsPerTrack]
inc ax
mov WORD[absoluteSector], ax
xor ax, ax
mov ax, cx
xor dx, dx
Absolute_Head:
;calculate the absolute Head
div WORD[SectorsPerTrack]
div WORD[SectorsPerHead]
mov WORD[absoluteHead], dx
xor ax, ax
xor bx, bx
xor dx, dx
Absolute_Track:
;calculate the absolute track
mov ax, WORD[SectorsPerTrack]
mov bx, WORD[SectorsPerHead]
mul bx
xor bx, bx
xor dx, dx
mov bx, ax
xor ax, ax
mov ax,cx
div bx
mov WORD[absoluteTrack], ax
ret
Read_Sector:
.MAIN:
mov di, 0x0005 ; five retries for error
.SECTORLOOP:
push ax
push bx
push cx
call LBA_TO_CHS
mov ah, 0x02
mov al, 0x01
mov ch, BYTE[absoluteTrack]; Track = Cylinder
mov cl, BYTE[absoluteSector];load in sector
mov dh, BYTE[absoluteHead]; Load in the head
mov dl, BYTE[DriveNumber];load in the drive number
int 0x13 ; access the bios
jnc .SUCCESS ; check to see if there was an overflow(ERROR)
xor ax, ax ; BIOS reset disk
int 0x13 ; invoke BIOS
dec di ; decrement error counter
pop cx ;resets everything
pop bx
pop ax
jnz .SECTORLOOP ; attempt to read again
int 0x18 ; Do not know what this does
.SUCCESS:
mov si, MSG_Progress
call sPrint
;restore counter and other registers
pop cx
pop bx
pop ax
add bx, WORD [BytesPerSector] ; queue next buffer
inc ax ; queue next sector
test cx, cx
jnz .MAIN; loops through 8 times
ret
main:
;----------------------------------------------------
; code located at 0000:7C00, adjust segment registers
;----------------------------------------------------
cli ; disable interrupts
mov ax, 0x07C0 ; setup registers to point to our segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
;----------------------------------------------------
; create stack
;----------------------------------------------------
mov ax, 0x0000 ; set the stack
mov ss, ax
mov sp, 0xFFFF
sti ; restore interrupts
mov si, MSG
call sPrint
;Calculate The Start of the datasector
mov al, BYTE[TotalFATs];moves the start of the Directory into ax
mul WORD[BigSectorsPerFAT]
add ax, WORD[ReservedSectors]
mov WORD[datasector], ax;Start of datasector into datasector
LOAD_ROOT:
mov ax, WORD[RootDirectoryStart]
call Cluster_TO_LBA
mov bx, Sector_Size
call Read_Sector;Read in the first sector
mov di, Sector_Size + 0x20; adds the offset to the sector size to point the destination index register to the first File
mov dx, WORD [di + 0x001A]; point the dx register to where all the information in that file is stored
mov WORD [cluster], dx ;mov the information into cluster
LOAD_STAGE2:
;Set up the segments where the Second Stage needs to be loaded
mov ax, 0100h ; set ES:BX = 0100:0000
mov es, ax
mov bx, 0
;Read the cluster which contains the Second Stage
mov cx, 0x0008
mov ax, WORD[cluster]
call Cluster_TO_LBA
call Read_Sector
Stage2:;jumps to stage2 of the boot loader
push WORD 0x0100
push WORD 0x0000
retf
Failed:
;An error has occured if this part is executed
mov si, FAILURE
call sPrint
mov ah, 0x00
int 0x16 ; await keypress
int 0x19 ; warm boot computer
MSG: db "Welcome to OS-Z!",0
absoluteSector db 0x00
absoluteHead db 0x00
absoluteTrack db 0x00
cluster dw 0x0000
datasector dw 0x0000
Sector_Size dw 0x0200
MSG_Progress: db ".", 0
FAILURE: db "The Bootloader has Failed to load...........", 0
TIMES 510 - ($-$$) DB 0
DW 0xAA55
Here is the stage 2 bootloader
BITS 16
ORG 0x0100
jmp main
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
%DEFINE BLUE 0x03
sPrint: ; Routine: output string in SI to screen
.repeat:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
xor bh, bh ;Must be set to zero
mov bl, BLUE ;The Color
mov cx, 01h ;The counter I guess QQ
lodsb ; Get character from string
test al, al ;If end of string jump to done
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
mov ah, 02h
mov bh, 00h
inc dl ;Cursor Position maybe?????
int 10h ;takes ah and bh and acts on their values
jmp .repeat
.done:
ret
main:
cli ; clear interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ax, 0x9000 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
sti ; enable interrupts
;-------------------------------;
; Print loading message ;
;-------------------------------;
mov si, LoadingMsg
call sPrint
LoadingMsg: db "Preparing to load Kernel.....", 0
And here is what I use to boot with both of the files
[BITS 16]
incbin "Stage1.bin"
incbin "Stage2.bin"
times (512 * 2880) - ($ - $$) db 0
I think the problem is when I start to load the root directory and read the first sector because its supposed to print the progress message if it does read it though there are no errors , I tried to do this without a tutorial and figure it out on my own and it has really helped me in understanding how to read the sector and converting to LBA and from LBA to CHS and using the segment offset model used in the 16 bit part of the bootloader , that being said there may be a bunch of errors but like you said " "experience" is the ability to recognize mistakes when you make 'em again ". And I have little to no experience with bootloaders but I have been at assembly for about a month now.
-
Wow! Big step! This is going to take some studying, and I'll probably try it. Let me take a quick guess at what "might" be wrong. You seem to be loading your stage2 at segment 0x100 offset 0, and jumping to segment 0x100 offset 0, but your stage2 says "org 0x100". This will (I think) cause stage2 to fail to find its data. Changing that to "org 0" would be an easy thing to try, to see if it helps any...
Best,
Frank
-
I have changed the function LBA_TO_CHS because apparently I was doing it wrong still trying to figure out what I did wrong when converting but any way now that I fixed that (I think) it now gives me an INT18 BOOT FAILURE message after my welcome pops up.
LBA_TO_CHS:
xor dx, dx ; prepare dx:ax for operation
div WORD [SectorsPerTrack] ; calculate
inc dl ; adjust for sector 0
mov BYTE [absoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [SectorsPerHead] ; calculate
mov BYTE [absoluteHead], dl
mov BYTE [absoluteTrack], al
ret
-
Hi Anonymous,
I didn't get far with this before realizing that your numbers for FAT32 obviously aren't going to work for my floppy drive. I'm not sure what it's doing for you, either. I can see you're reading the root directory into memory (where?), but from what? Do you have a FAT32 drive to read from?
Anyway, starting from "main:" (not that ".MAIN:", the other "main:"), 0xFFFF is a horrible alignment for your stack. Zero is a fine number for sp (if you want the whole segment) - it'll wrap around to 0xFFFE on the first push or call. Or start at 0xFFFE if that makes you nervous.
Then you print the message using a different sPrint. The int 10h/9 looks okay, but the int 10h/2 looks like it's setting the cursor to a random dx - starts off at zero (boot drive in dl... might be 80h?) so okay the first time. As I recall, to use int 10h/9, we need to "get cursor" first (int 10h/3?), then inc dl and do the int 10h/2. There's an int 10h/13h that will do colored text and advance the cursor (or not) - unusual parameters, the message goes in es:bp. It looks like you're "guessing" on these BIOS interrupts. Get RBIL (Ralf Brown's Interrupt List). The online versions are okay for interrupts, but if you download the whole thing you get ports.lst and memory.lst (plus other goodies) which will come in handy later. The int 18h loads ROM-BASIC, which isn't likely to be there unless you've got a genuine IBM... and probably not then, these days.
In any case, you return from sPrint with ah non-zero, then load al with [TotalFATs] and multiply by a word. This isn't going to give you a useful value. A little later, you do "mov bx, Sector_Size". This is the address of Sector_Size, not the [contents]. Is that what you intend? It seems to be the buffer into which Read_Sector reads sectors. The very first thing this is going to do is overwrite your "progress dot", so that may be why you don't see them. I get confused after that...
You may need to back up and take smaller steps, although I applaud your trying to figure out the LBA_TO_CHS thing - you'll probably need it eventually.
If I'm feeling ambitious I may try to rework your stage1 and see if I can get it to load stage2 from floppy again. I never worked much with FAT32. As I recall, we know the (maximum) size of the root directory for FAT12 and FAT16, but for FAT32 we don't. This may not be a problem from a bootloader since all the memory is "yours" anyway. My brain is turning to mush. Thunderstorm coming and the lights are beginning to flicker.
Later,
Frank
-
I made changes to the print function so here it is and Now I actually get how to move the cursor around and which registers are the row column and page and I actually started over well not over I am re-using the old code because now that I look back it's a little messy here it is :
BITS 16
ORG 0x00
Start:
jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
;macro for print
%macro Print 2
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov ah, 0x02;moves to a new line in the middle of the screen
mov dh, 0x01
xor bh, bh
mov dl, 22
int 10h
%endmacro
;*************************************;
; ;
; OEM PARAMETER BLOCK ;
; ;
; ;
;*************************************;
BPB_OEM DB "Zeroth OS " ;Name of the OS
BPB_BytesPerSector: DW 512 ;Size of the Sector
BPB_SectorsPerCluster: DB 1
BPB_ReservedSectors: DW 1
BPB_NumberOfFATs: DB 2
BPB_RootEntries: DW 224
BPB_TotalSectors: DW 2880
BPB_Media: DB 0xf0 ;; 0xF1
BPB_SectorsPerFAT: DW 9
BPB_SectorsPerTrack: DW 18
BPB_HeadsPerCylinder: DW 2
BPB_HiddenSectors: DD 0
BPB_TotalSectorsBig: DD 0
BS_DriveNumber: DB 0
BS_Unused: DB 0
BS_ExtBootSignature: DB 0x29
BS_SerialNumber: DD 0xa0a1a2a3
BS_VolumeLabel: DB "Z-OS FLOPPY "
BS_FileSystem: DB "FAT32 "
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 01h ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
ret
main:
cli; disable interrupts
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti ; enable interrupts
call clear
;move the cursor to the middle of the screen
mov ah, 0x02
xor dh, dh
xor bh, bh
mov dl, 22
int 0x10
Print W_MSG, TEAL
LOAD_STAGE2:
W_MSG: db "Welcome to the Zeroth-OS!", 0
Progress_MSG: db ".",0
TIMES 510 - ($-$$) DB 0
DW 0xAA55
EDIT: I know this may be ambitious and maybe your right that I should be taking it slow or one thing at a time but I just realized that if I continue to create this bootloader then make it really complex I would never actually be able to test it on real hardware because ... well I don't have a floppy or anything that uses a floppy. So I wen't around tying to find even some code on how to write boot off of CD and I found some and it is in AT&T syntax T_T, now I have to go translate that, and I think that may change the way I approach the file system am I right?
-
AT&T syntax shouldn't make much difference - looks wildly different, but should do the same thing. I think CDs have bigger sectors - 2k? - but there's a way to boot off CD "as if" it were a floppy. I don't know how to do it. I vaguely recall something about "El Torito spec"? Max mentions something about booting off a USB device to test his "painter" bootsector (in the Examples section). He might give us some clues if we asked him. That would have the advantage that it could be reused. http://www.osdev.org has a lot of info about this kind of thing. If you get advanced enough you could dedicate a hard drive to it...
Haven't tried your latest code yet...
Best,
Frank
-
AT&T code like this, you mean? No idea if it's right. It assembles.
;/* ISO-9660 boot sector
;* --------------------
;*
;* Copyright (c) 2008-2009 Frédéric Feret
;* All rights reserved.
;*
;* Features:
;* - supports ISO-9660 filesystem ("El Torito")
;* - supports multiples burning session
;* - no floppy emulation
;*
;* Limitations:
;* - supports only Joliet format
;*/
BITS 16
ORG 0x00
;/*
; * This is the main function of the boot sector, which loads the OS image
;* into memory at 1000:0000.
;*
;* Parameters:
;* DL = boot disk number.
;*/
;MISMATCH: " .global _start"
;_start:
cli
; /* The BIOS has loaded our boot sector at 0000:7C00. We move the code
; of this boot sector at 9000:0000. */
xor ax,ax
mov ds,ax
mov si,07C00h ; /* DS:SI = 0000:7C00. */
mov ax,09000h
mov es,ax
xor di,di ; /* ES:DI = 9000:0000. */
mov cx,00800h ; /* 2048 bytes. */
rep movsb ; /* do the relocation. */
;/* Jump to the new address. */
;MISMATCH: " ljmp $0x9000, $1f"
jmp 0x9000:here
here:
; /* Setup segment registers. */
mov ax,cs
mov ds,ax ; /* DS = CS = 9000. */
xor ax,ax
mov es,ax
mov ss,ax ;/* SS = ES = 0000. */
mov sp,07C00h ;/* SS:SP = 0000:7C00. */
; /* Save the boot disk number. */
mov [drive_number],dl
; /* Clear the screen. */
mov ax,003h
int 010h
mov si, msg_loading
call print_string
sti
; /* Check if the processor is a 386. */
pushf
pop ax ; /* FLAGS -> AX */
or ax,03000h ; /* try to set IOPL bits. */
push ax
popf ;/* AX -> FLAGS */
pushf
pop ax ;/* FLAGS -> AX */
test ax,03000h ;/* check if IOPL bits are always set */
jnz short .l1 ;/* it's a 386, or a higher model. */
;/* The processor is a 286 or even older model. We display an error message on the
; screen and then prompts the user to press a key on the keyboard to restart
; the computer. */
mov si, msg_no_386
call print_string
jmp reboot
.l1:
;/* Get the size in bytes of a sector from the BIOS. Normally, the size of
; a sector on a CD-ROM is 2048 bytes. */
mov word [disk_packet],01Ah
mov ah,048h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h
jc assume_2k_sector
mov ax, disk_packet + 0x18
mov [bytes_per_sect],ax
jmp .l1
assume_2k_sector:
;/* An error occured while retrieving the size of a sector. We will display
; a warning message on the screen, then we assume that a sector on the
; disk makes 2 kilobytes. */
mov word [bytes_per_sect],00800h
mov si, msg_assume_2k_sector
call print_string
.l1:
;/* To load the OS image (which is located at the root directory of the disk),
; we have to look at all sessions of the disk. We will retrieve information
; on the root directory (its size and location) of each session, load the
;directory into memory and see if the OS image filename is in this directory.
;If the file isn't found, we move on to the next session. If all sessions
;were covered and that the filename wasn't found, we conclude that the OS
;image isn't on the disk. The first volume descriptor is the 17th sector of
;the disk. */
mov eax,16
get_next_desc:
;/* Read the sector in memory at 0000:1000. */
mov [desc_sector],eax
mov bx,01000h
mov cx,1
call read_sectors
;/* Check for the signature "\2CD001" at the beginning of the descriptor. */
mov si, cd_signature
mov di,01000h
mov cx,6
cmpsb
je found_desc
;/* Check if we have looked in all the descriptors of volume. */
cmp byte [es:0x1000],0FFh
jne next_desc
;/* We looked in all sessions of the disk, and the OS image wasn't found.
; We display an error message on the screen and then prompts the user to
; press a key to restart the computer. */
mov si, msg_file_not_found
call print_string
jmp reboot
next_desc:
;/* Compute the next sector number to load. */
mov eax, [desc_sector]
inc eax
jmp get_next_desc
found_desc:
;/* We have to load a volume descriptor of a session in memory. We will check
; if the session supports the Joliet format for storing filenames and
; directories. Otherwise, the session is unknown. */
mov di,01058h
mov si, joliet_signature
mov cx,3
cmpsb
jne next_desc
;/* We found a session that supports Joliet format. We can find the size and
; the location of the root directory. */
mov eax, [es:0x109E]
mov [root_dir_start],eax
mov eax, [es:0x10A6]
mov [root_dir_size],eax
;/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [root_dir_sectors],ax
;/* Read the root directory in memory at 0000:1000. */
mov eax, [root_dir_start]
mov bx,01000h
mov cx, [root_dir_sectors]
call read_sectors
;/* We will look into the root directory the OS image filename. If the file has
; been found, we save the sector number where that file ans its size in bytes.
; Otherwise, we move to the next session. */
mov di,01000h
search_file:
add di,25
;/* Check if this entry refers to a file. */
cmp byte [es:+di],0
jne next_entry
push di
add di,8
mov si, osimage
mov cx,14
cmpsb
pop di
je found_file ; /* file found? */
next_entry:
add di,7
movzx ax,byte [es:+di]
add di,ax
.l1:
inc di
cmp byte [es:+di],0
je 1b
;/* Check if we have check all the entries of the root directory. */
mov eax, [root_dir_size]
add eax,01000h
cmp di,ax
jb search_file
;/* The OS image wasn't found in the root directory. We go to the next
; session of the disk. */
jmp next_desc
found_file:
sub di,25
;/* Get the location of this file. */
mov eax, [es:2+di]
mov [file_start],eax
;/* Get the size of this file. */
mov eax, [es:10+di]
mov [file_size],eax
;/* Compute the number of sectors to load. */
movzx ebx,word [bytes_per_sect]
div ebx
cmp edx,0
je .l1
inc eax
.l1:
mov [file_sectors],ax
;/* Read the OS image in memory at 1000:0000. */
mov eax, [file_start]
mov bx,01000h
mov es,bx
xor bx,bx
mov cx, [file_sectors]
call read_sectors
mov dl, [drive_number]
xor si,si
;/* Run the OS loader... */
jmp 0x1000:0x0000
;/*
; * This function loads one or more sectors in memory.
; *
; * Parmaeters:
; * EAX first sector to load.
; * CX number of sectors to load.
; * ES:BX destination address.
; */
read_sectors:
; /* To request the BIOS to load the sectors, we need to build a data
; packet that contains the number or sectors to load, the first
; logical sector to load and destination address. The address of
; this packet will then be given to the BIOS, which loads these
; sectors into memory. */
mov byte [disk_packet],010h
; /* We don't read one single sector at a time. */
mov [disk_packet + 2], word 0x01
; /* Write the destination address. */
mov [disk_packet + 4], bx
mov [disk_packet + 6], es
;/* Write the logical sector to load. */
mov [disk_packet + 8], eax
mov [disk_packet + 12], dword 0x0
read_one_sector:
;/* Read the sector into memory. */
mov ah,042h
xor al,al
mov si, disk_packet
mov dl, [drive_number]
int 013h
jnc short .l1 ; /* read error? */
mov si, msg_read_error
call print_string
jmp reboot
.l1:
; /* Updates the next sector to load. */
inc dword [disk_packet + 8]
; /* Updates the destination address. Rather than incrementing the offset, we
; will increase the segment. */
mov ax, [bytes_per_sect]
shr ax,4
add [disk_packet + 6], ax
loop read_one_sector
ret
;/*
;* This function displays a string to the screen, at the current cursor
;* position.
;*
;* Parameters:
;* DS:SI null-terminated string.
;*/
print_string:
; /* Read a character. */
repe lodsb
; /* Check if we reached the end of the string. */
cmp al,0
je short .l1
; /* Displays the character on screen. */
mov ah,00Eh
mov bx,007h
int 010h
jmp print_string
.l1:
ret
;/*
; * This function reboots the computer.
; */
reboot:
mov si, msg_reboot
call print_string
; /* Wait for a key. */
xor ax,ax
int 016h
; /* Rebooting... */
int 019h
;/*
; * Messages
; */
msg_loading: db `\n\rLoading...\n\n\r`, 0
msg_no_386: db `Error: 386 or higher processor required.\n\r`, 0
msg_assume_2k_sector: db `Error: failed to get sector size, assume 2 Kb.\n\r`, 0
msg_file_not_found: db `Error: OS image not found.\n\r`, 0
msg_read_error: db `Error: cannot read on disk.\n\r`, 0
msg_reboot: db `Press any key to restart your computer.\n\r`, 0
;/*
; * Datas
; */
cd_signature: db 002h
db 'CD001'
joliet_signature: db 025h,02Fh,045h
osimage: db 0, 'o', 0, 's', 0, 'i', 0, 'm', 0, 'a', 0, 'g', 0, 'e'
drive_number: db 0
bytes_per_sect: dw 0
root_dir_size: dd 0
root_dir_sectors: dw 0
root_dir_start: dd 0
file_size: dd 0
file_sectors: dw 0
file_start: dd 0
desc_sector: dd 0
disk_packet: times 020h db 0
;/*
;* Boot sector signature
;*/
; ORG 2046
times 2046 - ($ - $$) db 0
dw 0AA55h
Best,
Frank
-
Thanks frank It does assemble but when I try to put it into virtual box it says format not recognized and gives me an error message I think its because of what the Developer stated at the top:
Limitations:
;* - supports only Joliet format
I have been studying it and apparently I will have to Put The Descriptors for the Master Boot record into the first sector of the CD_ROM (I think) Each sector is still 512 bytes and the size of an ISO is 2 kilo-bytes or 2,048 bytes. This is as far As I have gotten Not much but I guess I have the structure right so far:
BITS 16
ORG 0x00
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
;macro for print
%macro Print 2
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov ah, 0x02;moves to a new line in the middle of the screen
mov dh, 0x01
xor bh, bh
mov dl, 22
int 10h
%endmacro
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 01h ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
ret
main:
cli; disable interrupts
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti ; enable interrupts
call clear
;move the cursor to the middle of the screen
mov ah, 0x02
xor dh, dh
xor bh, bh
mov dl, 22
int 0x10
Print W_MSG, TEAL;prints the welcome message in teal
INIT_MBR:
cd_signature: db "CD001"
cd_Version: db 0x01
W_MSG: db "Welcome to the Zeroth-OS!", 0
Progress_MSG: db ".",0
times 2048 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55
-
Limitations:
;* - supports only Joliet format
Tell me the trouble
Tell once to my ear
Turn, turn, turn again
Joliet prison
And ninety-nine years
Turn, turn to the rain
And the wind
- Bob Dylan
After "What's a Joliet format, mama?", my next question would have been "How do I write stage1.bin and stage2.bin to CD in the right places?". Will dd do it, if I can figure out "/dev/***", or do I have to make an iso and use "cdrecord"? There are answers to these questions, of course. I'd start looking around osdev.org and follow on from there. In your case, the VirtualBox docs may be more to the point. I thought the idea of a CD bootsector was to get away from VirtualBox. In my case, a USB device is probably what I want to boot from, failing a real floppy.
Once when my buddy was out of town, I grabbed what I thought was a "pen drive" off his desk. I could recognise the device, but couldn't read or write anything to it. Turned out what I had was a "card reader" - I didn't notice the little door on the side. I've never gotten around to trying an actual storage device. That's the extent of my experience with USB devices. I'm a floppy kinda guy. :)
Best,
Frank
-
Well It looks like I am so close to actually jumping to the next stage correctly
here is my Code:
BITS 16
ORG 0x00
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
;macro for print
%macro Print 2
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh;saves the rows for the next time we need to print
%endmacro
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
ret
Read_Extended_Sector:
pusha
xor ax, ax
xor dx, dx
xor bx, bx
;read in the sector
.ForLoop:
MOV DL,BYTE[CDDriveNumber] ; Set it up again
MOV AH,42h ; Read from drive function
MOV SI,DiskAddressPacket ; Load SI with address of the Disk Address Packet
INT 13h
jnc .Success
Print Read_Sector_Error_MSG, PURPLE
cli
hlt
.Success:
Print READ_SUCCESS, TEAL
cmp ah, Stage2
jz .DONE
Print FILE_NOT_FOUND, RED
cli
hlt
.DONE:
popa
ret
main:
cli; disable interrupts
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti ; enable interrupts
call clear
Print W_MSG, TEAL;prints the loading message in colour
call Read_Extended_Sector; Reads the first sector of the drive
;the read in data is stored in AH
cd_signature: db "CD001"
cd_Version: db 0x01
CDDriveNumber: db 80h
;Disk Address Packet
DiskAddressPacket: db 16,0
.SectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.Offset: dw 0 ; Offset :0000
.Segment: dw 0200h ; Segment 0200
.End: dq 16 ; Sector 16 or 10h on CD-ROM
W_MSG: db "Loading Z-Boot...........", 0
Stage2: db "STAGE2 BIN"
Read_Sector_Error_MSG: db "Failed to read sector ......",0
READ_SUCCESS: db "Reading the first sector was a success .......",0
FILE_NOT_FOUND: db "Error, File not found......."
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55
I am still unsure that this will work but I know I am going in the Right direction I started reading the documentation on int 0x13 here is the link :
http://en.wikipedia.org/wiki/INT_13H#INT_13h_AH.3D42h%3a_Extended_Read_Sectors_From_Drive
I now can assemble using mkisofs which copies it to a .iso file which I can probably burn to a disk if I wanted to now all i have to figure out is how to actually read the sector because the carry flag was set after I ran this so it printed the error message
EDIT:
just fixed it I realized that upon setting up the segments I have to save the CD_Drive number and put it correctly into the function here
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti
mov [CDDrivenumber], dl
-
Does "byte value exceeds bounds" ring any bells? It isn't clear to me what you expect to be in ah in Read_Extended_Sector. You compare it with "Stage2" which is the address of a variable containing "STAGE2 BIN", which looks like how the name would be displayed in a (FAT) directory entry... but I think CD directory names are in UTF16. :(
In any case, you pusha/popa around Read_Extended_Sector, so ah is going to be whatever it was going into it - 2 from the print routine would be my guess... It is the carry-flag that will tell you if the interrupt suceeded. If it did, whatever you read from... sector 16(?)... should be at 200h:0. You might want to look for it there before blindly jumping.
I like your version better, though. It doesn't say "all rights reserved"... :)
Best,
Frank
-
I am trying now to find the Volume descriptor and it is proving to be a rial PITA it's supposed to be in the 16th sector but there are only 4 sectors on the CD so I am at a loss
here it is
BITS 16
ORG 0x00
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
;macro for print
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
ret
Read_Sectors:
;/* Read the sector into memory. */
.ForLoop:
mov ah,042h
xor al,al
mov si, DiskAddressPacket
mov dl, [CDDriveNumber]
int 013h
jnc .Success ; /* read error? */
Print Read_Sector_Error_MSG, RED
cli
hlt
.Success:
Print Progress_MSG , PURPLE
inc WORD[DiskAddressPacket.SectorsToRead]
loop .ForLoop
call Print_ln
ret
main:
cli
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti
mov [CDDriveNumber],dl
call clear
Print W_MSG, TEAL;prints the loading message in colour
call Print_ln
LOAD_ROOT:
;first calculate the start of the Root directory
;mov ax, WORD[DiskAddressPacket.End]
mov WORD[DiskAddressPacket.SectorsToRead],16
;xor ax, ax
mov cx, 0x01
call Read_Sectors
Print READ_SUCCESS, TEAL
call Print_ln
Sector_Size: dw 512
CDDriveNumber: db 80h
CD_bytes_per_sect: dw 0
CD_root_dir_size: dd 0
CD_root_dir_sectors: dw 0
CD_root_dir_start: dd 0
CD_file_size: dd 0
CD_file_sectors: dw 0
CD_file_start: dd 0
CD_desc_sector: dd 0
CD_Signature: db "CD001"
CD_FILE_VER: db 0x01
;Disk Address Packet
DiskAddressPacket: db 16,0
.SectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.Offset: dw 0 ; Offset :0000
.Segment: dw 0200h ; Segment 0200
.End: dq 16 ; Sector 16 or 10h on CD-ROM
RETURN: DB 0
W_MSG: db "Loading Z-Boot", 0
Stage2: db "STAGE2 BIN"
Read_Sector_Error_MSG: db "Error, failed to read sector",0
READ_SUCCESS: db "Sectors read correctly",0
Progress_MSG: db ".",0
FILE_NOT_FOUND: db "Error, file not found",0
FOUND: db "Found", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55
Without the volume descriptor I cannot find the root directory which without it I can't really do anything any Ideas?
Also I am trying to register to OS Dev but it won't send me the activation email any idea on how to contact their admins?
-
How would I read in whats at the address of 0x0200:0 to I just use a JMP instruction to jump there and read in whats at ES and SI? I think I am getting it I have put the segment and offset of the DAP into ES:SI and now I am trying to print it to see if its there but no luck nothing printed here is what I tried right under my read sector code
mov es, WORD[DiskAddressPacket.Segment]
mov si, WORD[DiskAddressPacket.Offset]
mov dl, BYTE[ES:SI]
mov ah, 0xE
int 0x010
-
al not dl, but otherwise looks about right.
Best,
Frank
-
Thanks Frank I found the boot signature well I printed it with the code here it is :
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
xor bx, bx
.top
mov al, BYTE[ES:di+bx]
cmp al, ' '
je .Done
mov ah, 0xE
int 0x010
inc bx
jmp .top
.Done:
Now onto finding the root directory Apparently its not in the Volume descriptor so I have to go look for it in memory but yet again no idea how I'm Gonna go keep studying
-
I think I found the root but when I try and print it out I get these weird symbols is it a problem with my cPrint Function or Is it supposed to be like that?
I attached an image to my post to show you what it looks like.
here is the code:
BITS 16
ORG 0x00
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
;macro for print
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
ret
Read_Sectors:
;/* Read the sector into memory. */
.ForLoop:
mov ah,042h
xor al,al
mov si, DiskAddressPacket
mov dl, [CDDriveNumber]
int 013h
jnc .Success ; /* read error? */
Print Read_Sector_Error_MSG, RED
cli
hlt
.Success:
Print Progress_MSG , PURPLE
inc WORD[DiskAddressPacket.SectorsToRead]
loop .ForLoop
call Print_ln
ret
main:
cli
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti
mov [CDDriveNumber],dl
call clear
Print W_MSG, TEAL;prints the loading message in colour
call Print_ln
;First find the Signature of the CD
LOAD_SIGNATURE:
mov cx, 0x04
call Read_Sectors
Print READ_SUCCESS, TEAL
call Print_ln
;load the Volume descriptor to the Volume variable
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
xor bx, bx
.top:
mov al, BYTE[ES:DI+BX]
mov BYTE[VOLUME+BX], al
inc bx
cmp al, ' '
je .Done
jmp .top
.Done:
;see if the Volume descriptor contains the Signature
xor BX, BX
add BX, 0x01
xor cx, cx
.toploop:
xor ax, ax
mov al, BYTE[VOLUME+BX]
cmp al, BYTE[CD_Signature+BX-1]
je .FOUND_IT
jmp .Done2
inc CX
.FOUND_IT:
Print Progress_MSG, PURPLE
inc BX
jmp .toploop
.Done2:
cmp CX, 0
jne FAIL
call Print_ln
Print FOUND_CD, TEAL
jmp LOAD_ROOT
FAIL:
Print FILE_NOT_FOUND, RED
;Now Load the Root Directory from the Volume Descriptor
LOAD_ROOT:
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
call Print_ln
MOV AL,[ES:DI] ; Length of the current directory entry
MOV [CD_dir_curr_size],AL
Print CD_dir_curr_size, TEAL
call Print_ln
MOV EAX,[ES:DI+2] ; Starting sector of directory entry
MOV [CD_root_dir_start],EAX
Print CD_root_dir_start, TEAL
call Print_ln
MOV EAX,[ES:DI+10] ; Size of directory entry on CD/DVD/BD
MOV [CD_root_dir_size],EAX
Print CD_root_dir_size, TEAL
call Print_ln
MOV AL,[ES:DI+32] ; File's name length (see El Torito of ISO:9660 or CDROM.ASM)
MOV [CD_FileNameLength],AL
Print CD_FileNameLength, TEAL
call Print_ln
XOR BX,BX ; Initialize BX
XOR CX,CX ; Initialize CX
MOV SI,DI
Sector_Size: dw 512
CDDriveNumber: db 0x080
CD_bytes_per_sect: dw 0
CD_root_dir_size: dd 0
CD_root_dir_sectors: dw 0
CD_root_dir_start: dd 0
CD_file_size: dd 0
CD_file_sectors: dw 0
CD_file_start: dd 0
CD_desc_sector: dd 0
CD_Signature: db "CD001"
CD_FILE_VER: db 0x01
CD_FileNameLength: db 0x0
CD_dir_curr_size: db 0x0
joliet_signature: db 025h,02Fh,045h
;Disk Address Packet
DiskAddressPacket: db 0x010,0
.SectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.Offset: dw 0 ; Offset :0000
.Segment: dw 0x0200 ; Segment 0200
.End: dq 0x010 ; Sector 16 or 10h on CD-ROM
VOLUME: DB 0
W_MSG: db "Loading Z-Boot", 0
KERNEL: db "KRNL.BIN"
Read_Sector_Error_MSG: db "Error, failed to read sector",0
READ_SUCCESS: db "Sectors read correctly",0
Progress_MSG: db ".",0
FILE_NOT_FOUND: db "Error, file not found",0
FOUND_CD: db "Found the CD Signature", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55; boot signature
-
NeverMind I found out I needed to use the right offsets in order to find the Root
Here is what I did to solve it
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]
xor BX, BX
xor si, si
.top:
MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
je .FAIL
INC BX
jmp .top
.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:
xor ax, ax
MOV AL, BYTE[ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE
INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
call clear
Print File_Found, TEAL
call Print_ln
;call clear
SUB BX, 10
ADD DI, BX
;jump to where the file is located and run it
JMP [ES:DI]
.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
ret
Now I am trying to jump to the file because I found it and run the code there but its not working But at least I found the file :D
here is the stage2 code:
[BITS 16]
[ORG 0x500]
Start: jmp main
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x02 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
MOV BYTE[ROW], DH
MOV BYTE[COL], DL
ret
main:
cli ; clear interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ax, 0x9000 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
sti
;call clear
;set pos
call Print_ln
Print LOAD_SUCCESS, TEAL
call Print_ln
LOAD_SUCCESS: db "Stage 2 of the bootloader has loaded successfully!",0
-
I'll take your word for it that you've found the file...
;jump to where the file is located and run it
JMP [ES:DI]
A near indirect jump to a word found at [es:di]? I doubt it.
Try...
push es
push di
retf
Why is stage2 "org 0x500"? Is that where the file is loaded?
Best,
Frank
-
Here is the updated code for it It still isn't jumping to it correctly:
[BITS 16]
[ORG 0x00]
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
;macro for print
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
itoa:;number is passed into ax
jmp .beggining
.negate:
neg eax
push eax
mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor ebx , ebx
mov ecx, 10;mov into cx 10
cmp eax, 0
jl .negate
.top:
;divide by 10 and push remainder onto stack
xor edx, edx;clear out remainder
div ecx ;divide ax by 10
push edx;push the remainder onto the stack for later
inc ebx;count the number of digits
test eax,eax;if ax = 0 then stop
jne .top
.loop:
pop eax;restore the remainder
add eax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec ebx;get ready for the next digit
cmp ebx, 0;if not zero then jump to .loop
jne .loop
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x01 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
mov BYTE[ROW], DH
mov BYTE[COL],0
ret
Read_Sectors:
;/* Read the sector into memory. */
.ForLoop:
mov ah,042h
xor al,al
mov si, DiskAddressPacket
mov dl, [CDDriveNumber]
int 013h
jnc .Success ; /* read error? */
Print Read_Sector_Error_MSG, RED
cli
hlt
.Success:
Print Progress_MSG , PURPLE
inc WORD[DiskAddressPacket.SectorsToRead]
loop .ForLoop
call Print_ln
ret
CHECK_DESC:
Print CHECK_DESC_MSG, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
xor bx, bx
.top:
mov al, BYTE[ES:DI+BX]
mov BYTE[VOLUME+BX], al
inc bx
cmp al, ' '
je .Done
jmp .top
.Done:
;see if the Volume descriptor contains the Signature
xor BX, BX; clear out bx
add BX, 0x01;move into bx the offset
xor cx, cx;clear out cx
.toploop:
xor ax, ax
mov al, BYTE[VOLUME+BX]
cmp al, BYTE[CD_Signature+BX-1]
je .FOUND_IT; Compare the letters Byte by Byte to see if they are the same
jmp .Done2
inc CX;increments if even one letter is wrong
.FOUND_IT:
Print Progress_MSG, PURPLE
inc BX;Increments the offset
jmp .toploop
.Done2:
cmp CX, 0;if signatures don't match then stop the system and print an error Message
jne .FAIL
call Print_ln
Print FOUND_CD, TEAL
jmp .Done3
.FAIL:
Print FILE_NOT_FOUND, RED
cli
hlt
.Done3:
call Print_ln
ret
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL;prints the loading message
call Print_ln
;the adress is already stored in ES:DI
MOV ES, WORD[DiskAddressPacket.Segment]
MOV DI, WORD[DiskAddressPacket.Offset]
xor BX, BX;initialize bx
xor si, si ;initialize si
.top:
MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
cmp AL,BYTE[STAGE2];compares chars
je .Done;if the same then jump to the next label
cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
je .FAIL
INC BX
jmp .top
.Done:
Print Found_Possible_FILE, TEAL;Prints the possible file found message
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:;compares strings to see if they match
xor ax, ax
MOV AL, BYTE[ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE
INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
call clear
Print File_Found, TEAL
call Print_ln
SUB BX, 10
ADD DI, BX
LEA EAX, [ES:DI];gets the address of the start of the file
call itoa;prints it
call Print_ln
Print Reading_Sectors, TEAL;Print the reading sectors message
;loads the address into the DAP
MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset], DI
;reads the sectors with the new address
;XOR AX, AX
;MOV AX, WORD[DiskAddressPacket.End]
;MOV WORD[DiskAddressPacket.SectorsToRead], 0
mov cx, 0x04
call Read_Sectors
Print READ_SUCCESS, TEAL;Prints that read was a success
call Print_ln
mov dl, [CDDriveNumber];puts the drive number into dl for the next stage to use
;xor si,si
push ES
push DI
retf;jumps to the next stage or tries to jump error here
.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED;print file not found
cli;halt the system
hlt
ret
main:
;first stage of bootloader is loaded at the address 0x07c0:0x0FFFE
;second stage of bootloader is loaded at address 0x9000:0x0FFFF
cli
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax; stack begins at 0x9000-0xffff
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti
mov [CDDriveNumber],dl
;call clear
Print W_MSG, TEAL;prints the loading message in colour
call Print_ln
;First find the Signature of the CD
Print Reading_Sectors, TEAL
LOAD_SIGNATURE:
mov cx, 0x04
call Read_Sectors
Print READ_SUCCESS, TEAL
call Print_ln
;load the Volume descriptor to the Volume variable
call CHECK_DESC
;Now Load the Root Directory from the Volume Descriptor
LOAD_ROOT:
;Print Reading_Sectors, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
XOR BX, BX
MOV BX, 40 ;move in the offset
VolumeLabelLoop:
MOV CL,[ES:DI+BX] ; Grab a letter
CMP CL,' ' ; Is it a space? (Assumes end of string is space, may run out)
JE .VolumeLabelDone ; Yes, we are done
MOV [VOLUME+BX-40],CL
INC BX
JMP VolumeLabelLoop ; Need to compare BX to length of Volume Label on CD (32?)
.VolumeLabelDone:
MOV byte [VOLUME+BX-40],0 ; End the string
MOV EAX,[ES:DI+158] ; LBA of root directory, where all things start.
MOV [DiskAddressPacket.End],EAX ; Load packet with new address on CD of the root directory
xor cx, cx
mov cx, 0x01
Print Reading_Sectors, TEAL
call Read_Sectors ; Call read sector from drive
Print READ_SUCCESS, TEAL;if the program gets here it means it was a success
call Print_ln
LOAD_STAGE2:
call READ_STAGE2
Sector_Size: dw 512
CDDriveNumber: db 0x080
CD_bytes_per_sect: dw 0
CD_root_dir_size: dd 0
CD_root_dir_sectors: dw 0
CD_root_dir_start: dd 0
CD_file_size: dd 0
CD_file_sectors: dw 0
CD_file_start: dd 0
CD_desc_sector: dd 0
CD_Signature: db "CD001"
CD_FILE_VER: db 0x01
CD_FileNameLength: db 0x0
CD_dir_curr_size: db 0x0
joliet_signature: db 025h,02Fh,045h
Reading_Sectors: db "Reading sectors", 0
CHECK_DESC_MSG: db "Checking for CD Signature",0
LOADING_STAGE2_MSG: db "Loading Stage 2 of boot loader",0
STAGE_2_LEN: db 0xA
File_Found: db "File for Stage 2 of the bootloader was successfully loaded!!",0
LOADING_STAGE2_FAILED: db "Failed to load Stage 2 of the boot loader !!!!!",0
Found_Possible_FILE: db "Found Possible File",0
;Disk Address Packet
DiskAddressPacket: db 0x010,0
.SectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.Offset: dw 0 ; Offset :0000
.Segment: dw 0x0200 ; Segment 0200
.End: dq 0x010 ; Sector 16 or 10h on CD-ROM
VOLUME: DB 0
W_MSG: db "Loading Z-Boot", 0
STAGE2: db "STAGE2.BIN"
Read_Sector_Error_MSG: db "Error, failed to read sector",0
READ_SUCCESS: db "Sectors read correctly!",0
Progress_MSG: db ".",0
FILE_NOT_FOUND: db "Error, file not found!",0
FOUND_CD: db "Found the CD Signature!", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55; boot signature
Updated code for Second stage
[BITS 16]
[ORG 0x0100]
Start: jmp main
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
itoa:;number is passed into ax
jmp .beggining
.negate:
neg ax
push ax
mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor bx , bx
mov cx, 10;mov into cx 10
cmp ax, 0
jl .negate
.top:
;divide by 10 and push remainder onto stack
xor dx, dx;clear out remainder
div cx ;divide ax by 10
push dx;push the remainder onto the stack for later
inc bx;count the number of digits
test ax,ax;if ax = 0 then stop
jne .top
.loop:
pop ax;restore the remainder
add ax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec bx;get ready for the next digit
cmp bx, 0;if not zero then jump to .loop
jne .loop
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x01 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
MOV BYTE[ROW], DH
MOV BYTE[COL], DL
ret
main:
;first stage of bootloader is loaded at the address 0x07c0:0x0FFFE
;second stage of bootloader is loaded at address 0x9000:0x0FFFF
cli
mov ax, 0x9000 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFF
sti
call Print_ln
Print LOAD_SUCCESS, TEAL
call Print_ln
LOAD_SUCCESS: db "Stage 2 of the bootloader has loaded successfully!",0
-
Hmmm maybe I haven't found the file because whenever I jump to it it does print some code but its not supposed to be printed here let me attach the png am I going through the root incorrectly ??? It is jumping somewhere because it is executing code it shouldn't be once it makes that jump it should be out of the file. By the way the number not in color is the address at [ES:DI]
-
OK I have changed it to see the real adress where it is reading and it looks like it is way off here is the code for the read stage 2 function:
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL;prints the loading message
call Print_ln
;the adress is already stored in ES:DI
;add DI, 158
xor BX, BX;initialize bx
xor si, si ;initialize si
.top:
MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
cmp AL,BYTE[STAGE2];compares chars
je .Done;if the same then jump to the next label
cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
je .FAIL
INC BX
jmp .top
.Done:
Print Found_Possible_FILE, TEAL;Prints the possible file found message
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:;compares strings to see if they match
xor ax, ax
MOV AL, BYTE[ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE
INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
call clear
Print File_Found, TEAL
call Print_ln
SUB BX, 10
ADD DI, BX
Print Reading_Sectors, TEAL;Print the reading sectors message
;loads the address into the DAP
MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset], DI
;reads the sectors with the new address
xor cx, cx
mov cx, 0x04
call Read_Sectors
Print READ_SUCCESS, TEAL;Prints that read was a success
call Print_ln
mov dl, [CDDriveNumber];puts the drive number into dl for the next stage to use
;xor si,si
;Prints out the segment and offset ES:DI for debugging
mov ax ,es
call itoa;prints it
mov al, BYTE[Colon]
mov ah, 0xe
int 0x010
mov ax ,di;gets the address of the start of the file
call itoa;prints it
call Print_ln
jmp 0x0200:0x0;jumping here
.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED;print file not found
cli;halt the system
hlt
ret
Here is what the output looks like :
-
Judging from the number you print, the sector you read (if success) goes at 0x200:0x1CE. Then you jump to 0x200:0. This looks like it could be a problem.
Best,
Frank
-
So I tried jumping to 0x0200:0x1CE and no change for some reason, I am jumping to that location because that is where the result of the read sectors is stored or at least it should be I might check it again
-
Seems it would make more sense to load it at 0x200:0... or perhaps at 0x200:0x100 since that seems to be your latest (apparently random) "org" in stage2.
Best,
Frank
-
I didn't had a close look at your code but I saw this:
.top:
MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
cmp AL,BYTE[STAGE2];compares chars
je .Done;if the same then jump to the next label
cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
je .FAIL
INC BX
jmp .top
and it looks senseless to me. What are you doing here? Two identical cmp instructions followed by identical jcc instructions to different locations??
btw:
MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
If you hadn't told me that you move something into al .... ;)
-
I tried loading to that too and it still is giving me the same output hmmm Should I give it a new origin? I thought you could give it whatever you want according to the memory map of course and I think thats ok right?
-
Gammac I am comparing the the file name to the string of the file name I wan't to find if it is the same then I have found the file subtract the offset by the length of the file name and add it to DI.
Also I got a different output this time there is no random prints after I print there address but there is nothing after it at all which still means I failed to jump to it I tried jmp [ES:DI] still didn't work Man this is a real conundrum isn't it im gonna keep hacking at it to see what I get.
-
but this branch
je .FAIL
will never happened
-
Almost forgot to post output here it is:
-
Wow I didn't even notice that *face palm* thanks gammac now I realize why its doing this I messed up so bad :P I'm gonna go ahead and fix that
-
Ok here is my code it is printing out what is at ES:DI+BX and it prints out the file that I wan't but it moves on :( I might have missed something here is the code
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]
xor BX, BX
xor si, si
.top:
MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
je .FAIL
INC BX
jmp .top
.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:
xor ax, ax
MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE
INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
Print File_Found, TEAL
call Print_ln
;call clear
SUB BX, 10
ADD DI, BX
;jump to where the file is located and run it
JMP 0x00:0x0200
.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
ret
Here is the output:
-
Now its just going crazy its like its skipping everything and going straight to printing that the file was found but it wasn't
Here is the new code:
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]
xor BX, BX
xor si, si
xor cx, cx
.top3:
add BX, 12
.top:
MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
jne .top3
INC BX
jmp .top
.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:
xor ax, ax
MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE
INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
call Print_ln
Print File_Found, TEAL
call Print_ln
;call clear
SUB BX, 10
ADD DI, BX
;jump to where the file is located and run it
JMP 0x0200:0x00
.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
ret
Here is the output:
-
Here is what the root looks like if you need it at all:
" r8ð " r8ð , r5ð
BOOT.CAT;1 . Î Îr5ð STAGE2.BIN;1 0 r5ð ZEROTHST.BIN;1 ªUUªˆ éƒ `Š6 ´· þƲ ͈6 Æ aô ¹ ¬„ÀtÍ´· þÂÍëêô° Í´ Í´· ¶ ² ÍôB0À¾‡Š–Ís`1À1ÒŠ6 Š 1Û³¾±è®ÿˆ aúô`1À1ÒŠ6 Š 1Û³¾æèÿˆ aÿ‰â±èhÿÃ`1À1ÒŠ6 Š 1Û³¾Ìèjÿˆ aŽ‹>‹1Û&Šˆ‡—C< tëò1ÛƒÃ1É1ÀЇ—:‡°të A`1À1ÒŠ6 Š 1Û³¾æè ÿˆ aCëÒƒù u!èöþ`1À1ÒŠ6 Š 1Û³¾ÿèùþˆ aë`1À1ÒŠ6 Š 1Û³¾èèÛþˆ aúôè·þÃ`1À1ÒŠ6 Š 1Û³¾æè¹þˆ aè—þ1Û1ö&Š´Í&Š<;tCëïúôÃú¸ÀŽØŽèŽà1ÀŽÀŽÐ¼þÿûˆ–è•þ`1À1ÒŠ6 Š 1Û³¾˜ègþˆ aèEþ`1À1ÒŠ6 Š 1Û³¾¼èHþˆ a¹ èiþ`1À1ÒŠ6 Š 1Û³¾Îè&þˆ aèþèšþŽ‹>‹1Û»( &Š €ù tˆoCëñƇo &f‹…ž f£1ɹ `1À1ÒŠ6 Š 1Û³¾¼èÔýˆ aèøý`1À1ÒŠ6 Š 1Û³¾Îèµýˆ aè“ýèÚþ`1À1ÒŠ6 Š 1Û³¾Cè“ýˆ aèqý € CD001 %/EReading sectors Checking for CD Signature Loading Stage 2 of boot loader
File for Stage 2 of the bootloader was successfully loaded!! Failed to load Stage 2 of the boot loader !!!!! Found Possible File
-
I don't know if this is important but it looks like stage 2 comes before zerothstage in the root I don't know if that matters at all just wanted to point that out
-
xor BX, BX
xor si, si
xor cx, cx
.top3:
add BX, 12 ; What happens if bx is incremented elsewhere?
.top:
MOV AL,[ES:DI+BX] ;starting address ; address of a filename in your list of names?
cmp AL,BYTE[STAGE2] ; STAGE2 is the address of given filename?
je .Done
cmp AL,BYTE[STAGE2] ; useless, previous branch do not alter flags
jne .top3 ; test next filename?
INC BX ; ATTENTION: never reached
jmp .top ; never reached
.Done:
; OK, we are here that means the first character matches.
; What are you doing now?
...
please explain your whole filesearching algorithm in pseudocode and try to write well commented code.
XOR SI, SI;Clear out for use
...
xor cx, cx;clear out for use as counter
this types of comments are useless, only the word counter is an information
INT 0x010
what does this interupt?
-
Sorry about the undocumented code I will fix that ASAP as for INT 0x010 that is to write to the video memory to output things on the screen basically a print thats how I know that it passes it file I wan't here is the code:
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
;mov es, [DiskAddressPacket.Segment]
;mov di, [DiskAddressPacket.Offset]
xor BX, BX;clears out bx
xor si, si ;clears out si
xor cx, cx
.top:
MOV AL,BYTE[ES:DI+BX] ;moves a byte of a possible start of a file entry
cmp AL,BYTE[STAGE2];compares it with file I want
je .Done;if it is then jump out of loop
INC BX;get ready for next file entry
jmp .top
.Done:
Print Found_Possible_FILE, TEAL;prints it found a possible file
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:;compares strings to see if they are the same
;xor ax, ax;clears out acx
;prints out a letter to the screen
MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
;;;;;;;;;;;;;;;;;;
xor ax, ax
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
Print Progress_MSG, PURPLE;progress message
INC BX;get ready for next character
INC SI;get ready for next character
INC CX; increment counter
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
call Print_ln
Print File_Found, TEAL;prints found file if found
call Print_ln
Print Reading_Sectors, TEAL;prints reading sector message
;call clear
SUB BX, 10;goes back to the start of the file
ADD DI, BX;adds to the offset
;moves in the new adress ES:DI into the DAP
MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset], DI
xor cx, cx;clears out cx
mov cx, 0x04;puts in cx 0x04 for how many sectors to read
call Read_Sectors;calls the read sectors
Print READ_SUCCESS, TEAL;if it gets here that means it was successful
;jump to where the file is located and run it
;call Print_ln
;Print File_Found, TEAL
JMP [ES:DI] ;jumps to the file
.FAIL:;it failed so print that the file wasn't found and halt the system
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
ret
EDIT: I finally fixed the string compare it wasn't working because the STAGE2_LEN was a defined BYTE instead of a DEFINED WORD :D now I still have the problem of going to the next file. I will post Output to show what it looks like the code above was updated to the new code.
-
Here is the output:
-
sorry Anonymous, your code is an 'eye-pain' and I bet it won't work correct. Searching for two identical letters and then comparing the rest will produce false positives e.g. if you have files named 'oldstage2' and 'stage2'.
-
But I don't have files named oldstage2 because filenames can't be longer than 10 6 for the name 1 for the . and 3 for the extension because it is an El torrito standard ISO that's why I am not checking for files that might have an identical name.
-
I have been using the code for CD bootloader to help me out if this helps anyone see what I am trying to do and yes it is in fasm but it is the only one that I could find that is closest to nasm and booting off of a CD
-
I notice you're back to the near jump. I'm really quite sure that isn't going to do what you want.
LOADSEG equ 0x200 ; ?
LOADOFFS equ 0 ; ?
; some ways to do a far jump
jmp LOADSEG:LOADOFFS
; this needs to be "immediate"
; note that segment comes first in this syntax
; in contrast to the usual little-endian arrangement
; jmp es:bx will not work (more's the pity)
; but you can do...
push es
push bx
retf
; with the same result
; or you could use an indirect jump
; it jumps to the address found at the address you provide
;...
jumptarget dw LOADOFFS, LOADSEG
;...
jmp far [jumptarget]
; if you don't know 'em in advance, you can...
mov [jumptarget], bx
mov [jumptarget + 2], es
jmp far [jumptarget]
; but...
jmp [jumptarget]
; or
jmp [es:bx]
; is going to take just the offset
; and jmp there - in the same segment
Hope that helps...
Best,
Frank
EDIT: Well how does the Fasm file do it? Fine assembler! Why not just use it?
-
I tried everything you said and it is still not going there the fasm file uses some drive geometry but the only thing is that it won't work because my iso will only read 4 sectors anything higher it will freeze because it is not able to ready anything else probably because the files I have on there only occupy 4 sectors
-
Here is the output of this far jump:
mov [jumptarget], ES
mov [jumptarget + 2], DI
jmp far [jumptarget]
The print below the printed segment offset address is not supposed to happen so it is jumping somewhere just maybe not far enough???
-
I have been using the code for CD bootloader to help me out if this helps anyone see what I am trying to do and yes it is in fasm but it is the only one that I could find that is closest to nasm and booting off of a CD
Interesting, thank you for sharing this file. :)
-
mov [jumptarget], ES
mov [jumptarget + 2], DI
jmp far [jumptarget]
Nope. Little-endian.
mov [jumptarget], DI
mov [jumptarget + 2], ES
jmp far [jumptarget]
Best,
Frank
-
Thanks for clarifying still wouldn't work but thanks anyway I will keep at it
-
I tried modifying it by using some of the code that I attached but still no luck am probably gonna switch back to what I was doing before but its attached it you want to see it it is too big to fit in this post also I found this link on the specification of El torito standard here it is : http://bazaar.launchpad.net/~libburnia-team/libisofs/scdbackup/view/head:/doc/boot_sectors.txt , Here as well : http://wiki.osdev.org/El-Torito , I've been reading about a path table which you can use to jump to the address of the file which is probably what I need Ill keep reading up on this hope this helps you guys help me :D
-
Sorry, I can't resist, I have to ask. ;)
Are you sure that your image file is a valid image with functional file system?
-
Well I am sure that the image is bootable and has a file system, am I sure that the little driver I am writing for it is working no I am not thats why am I here.
-
Here I this is my most recent try at this if it helps:
EDIT: Updated to new Code so there is no confusion
[BITS 16]
[ORG 0x0]
Start: jmp main
;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW: db 0
LOADSEG equ 0x200 ; ?
LOADOFFS equ 0 ; ?
jumptarget dw LOADOFFS, LOADSEG
;macro for print
%macro Print 2
pusha
xor ax, ax
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
mov dl, BYTE[COL]
xor bx, bx
mov bl, %2
mov si, %1
call cPrint
mov BYTE[COL], dl
;saves the rows for the next time we need to print
popa
%endmacro
Print_ln:
pusha
mov dh, BYTE[ROW]
mov ah, 0x02 ;set cursor pos
mov bh, 0x00 ;page 00
inc dh ;row 00
mov dl, 0x00 ;col. 00
int 0x10
mov BYTE[ROW], dh
mov BYTE[COL], 0
popa
ret
itoa:;number is passed into ax
jmp .beggining
.negate:
neg ax
push ax
mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor bx , bx
mov cx, 10;mov into cx 10
cmp ax, 0
jl .negate
.top:
;divide by 10 and push remainder onto stack
xor dx, dx;clear out remainder
div cx ;divide ax by 10
push dx;push the remainder onto the stack for later
inc bx;count the number of digits
test ax,ax;if ax = 0 then stop
jne .top
.loop:
pop ax;restore the remainder
add ax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec bx;get ready for the next digit
cmp bx, 0;if not zero then jump to .loop
jne .loop
ret
cPrint: ; Routine: output string in SI to screen
.top:
;Paramaters for Input
mov ah, 09h ; Must be 9 to print color
mov cx, 0x01 ;x position
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
mov ah, 0x02 ;set cursor position
mov bh, 0x00 ;page
inc dl ;column
int 0x10 ;changes the cursor position so the next char can be written at the new location
jmp .top
.done:
ret
;clears the screen and sets the cursor position to the top left
clear:
mov ah, 0x0F ;get current video mode
mov al, 0x00 ;reset register
int 0x10 ;get video mode
mov ah, 0x00 ;set video mode
int 0x10 ;reset screen
mov ah, 0x02 ;set cursor pos
mov bh, 0x01 ;page 00
mov dh, 0x00 ;row 00
mov dl, 0x00 ;col. 00
int 0x10 ;set pos
mov BYTE[ROW], DH
mov BYTE[COL],0
ret
Read_Sectors:
;/* Read the sector into memory. */
.ForLoop:
mov ah,042h
xor al,al
mov si, DiskAddressPacket
mov dl, [CDDriveNumber]
int 013h
jnc .Success ; /* read error? */
Print Read_Sector_Error_MSG, RED
cli
hlt
.Success:
Print Progress_MSG , PURPLE
inc WORD[DiskAddressPacket.SectorsToRead]
loop .ForLoop
call Print_ln
ret
CHECK_DESC:
Print CHECK_DESC_MSG, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
xor bx, bx
.top:
mov al, BYTE[ES:DI+BX]
mov BYTE[VOLUME+BX], al
inc bx
cmp al, ' '
je .Done
jmp .top
.Done:
;see if the Volume descriptor contains the Signature
xor BX, BX; clear out bx
add BX, 0x01;move into bx the offset
xor cx, cx;clear out cx
.toploop:
xor ax, ax
mov al, BYTE[VOLUME+BX]
cmp al, BYTE[CD_Signature+BX-1]
je .FOUND_IT; Compare the letters Byte by Byte to see if they are the same
jmp .Done2
inc CX;increments if even one letter is wrong
.FOUND_IT:
Print Progress_MSG, PURPLE
inc BX;Increments the offset
jmp .toploop
.Done2:
cmp CX, 0;if signatures don't match then stop the system and print an error Message
jne .FAIL
call Print_ln
Print FOUND_CD, TEAL
jmp .Done3
.FAIL:
Print FILE_NOT_FOUND, RED
cli
hlt
.Done3:
call Print_ln
ret
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov di, [DiskAddressPacket.Offset]
mov es, [DiskAddressPacket.Segment]
xor BX, BX;clears out bx
xor si, si ;clears out si
xor cx, cx
.top:
MOV AL,BYTE[ES:DI+BX] ;moves a byte of a possible start of a file entry
cmp AL,BYTE[STAGE2];compares it with file I want
je .Done;if it is then jump out of loop
INC BX;get ready for next file entry
jmp .top
.Done:
Print Found_Possible_FILE, TEAL;prints it found a possible file
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:;compares strings to see if they are the same
;xor ax, ax;clears out acx
;prints out a letter to the screen
MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
;;;;;;;;;;;;;;;;;;
xor ax, ax
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]
je .Success
call Print_ln
jmp .top
.Success:
;Print Progress_MSG, PURPLE;progress message
INC BX;get ready for next character
INC SI;get ready for next character
INC CX; increment counter
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
call Print_ln
Print File_Found, TEAL;prints found file if found
call Print_ln
Print Reading_Sectors, TEAL;prints reading sector message
;call clear
SUB BX, WORD[STAGE_2_LEN];goes back to the start of the file
ADD DI, BX;adds to the offset
;moves in the new address ES:DI into the DAP
;MOV WORD[DiskAddressPacket.Offset], DI
;MOV WORD[DiskAddressPacket.Segment], ES
;MOV EAX, [ES:DI]
;MOV DWORD[DiskAddressPacket.End],EAX
;MOV WORD[DiskAddressPacket.SectorsToRead], 4
;read all sectors
xor cx, cx;clears out cx
mov cx, 0x01;puts in cx 0x04 for how many sectors to read
call Read_Sectors;calls the read sectors
Print READ_SUCCESS, TEAL;if it gets here that means it was successful
;jump to where the file is located and run it
call Print_ln
MOV AX, ES
call itoa
mov AL, ':'
MOV AH, 0xE
INT 0x010
MOV AX, DI
call itoa
call Print_ln
;call clear
mov [jumptarget], WORD 0x000
mov [jumptarget + 2], WORD 0x200
jmp far [jumptarget]
;jmp 000h:0000D800h
;PUSH 0x0200
;PUSH 0x0000
;retf
.FAIL:;it failed so print that the file wasn't found and halt the system
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
ret
main:
;first stage of bootloader is loaded at the address 0x07c0:0x0FFFF
;second stage of bootloader is loaded at address 0x9000:0x0FFFF
cli
mov ax, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax
mov fs, ax
Create_Stack:
xor ax, ax
mov es, ax
mov ss, ax
mov sp ,0x0FFFE
sti
mov [CDDriveNumber],dl
call clear
Print W_MSG, TEAL;prints the loading message in colour
call Print_ln
;First find the Signature of the CD
Print Reading_Sectors, TEAL
LOAD_SIGNATURE:
mov cx, 0x04
call Read_Sectors
Print READ_SUCCESS, TEAL
call Print_ln
;load the Volume descriptor to the Volume variable
call CHECK_DESC
;Now Load the Root Directory from the Volume Descriptor
LOAD_ROOT:
;Print Reading_Sectors, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]
XOR BX, BX
MOV BX, 40 ;move in the offset
VolumeLabelLoop:
MOV CL,[ES:DI+BX] ; Grab a letter
CMP CL,' ' ; Is it a space? (Assumes end of string is space, may run out)
JE .VolumeLabelDone ; Yes, we are done
MOV [VOLUME+BX-40],CL
INC BX
JMP VolumeLabelLoop ; Need to compare BX to length of Volume Label on CD (32?)
.VolumeLabelDone:
Print Reading_Sectors, TEAL
MOV byte [VOLUME+BX-40],0 ; End the string
MOV EAX,[ES:DI+158] ; LBA of root directory, where all things start.
;MOV [DiskAddressPacket.End],EAX ; Load packet with new address on CD of the root directory
MOV DWORD[DiskAddressPacket.End],EAX ; Load packet with new address on CD of the root directory
xor cx, cx
mov cx, 0x01
call Read_Sectors
Print READ_SUCCESS, TEAL;if the program gets here it means it was a success
call Print_ln
LOAD_STAGE2:
call READ_STAGE2
.FAILURE:
Print FILE_NOT_FOUND, RED
cli
hlt
Sector_Size: dw 512
CDDriveNumber: db 0x080
CD_Signature: db "CD001"
CD_FILE_VER: db 0x01
CD_FileNameLength: db 0x0
CD_dir_curr_size: db 0x0
Reading_Sectors: db "Reading sectors", 0
CHECK_DESC_MSG: db "Checking for CD Signature",0
LOADING_STAGE2_MSG: db "Loading Stage 2 of boot loader",0
STAGE_2_LEN: DW 0xA
File_Found: db "File for Stage 2 of the bootloader was found!!",0
LOADING_STAGE2_FAILED: db "Failed to load Stage 2 of the boot loader !!!!!",0
Found_Possible_FILE: db "Found Possible File",0
Colon: db ":",0
FILE_ENTRY: db 0
JolietSig DB 25h, 2fh, 45h ; this is the value of the escape sequence for a Joliet CD
;Disk Address Packet
DiskAddressPacket: db 0x010,0
.SectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.Offset: dw 0 ; Offset :0000
.Segment: dw 0x0200 ; Segment 0200
.End: dq 0x010 ; Sector 16 or 10h on CD-ROM
VOLUME: DW 0
W_MSG: db "Loading Z-Boot", 0
STAGE2: db "STAGE2.BIN"
Read_Sector_Error_MSG: db "Error, failed to read sector",0
READ_SUCCESS: db "Sectors read correctly!",0
Progress_MSG: db ".",0
FILE_NOT_FOUND: db "Error, file not found!",0
FOUND_CD: db "Found the CD Signature!", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55; boot signature
BTW Just noticed this is the longest topic in the history of this forum
-
Anyone else have anything I am stuck I really don't know what to do now :-\
-
Ok So I am now using org 0 because as I have come to find out that's where I would be jumping to if I was jumping to 0x0200:0x000 still no change I also think it might be the way I set up my segments and offsets when creating the stack in both stages in Stage1 of the boot loader the segment:offset address is at 0x07c0:0x0FFFF and the Stage2 address is 0x9000:0x0FFFF Maybe that might be the problem but I have no idea what to change it to.
-
BTW Just noticed this is the longest topic in the history of this forum
Congratulations! You have won a prize - a FREE COPY of Nasm!
Seriously, I haven't even finished reading the version before last. You are fast approaching the point where you need some version control (git or something) or I won't be the only one who's confused about which version is which.
Your stack is poorly aligned (again), but I doubt if that's the problem. Some systems use the upper part of segment 0x9000 for something (I forget what, if I ever knew). That could be a problem, but I doubt it. Your first stage stack is at 0:0xFFFF (according to the code), not 0x7C0:0xFFFF as you state.
This is almost certainly wrong:
LEA EAX, [ES:DI]
MOV DWORD[DiskAddressPacket.End],EAX
"VOLUME" is defined as "db 0", but you appear to be putting multiple bytes in it.
je .FOUND_IT; Compare the letters Byte by Byte to see if they are the same
jmp .Done2
inc CX;increments if even one letter is wrong
.FOUND_IT:
The "inc cx" is never executed.
In no particular order, those are some things I see wrong in your latest(?) version.
As our friend Betov used to say, "Courage!"
Best,
Frank
-
Ya you are right I accidently posted the wrong code I am Because my Read stage 2 function doesen't look like that anymore other than that I changed the volume to a defined word no change I'll work on Version Control and won't post as much code Maybe I'll find the answer this time, Also I updated the code above to the correct version
-
It works now finally after searching and countless nights hacking at my code to figure out what was wrong here is the soulution it is attached if anyone wants to look at the code
-
hi there,
i am experimenting with developing a 64bit os from the ground up. i have 2 asm files: (stage1.asm, stage2.asm). stage 2 will be the 64bit kernel loader (not quite there yet). at the moment stage 2 will simply display the usual welcome text.
stage 1 simply has to find and load stage 2 from fat32. how do i combine the 2 files so that i can run it in bochs.
my development environment is:
win7 pro 64bit
bochs
nasm
thanks for your help,
tony
-
Hi Tony,
I'm not really familiar with Bochs. I was under the impression that it came with its own disk image manipulation program, no?
I assume when you want to load Stage2.bin "from FAT32", you mean as a "named file". I don't think you really need to "combine" the files - more like "fake copy" it to "fake disk". It may be somewhat easier, to get started, to put Stage2 in known sectors (right after Stage1, probably) - but you've gotta deal with file systems eventually...
I'd poke around osdev.org and see if you can find examples of getting started with Bochs
http://wiki.osdev.org/Bochs
Best,
Frank
-
Tried to make an OS using the two stage CD bootloader and it miserably fails whenever the system is trying to read from BIOS,
Used 86Box as an emulator.
Throws up every time with a sector error.
It shows the same message as that anonymous coder with the CD boot.