flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > Bootloader example error Goto page 1, 2 Next |
Author |
|
smiddy 10 Aug 2005, 07:43
Here is how I tackle what their trying to do:
Code: BootSector: ; Label in order to determine size of code for padding. . . . TIMES 510-($-BootSector) DB 0 DW 0AA55h The label BootSector is placed at the begining of the code. The math works out like this: 510 - (current relative location minus BootSector). So that anything less than 510 bytes will be filled with DB 0. Looking at the example you give, I can not acertain what is up. It is using a reserved byte, then using the origin (supposing boot sector of 07C00h) adding 512 then deleting 2 (why not just use 510?) minus the current location. It makes sense that it is 30 some K, since 7C00h is somewhere near that...but it doesn't make any sense in relation to the size of the boot sector code (it's all relative, as that smart guy once said). |
|||
10 Aug 2005, 07:43 |
|
Tomasz Grysztar 10 Aug 2005, 12:50
The "rb 7C00h+512-2-$" is OK, since the boot sector has the origin 7C00h, so $ is 7C00h+current position in sector. If it causes "invalid value" error it means that the value is negative, that is that $ is higher than 7C00h+510, what means that the code is too large to fit in the 512 bytes - you must have altered the source somehow that it does no longer fit in the single sector.
|
|||
10 Aug 2005, 12:50 |
|
shoorick 10 Aug 2005, 13:29
you can continue code beyond this signature, just inside first 512 bytes you will need load these additional sectors.
|
|||
10 Aug 2005, 13:29 |
|
DataHunter2009 10 Aug 2005, 14:07
Okay... um i didn't understand that last post by shoorick, becuase I'm new to this.
And all I did was changed the strings that displayed while the loader was, um... loading. SO I don't see how that could have changed much since iI only added one or two words. ANd I also took out the huge block of comments at the top... which to me, would have made it even smaller... |
|||
10 Aug 2005, 14:07 |
|
smiddy 10 Aug 2005, 14:24
@Tom, I see what you're saying. In my example BootSector is = org = 7C00h, and instead of padding with 0, rb doesn't transform the existing bytes in memory. Why put 512 - 2? Is that to show that the size for the entire boot sector has to be 512 bytes?
@DataHunter2009, if you increased teh number of characters then you have increased the number of bytes the boot loader is, which if it is over 510 bytes, will produce an error. From what I make of shoorick's message, he is saying that you can continue to code in the following sectors, so long as you load those sectors too, for your code. Just remember, the last two bytes of the first sector (the boot sector) has to be 55h and AAh. (equivelent to DW 0AA55h, due to endian-ness). |
|||
10 Aug 2005, 14:24 |
|
DataHunter2009 10 Aug 2005, 15:42
I don't see what could be causing the problem then... I mean, all I did was took out a huge block of comments and added two words to the loading message... Everything else is exactly the same as the example from the site.
Here it is, if you want to have a look: Code: org 7C00h FATSize equ 6144 ;4096*1.5, max entries*entry size RootSize equ 512 ;we'll read one sector (512b) at once start: jmp byte boot_code nop b08_OEM db 'FucKnows' wSecSize dw 'XX' ;always must be a multiplier of 32! ;(actually not used, 512b assumed) bSecsPerCluster db 'X' ;number of sectors per one cluster wResSecs dw 'XX' ;boot and reserved sectors ;also serves as data sector variable bNumFATs db 'X' ;number of FATs wRootEntries dw 'XX' ;number of root entries wTotSecs dw 'XX' ;total sectors bMedia db 'X' ;"media descriptor", hehehe wSecsPerFAT dw 'XX' ;number of sector occupied by one FAT wSecsPerTrack dw 'XX' ;sectors per track, should be < 64! wSidesPerTrack dw 'XX' ;number of sides dHiddenSecs dd 'XXXX' ;used only by DOS instead of MBR data dBigTotSecs dd 'XXXX' ;big total sectors (not used) bDrive db 'X' ;drive number, filled from BIOS db 'X' bExtBootSig db 'X' ;extended boot sector signature dSerNum dd 0BA5EC0DEh ;serial number b11_VolumeLabel db '=cakepiece=' ;volume label, addition to ser.num.? b08_FileSysID db 'FAT12 ' ;completely unused FS signature... boot_code: ;the modified DPT, along with the address of the old one, will be stored here push cs pop ds ;ds=cs (0) mov [bDrive],dl ;save the boot drive number cmp word [413h],(90000h+7C00h+FATSize+RootSize)/1024+1 ;do we have the memory we need? jb byte error ;can't boot if less mov ax,09000h ;set ss to 9000h mov ss,ax ;interrupts disabled for the next op. mov sp,start ;ss:sp=9000:7C00 mov es,ax ;es=9000 mov si,sp ;si=7C00 mov di,sp ;di=7C00 mov ch,01h ;256 to 511 words ; cld ;hopefully not needed... rep movsw ;copy from 0000:7C00 to 9000:7C00 lds si,[1Eh*4] ;ds:si->int 1Eh "handler" mov di,boot_code+4 ;es:di->boot_code+4 mov [cs:di-4],si ;save the address of the old... mov [cs:di-2],ds ;...int 1Eh "handler" mov [cs:1Eh*4],di ;store the offset and... mov [cs:1Eh*4+2],ax ;...segment of new int 1Eh "handler" mov cl,11 ;copy 11 bytes (ch=0 already) rep movsb ;from the old "handler" to the new one mov ds,ax ;ds=9000 now mov byte [di-2],15 ;set head settle time to 15ms ; mov al,byte [wSecsPerTrack] ;al=sectors per track (last sector) ; mov byte [di-7],al ;set last sector on track mov byte [di-7],36 ;set last sector on track <-- hmm, ok? ;should recalibrate after changing DPT? jmp far 9000h:jump_here ;jump to the new code error: mov si,szError ;si->error string call write xor ah,ah ;wait key function number int 16h ;BIOS keyboard interrupt mov si,szCR call write ;restore the address of the old int 1Eh "handler" les bx,[boot_code] ;get the address of the old int 1Eh xor ax,ax ;ax=0 mov ds,ax ;ds=0 mov [1Eh*4],bx ;save offset to interrupt table mov [1Eh*4+2],es ;save segment to interrupt table int 19h ;bootstrap write: mov ah,0Eh ;TTY output function number ; mov bx,0007h ;attribute (weird...) .more: lodsb ;get a byte or al,al jz .done int 10h ;BIOS video interrupt jmp .more ;repeat for the rest .done: retn jump_here: ;read FAT to es:bx (9000:FAT) (es=ds) mov al,[bNumFATs] ;ax=number of FATs mov ah,byte [wSecsPerFAT] ;how many sectors to read, assumed <256 mul ah ;ax=sectors per all FATs push [wResSecs] ;preserve reserved sectors variable add [wResSecs],ax ;fix up the data sector variable ;now it points to the root directory xchg cx,ax ;cx=sectors per all FATs pop ax ;ax=FAT sector number mov bx,FAT ;read to es:bx, which->FAT call read_linear ;read sectors ;read the root directory to es:bx (whatever it is) ; mov ax,[wResSecs] ;root directory sector number, not ;needed: root directory goes right ;after both FATs mov di,[wRootEntries] ;di=number of entries in the root dir. mov cl,4 ;shift four bits right (/16) shr di,cl ;di=di*32/512 (assumed sector size) ;so, di=number of root dir. sectors add [wResSecs],di ;fix up the data sector variable ;now it points to the first cluster read_root: push di ;preserve the counter push es ;preserve es mov cl,1 ;one sector call read_linear ;read sector (ax gets increased) pop es ;restore es mov di,bx ;es:di->RootDir mov cl,512/32 ;16 entries, sector size of 512 assumed ;(32=size of one entry) read_root_nextfile: push cx ;preserve counter mov cl,11 ;file name length mov si,sFileName ;ds:di->OS file name repe cmpsb ;compare je byte found_system ;jump if equal (file found) add di,cx ;increase si by the rest of cx add di,21 ;and fix up by 21 bytes - move to the ;next entry pop cx ;restore counter loop read_root_nextfile ;repeat for next entry pop di ;restore counter dec di ;decrease it jnz byte read_root ;if not zero, repeat for next sector ;didn't find the OS file jmp byte error found_system: ;pop bx ;pop two cx counters ;pop bx mov si,szLoading call write mov di,[es:di+15] ;di=cluster number from directory entry mov ax,160h ;0160 (segment) mov es,ax ;load to 0160:0000 (0000:1600) xor bx,bx ;0000 (offset) next_block: xor cx,cx mov cl,[bSecsPerCluster] ;reset sector count to 1 cluster mov si,di ;si=next should-be cluster for ;contiguous reads next_contiguous: mov ax,3 ;3 mul si ;multiply cluster number by 3 ;dx assumed to be 0, it's a floppy! shr ax,1 ;divide by two xchg bp,ax ;bp=ax mov ax,word [FAT+bp] ;ax=FAT element with junk ;(addressing with bp, since ss=ds) jc byte odd_cluster ;jump if the value was odd even_cluster: and ax,0FFFh ;leave only lower 12 bits jmp got_cluster ;got it odd_cluster: push cx ;preserve sector count mov cl,4 ;shift four bits right shr ax,cl ;(leave only bits 4-15) pop cx ;restore sector count got_cluster: inc si ;si=current cluster+1 ;the following two lines may be omitted, since it would give an error (fatal) ;only if at cluster FF7-FFE there would be FF8-FFF (EOF), then, yes, this will ;think that FAT entry #FF7-FFE points to cluster FF8-FFF (contiguous) and will ;continue the process, which will definitely lead to an error. But since on ;usual floppies there's normally no such cluster numbers... well, we can skip ;this part and the code that follows it will do all we need ; cmp ax,0FF8h ;EOF (FF8-FFF)? ; jae byte force_read ;if yes, force read cmp ax,si ;next cluster=current cluster+1? je byte still_contiguous ;it's still contiguous force_read: xchg di,ax ;ax=di (base cluster), di=new cluster dec ax ;decrease by 2 to get the actual... (1) dec ax ;...cluster number (2) ;currently 1 sector per cluster assumed for floppies xor dx,dx mov dl,[bSecsPerCluster] mul dx ;multiply by sectors per cluster ;(dx ignored) add ax,[wResSecs] ;fix up by data sector variable call read_linear ;read cx sectors at ax to es:bx cmp di,0FF8h ;the new cluster is EOF (FF8-FFF)? jb byte next_block ;if not in this range, read next block ;we got it all! all_read: jmp far 0000h:1600h ;jump to the code we've read still_contiguous: ;prevent overflow of cx... but since the number of sectors on a normal floppy ;can't even get more than 4096, don't care. this is indeed stupid... ;? ; cmp cx,640*1024/512 ;anyway, not more than 640kb at once ; jae byte force_read ;if it's more... (this is stupid) ;? add cl,[bSecsPerCluster] ;increase sector count by 1 cluster adc ch,0 jmp next_contiguous read_linear: ;in: ax=LBA starting sector, cx - number, es:bx->buffer ;!!! The supplied es:bx should not only be paragraph aligned in physical !!! ;!!! memory, but even 512-byte page aligned !!! ;should preserve ax,bx,??? ;destroys: es (increased, points to memory right after the last sector read), ; bp, si... ;read: ; convert x (LBA starting sector) to CHS triple ; count=SecsPerTrack-S+1 ; if count>n (number of sectors to read) then count=n ; calculate the maximum number of sectors that can be read between the ; physical address of es:bx and the next 64kb boundary ; if count>number then count=number ; read count sectors at CHS to es:bx ; sub n,count ; add x,count ; if n<>0 then jmp read read_linear_next: push ax ;preserve LBA sector number push cx ;preserve count ;convert LBA sector number to CHS triple ; cmp dx,[SecsPerTrack] ;prevent overflow ; jnb byte read_linear_fail ;won't overflow on a floppy in normal conditions, and since we don't use dx at ;all, zero it (cwd used since the LBA sector will definitely be below 8000h on ;a floppy... lots of assumptions!): cwd ;dx=0 div [wSecsPerTrack] ;dx=0-based sector (hopefully, < 256 ;and even < 64), ax=quotient inc dx ;make sector 1-based push dx ;preserve it cwd ;dx=0 again div [wSidesPerTrack] ;dx=head, ax=track (should be < 256) pop cx ;restore sector number to cx mov ch,al ;ch=track number (only bits 7-0) mov dh,dl ;dh=head number, cl=sector (bits 5-0) mov dl,[bDrive] ;dl=drive number mov ax,[wSecsPerTrack] ;al=sectors per track, should be < 256 sub al,cl ;al=sectors we can read at once inc ax ;need to do that: sectors are 1-based ;(can_read=SecsPerTrack-S+1) ;may be we can address the saved cx using [ss:imm]? pop si ;restore count to si push si ;and save si back cmp ax,si ;may be even less is left to be read? jna byte read_linear_count_ok ;no, not less xchg si,ax ;yes, less, so ax=si read_linear_count_ok: ;now calculate the maximum number of sectors that can be read between the ;physical address of es:bx and the next 64kb boundary ; -= the following code sucks =- push bx ;begin suck - preserve them all! push cx push ax mov ax,es ;ax=segment and bx=offset to read to mov cl,4 ;shift four bits right, divide by 16 shr bx,cl ;bx=offset/16 add ax,bx ;ax=physical address in paragraphs mov bx,ax ;and bx is the same and bx,0F000h ;mask of lower 12 bits add bh,010h ;increase bits 12-15 ;(so we got the next 64kb boundary) sub bx,ax ;so, bx=number of paragraphs between ;es:bx and the next 64kb boundary inc cx ;cl=5 (for shift, divide by 32) shr bx,cl ;now bx=number of 512b blocks between ;es:bx and the next 64kb boundary pop ax ;restore ax pop cx ;restore cx cmp al,bl ;may be we're trying to read too much? jna byte read_linear_count_really_ok ;no, quite fair amount xchg ax,bx ;yes, so read less (till the next 64kb ;boundary) read_linear_count_really_ok: pop bx ;end suck - restore the last register mov bp,3 ;number of retries read_linear_again: push ax ;save ax; count can be destroyed? RIGHT mov ah,02h ;read sectors int 13h ;BIOS disk interrupt jnc byte read_linear_ok ;cool, no error (really?!! ) xor ah,ah ;recalibrate int 13h ;well, dl already contains drive ;number if somebody needs it :I pop ax ;restore count dec bp ;decrease tries counter jnz byte read_linear_again ;jump if not zero (try again) jmp error ;well, error <-- hmm read_linear_ok: ;-= this code also sucks! =- pop ax ;restore count push ax ;and preserve it again mov cl,5 ;shift five bits left (*32) shl ax,cl ;ax=number of paragraphs we've read ;(number of sectors*512/16=...*32) mov cx,es ;cx=current es add cx,ax ;fix up cx mov es,cx ;and put it back to es pop si ;restore count to si pop cx ;restore the number of sectors to read pop ax ;restore LBA sector number add ax,si ;increase it by the number of sectors ;already read sub cx,si ;decrease it by the number of sectors ;already read jnz byte read_linear_next ;if any more sectors to read, do retn ;bye szLoading db 'Loading Reactor Operating System' szCR db 13,10,0 szError db 'Load error or no code>',0 sFileName db 'BASECODE ' ;mister, what's that? guess yourself rb 7C00h+512-2-$ ;fill up to the boot record signature db 055h,0AAh ;the signature itself ;end of sector - offset 200h (512) FAT rb 3072*2 |
|||
10 Aug 2005, 15:42 |
|
DataHunter2009 10 Aug 2005, 17:00
Sorry for the double post, but I am using a different boot loader now. It's simpler. But the problem is, it reboots when it tried to load the kernel. I'm guessing it can't find it, but I copied it onto the floppy just like I normally do.
Here's the code: Code: use16 start: mov ax, 0x7C00 ; init stack - orig mov ax, 0x07C0 ; init stack mov ss, ax ; mov bp, 0 ; mov sp, 0 ; mov ds, ax ; init ds mov ax, 0x07E0 ; init es mov es, ax ; mov ax, 0x0000 ; init fs mov fs, ax ; mov ah, 0x00 ; init floppy mov dl, 0x01 ; int 0x13 ; jc @f ; if error then reboot mov ah, 0x02 ; load kernel mov al, 10 ; read 5kb mov bx, 0x0000 ; the kernel's targetadress mov cx, 0x0002 ; read cylinder:0 sector:1 mov dx, 0x0000 ; read head:0 drive:0 (A) int 0x13 ; jc @f ; if error then reboot jmp 0x7C00:0x0000 ; run kernel - orig call 0x07E0:0x0000 @@: mov ax, [warmboot] ; reboot mov [fs:0x0472], ax; jmp 0xFFFF:0 ; daten: warmboot dw 0x1234 coldboot dw 0x0000 times 512-($-start)-2 db 0 dw 0xAA55 Any ideas? |
|||
10 Aug 2005, 17:00 |
|
THEWizardGenius 10 Aug 2005, 17:31
As I recall, the output file, without adding
Code: rb 7C00h+512-2-$ ;fill up to the boot record signature db 055h,0AAh ;the signature itself comes out to only a few bytes less than 510 bytes. Your code (not including the boot signature and null-padding) must not exceed 510 bytes. I'm guessing that by adding "Reactor Operating System" you made the file too long. Thus, (7C00h+512-2-$) evaluated to a negative value, which clearly wouldn't work too well. So you have to make it smaller. I would recommend changing the loading message to "Loading ReactorOS" or "Loading ReactOS" or even "Loading ROS". The smaller, the better. You could just make it "Loading", too. Of course, you have to add a NULL at the end (if you wanted you could completely remove szCR and put NULL at the end of the message, but then all subsequent messages would be on the same line, until your kernel changed it). In short, make it smaller and it'll work. BTW, the thread "Bootloader" (started by me) has a bootloader based on the one you are using. It enters protected mode, so if you don't want that it won't be what you need. However, it works fine so you might try that. You do have to modify it a bit (read the last couple posts in the thread). |
|||
10 Aug 2005, 17:31 |
|
smiddy 10 Aug 2005, 17:59
@DataHunter2009, I shortended the variable:
Code: szLoading db 'Loading ROS' and it compiled like a champ. Each character you add to the program adds to the byte count. Room in a the boot sector is precious stuff, eeking out every last bit (pun intended) of memory is a must. |
|||
10 Aug 2005, 17:59 |
|
DataHunter2009 10 Aug 2005, 18:12
Thanks! I changed the string and it compile fine, but now it says "load error or no code>" when it boots. I even changed "BASECODE " to "KERNEL BIN" and it still doesn't work.
|
|||
10 Aug 2005, 18:12 |
|
shoorick 10 Aug 2005, 18:27
i'm not familiar with booting well, but as i know fat should start from 1 track, not directly from the first sector - there empty space on the track 0 i recommended to use before, but i can be wrong - has no docs near.
regards! |
|||
10 Aug 2005, 18:27 |
|
shoorick 11 Aug 2005, 00:15
i was really wrong about floppy - it is possible to shift fat with increasing amount of reseved sectors in bpb
|
|||
11 Aug 2005, 00:15 |
|
DataHunter2009 11 Aug 2005, 00:53
Can someone please explain to me (in plain english) why this bootloader doesn't load my kernel? I don't know much of what you are saying, so I'm not sure i understand it all... hopefully I will once i get this crap working.
|
|||
11 Aug 2005, 00:53 |
|
THEWizardGenius 11 Aug 2005, 01:13
I think you need two spaces between "KERNEL" and "BIN". In FAT, the main filename must be exactly 8 characters, and the extension exactly 3. If you have less you must pad with spaces. KERNEL is 6 characters, so put two spaces to make it 8. BIN is 3 characters, so you do not need to pad with spaces at all. So it should be "KERNEL BIN". Here's the (modified) code:
Code: org 7C00h FATSize equ 6144 ;4096*1.5, max entries*entry size RootSize equ 512 ;we'll read one sector (512b) at once start: jmp byte boot_code nop b08_OEM db 'FucKnows' wSecSize dw 'XX' ;always must be a multiplier of 32! ;(actually not used, 512b assumed) bSecsPerCluster db 'X' ;number of sectors per one cluster wResSecs dw 'XX' ;boot and reserved sectors ;also serves as data sector variable bNumFATs db 'X' ;number of FATs wRootEntries dw 'XX' ;number of root entries wTotSecs dw 'XX' ;total sectors bMedia db 'X' ;"media descriptor", hehehe wSecsPerFAT dw 'XX' ;number of sector occupied by one FAT wSecsPerTrack dw 'XX' ;sectors per track, should be < 64! wSidesPerTrack dw 'XX' ;number of sides dHiddenSecs dd 'XXXX' ;used only by DOS instead of MBR data dBigTotSecs dd 'XXXX' ;big total sectors (not used) bDrive db 'X' ;drive number, filled from BIOS db 'X' bExtBootSig db 'X' ;extended boot sector signature dSerNum dd 0BA5EC0DEh ;serial number b11_VolumeLabel db '=cakepiece=' ;volume label, addition to ser.num.? b08_FileSysID db 'FAT12 ' ;completely unused FS signature... boot_code: ;the modified DPT, along with the address of the old one, will be stored here push cs pop ds ;ds=cs (0) mov [bDrive],dl ;save the boot drive number cmp word [413h],(90000h+7C00h+FATSize+RootSize)/1024+1 ;do we have the memory we need? jb byte error ;can't boot if less mov ax,09000h ;set ss to 9000h mov ss,ax ;interrupts disabled for the next op. mov sp,start ;ss:sp=9000:7C00 mov es,ax ;es=9000 mov si,sp ;si=7C00 mov di,sp ;di=7C00 mov ch,01h ;256 to 511 words ; cld ;hopefully not needed... rep movsw ;copy from 0000:7C00 to 9000:7C00 lds si,[1Eh*4] ;ds:si->int 1Eh "handler" mov di,boot_code+4 ;es:di->boot_code+4 mov [cs:di-4],si ;save the address of the old... mov [cs:di-2],ds ;...int 1Eh "handler" mov [cs:1Eh*4],di ;store the offset and... mov [cs:1Eh*4+2],ax ;...segment of new int 1Eh "handler" mov cl,11 ;copy 11 bytes (ch=0 already) rep movsb ;from the old "handler" to the new one mov ds,ax ;ds=9000 now mov byte [di-2],15 ;set head settle time to 15ms ; mov al,byte [wSecsPerTrack] ;al=sectors per track (last sector) ; mov byte [di-7],al ;set last sector on track mov byte [di-7],36 ;set last sector on track <-- hmm, ok? ;should recalibrate after changing DPT? jmp far 9000h:jump_here ;jump to the new code error: mov si,szError ;si->error string call write xor ah,ah ;wait key function number int 16h ;BIOS keyboard interrupt mov si,szCR call write ;restore the address of the old int 1Eh "handler" les bx,[boot_code] ;get the address of the old int 1Eh xor ax,ax ;ax=0 mov ds,ax ;ds=0 mov [1Eh*4],bx ;save offset to interrupt table mov [1Eh*4+2],es ;save segment to interrupt table int 19h ;bootstrap write: mov ah,0Eh ;TTY output function number ; mov bx,0007h ;attribute (weird...) .more: lodsb ;get a byte or al,al jz .done int 10h ;BIOS video interrupt jmp .more ;repeat for the rest .done: retn jump_here: ;read FAT to es:bx (9000:FAT) (es=ds) mov al,[bNumFATs] ;ax=number of FATs mov ah,byte [wSecsPerFAT] ;how many sectors to read, assumed <256 mul ah ;ax=sectors per all FATs push [wResSecs] ;preserve reserved sectors variable add [wResSecs],ax ;fix up the data sector variable ;now it points to the root directory xchg cx,ax ;cx=sectors per all FATs pop ax ;ax=FAT sector number mov bx,FAT ;read to es:bx, which->FAT call read_linear ;read sectors ;read the root directory to es:bx (whatever it is) ; mov ax,[wResSecs] ;root directory sector number, not ;needed: root directory goes right ;after both FATs mov di,[wRootEntries] ;di=number of entries in the root dir. mov cl,4 ;shift four bits right (/16) shr di,cl ;di=di*32/512 (assumed sector size) ;so, di=number of root dir. sectors add [wResSecs],di ;fix up the data sector variable ;now it points to the first cluster read_root: push di ;preserve the counter push es ;preserve es mov cl,1 ;one sector call read_linear ;read sector (ax gets increased) pop es ;restore es mov di,bx ;es:di->RootDir mov cl,512/32 ;16 entries, sector size of 512 assumed ;(32=size of one entry) read_root_nextfile: push cx ;preserve counter mov cl,11 ;file name length mov si,sFileName ;ds:di->OS file name repe cmpsb ;compare je byte found_system ;jump if equal (file found) add di,cx ;increase si by the rest of cx add di,21 ;and fix up by 21 bytes - move to the ;next entry pop cx ;restore counter loop read_root_nextfile ;repeat for next entry pop di ;restore counter dec di ;decrease it jnz byte read_root ;if not zero, repeat for next sector ;didn't find the OS file jmp byte error found_system: ;pop bx ;pop two cx counters ;pop bx mov si,szLoading call write mov di,[es:di+15] ;di=cluster number from directory entry mov ax,160h ;0160 (segment) mov es,ax ;load to 0160:0000 (0000:1600) xor bx,bx ;0000 (offset) next_block: xor cx,cx mov cl,[bSecsPerCluster] ;reset sector count to 1 cluster mov si,di ;si=next should-be cluster for ;contiguous reads next_contiguous: mov ax,3 ;3 mul si ;multiply cluster number by 3 ;dx assumed to be 0, it's a floppy! shr ax,1 ;divide by two xchg bp,ax ;bp=ax mov ax,word [FAT+bp] ;ax=FAT element with junk ;(addressing with bp, since ss=ds) jc byte odd_cluster ;jump if the value was odd even_cluster: and ax,0FFFh ;leave only lower 12 bits jmp got_cluster ;got it odd_cluster: push cx ;preserve sector count mov cl,4 ;shift four bits right shr ax,cl ;(leave only bits 4-15) pop cx ;restore sector count got_cluster: inc si ;si=current cluster+1 ;the following two lines may be omitted, since it would give an error (fatal) ;only if at cluster FF7-FFE there would be FF8-FFF (EOF), then, yes, this will ;think that FAT entry #FF7-FFE points to cluster FF8-FFF (contiguous) and will ;continue the process, which will definitely lead to an error. But since on ;usual floppies there's normally no such cluster numbers... well, we can skip ;this part and the code that follows it will do all we need ; cmp ax,0FF8h ;EOF (FF8-FFF)? ; jae byte force_read ;if yes, force read cmp ax,si ;next cluster=current cluster+1? je byte still_contiguous ;it's still contiguous force_read: xchg di,ax ;ax=di (base cluster), di=new cluster dec ax ;decrease by 2 to get the actual... (1) dec ax ;...cluster number (2) ;currently 1 sector per cluster assumed for floppies xor dx,dx mov dl,[bSecsPerCluster] mul dx ;multiply by sectors per cluster ;(dx ignored) add ax,[wResSecs] ;fix up by data sector variable call read_linear ;read cx sectors at ax to es:bx cmp di,0FF8h ;the new cluster is EOF (FF8-FFF)? jb byte next_block ;if not in this range, read next block ;we got it all! all_read: jmp far 0000h:1600h ;jump to the code we've read still_contiguous: ;prevent overflow of cx... but since the number of sectors on a normal floppy ;can't even get more than 4096, don't care. this is indeed stupid... ;? ; cmp cx,640*1024/512 ;anyway, not more than 640kb at once ; jae byte force_read ;if it's more... (this is stupid) ;? add cl,[bSecsPerCluster] ;increase sector count by 1 cluster adc ch,0 jmp next_contiguous read_linear: ;in: ax=LBA starting sector, cx - number, es:bx->buffer ;!!! The supplied es:bx should not only be paragraph aligned in physical !!! ;!!! memory, but even 512-byte page aligned !!! ;should preserve ax,bx,??? ;destroys: es (increased, points to memory right after the last sector read), ; bp, si... ;read: ; convert x (LBA starting sector) to CHS triple ; count=SecsPerTrack-S+1 ; if count>n (number of sectors to read) then count=n ; calculate the maximum number of sectors that can be read between the ; physical address of es:bx and the next 64kb boundary ; if count>number then count=number ; read count sectors at CHS to es:bx ; sub n,count ; add x,count ; if n<>0 then jmp read read_linear_next: push ax ;preserve LBA sector number push cx ;preserve count ;convert LBA sector number to CHS triple ; cmp dx,[SecsPerTrack] ;prevent overflow ; jnb byte read_linear_fail ;won't overflow on a floppy in normal conditions, and since we don't use dx at ;all, zero it (cwd used since the LBA sector will definitely be below 8000h on ;a floppy... lots of assumptions!): cwd ;dx=0 div [wSecsPerTrack] ;dx=0-based sector (hopefully, < 256 ;and even < 64), ax=quotient inc dx ;make sector 1-based push dx ;preserve it cwd ;dx=0 again div [wSidesPerTrack] ;dx=head, ax=track (should be < 256) pop cx ;restore sector number to cx mov ch,al ;ch=track number (only bits 7-0) mov dh,dl ;dh=head number, cl=sector (bits 5-0) mov dl,[bDrive] ;dl=drive number mov ax,[wSecsPerTrack] ;al=sectors per track, should be < 256 sub al,cl ;al=sectors we can read at once inc ax ;need to do that: sectors are 1-based ;(can_read=SecsPerTrack-S+1) ;may be we can address the saved cx using [ss:imm]? pop si ;restore count to si push si ;and save si back cmp ax,si ;may be even less is left to be read? jna byte read_linear_count_ok ;no, not less xchg si,ax ;yes, less, so ax=si read_linear_count_ok: ;now calculate the maximum number of sectors that can be read between the ;physical address of es:bx and the next 64kb boundary ; -= the following code sucks =- push bx ;begin suck - preserve them all! push cx push ax mov ax,es ;ax=segment and bx=offset to read to mov cl,4 ;shift four bits right, divide by 16 shr bx,cl ;bx=offset/16 add ax,bx ;ax=physical address in paragraphs mov bx,ax ;and bx is the same and bx,0F000h ;mask of lower 12 bits add bh,010h ;increase bits 12-15 ;(so we got the next 64kb boundary) sub bx,ax ;so, bx=number of paragraphs between ;es:bx and the next 64kb boundary inc cx ;cl=5 (for shift, divide by 32) shr bx,cl ;now bx=number of 512b blocks between ;es:bx and the next 64kb boundary pop ax ;restore ax pop cx ;restore cx cmp al,bl ;may be we're trying to read too much? jna byte read_linear_count_really_ok ;no, quite fair amount xchg ax,bx ;yes, so read less (till the next 64kb ;boundary) read_linear_count_really_ok: pop bx ;end suck - restore the last register mov bp,3 ;number of retries read_linear_again: push ax ;save ax; count can be destroyed? RIGHT mov ah,02h ;read sectors int 13h ;BIOS disk interrupt jnc byte read_linear_ok ;cool, no error (really?!! ) xor ah,ah ;recalibrate int 13h ;well, dl already contains drive ;number if somebody needs it :I pop ax ;restore count dec bp ;decrease tries counter jnz byte read_linear_again ;jump if not zero (try again) jmp error ;well, error <-- hmm read_linear_ok: ;-= this code also sucks! =- pop ax ;restore count push ax ;and preserve it again mov cl,5 ;shift five bits left (*32) shl ax,cl ;ax=number of paragraphs we've read ;(number of sectors*512/16=...*32) mov cx,es ;cx=current es add cx,ax ;fix up cx mov es,cx ;and put it back to es pop si ;restore count to si pop cx ;restore the number of sectors to read pop ax ;restore LBA sector number add ax,si ;increase it by the number of sectors ;already read sub cx,si ;decrease it by the number of sectors ;already read jnz byte read_linear_next ;if any more sectors to read, do retn ;bye szLoading db 'Loading ROS' szCR db 13,10,0 szError db 'Load error or no code>',0 sFileName db 'KERNEL BIN' ;mister, what's that? guess yourself rb 7C00h+512-2-$ ;fill up to the boot record signature db 055h,0AAh ;the signature itself ;end of sector - offset 200h (512) FAT rb 3072*2 Note: I haven't yet tried this, haven't even compiled it, but it should work. You could always try mine if not |
|||
11 Aug 2005, 01:13 |
|
DataHunter2009 11 Aug 2005, 01:19
I already tried that, but thanks for posting . It doidn't work either. Still gave me the load error.
|
|||
11 Aug 2005, 01:19 |
|
THEWizardGenius 11 Aug 2005, 01:22
Odd... you could try my bootloader. It does pmode, which maybe you don't want, but you can try it and if it works remove the pmode code from the bootloader. A test kernel for use with the bootloader:
Code: ;A test kernel for JOS1 format binary use32 org 0x10000 ;Write a "J" on the screen mov word [0xB8000],'JJ' mov word [0xB8002],'aa' mov word [0xB8004],'mm' mov word [0xB8006],'ee' mov word [0xB8008],'ss' mov word [0xB800A],'!!' ;And "hlt", which saves more power than "jmp $" cli hlt ;gdt: dw 0x0000, 0x0000, 0x0000, 0x0000 ;codesel: dw 0xFFFF, 0x0000, 0x9800, 0x00CF ;datasel: dw 0xFFFF, 0x0000, 0x9200, 0x00CF ;gdt_end: ;gdtr: dw gdt_end - gdt - 1 ; dd gdt
_________________ FASM Rules! OS Dev is fun! Pepsi tastes nasty! Some ants toot! It's over! |
|||||||||||
11 Aug 2005, 01:22 |
|
DataHunter2009 11 Aug 2005, 02:00
That doesn't work either. I actually think that Virtual PC is messing everything up. I've tried almost 13 bootloaders and every one of them has locked up or restarted on VPC. I recently caught my testbed computer on fire, so I have to use an emulator to test everything. I think i'll download VMware and try it on that.
|
|||
11 Aug 2005, 02:00 |
|
THEWizardGenius 11 Aug 2005, 16:42
Well in that case why not try a real PC? Maybe it will work...
|
|||
11 Aug 2005, 16:42 |
|
DataHunter2009 11 Aug 2005, 17:42
Like I said already, my testbed machine caught fire, so I can't use it. And my nly other system is way to expensive to test this on.
|
|||
11 Aug 2005, 17:42 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.