flat assembler
Message board for the users of flat assembler.

Index > OS Construction > 2 phase boot code,

Author
Thread Post new topic Reply to topic
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 06 Feb 2006, 14:54
I'm experimenting with FDD boot code, Cool

1 sector isnt a lot of space, 510 bytes maximum (with 55 aa at the end)
and to be safe I'm restricting to 446 bytes as in the
future I will look at HD boot code so I think I need to
avoid trashing the partition descriptors which begin at 446,

now my plan is to create 2 programs boot0 and boot1,
boot0 is less than 446 bytes and is an "org 7c00h" program,
and will be in sector 1,

boot1 will be at most 32K and will be stored at sector 2 onwards,
(initial experiments will probably be just 2K),

now boot0 will use int 13h ah=2 to read 32K from sector 2
(boot1) and then jump to this loaded code Razz

Now because boot0 starts at 7c00h this doesnt leave a lot
of space in the segment, so my plan is to load boot1 to
10000h, ie

org 10000h
.....

so the plan is to copy 64 sectors from sector 2 to 10000h
and then jump there Idea

I think I need to set up the segment registers before doing this,

is the correct thing to do to set cs = ds = ss = 1000h Question

what other registers need setting ? Rolling Eyes

what should I set esp to? Confused

what are the recommended ways to get around the 446 (510?) byte
limit? Shocked
Post 06 Feb 2006, 14:54
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 06 Feb 2006, 18:44
I think your making a lot of work for yourself, why not get "bootprog" from here:
http://alexfru.chat.ru/epm.html#bootprog
This will let you put your "boot1" any where on the floppy and update your "boot1" from win/linux as if it was a normal file, it includes nasm source code for both floppy and hdd loading.
This is the program i use to load my OS "Dex4u".
Post 06 Feb 2006, 18:44
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 06 Feb 2006, 21:20
Dex4u wrote:
I think your making a lot of work for yourself, why not get "bootprog" from here:
http://alexfru.chat.ru/epm.html#bootprog
This will let you put your "boot1" any where on the floppy and update your "boot1" from win/linux as if it was a normal file, it includes nasm source code for both floppy and hdd loading.
This is the program i use to load my OS "Dex4u".


I'll study it,

in the meantime I attempted the following boot0,
it copies the sectors from 2 onwards to 10000h correctly
however the jump to 10000h didnt function,

the boot1 code at 10000h (not presented here) was fine at
7c00h

can anyone see the error with this boot0?


Code:

QUANTITY        equ     32768

        org 7c00h
        
        mov ebx,01000h  
        mov es,bx       ; <<4 = 10000h
        mov ebx,0       ; es:bx = buffer = 1000:0 == 10000h

        mov edx,0
        mov ecx,0
        mov cl,2        ; sector no. starts at 1!
        
        mov eax,QUANTITY
        shr eax,9       ; al = no. sectors
        mov ah,02h      ; read sectors
        
        int 13h
        
        mov ebx,01000h  
        mov ss,bx
        mov [esp_phase0],esp
        mov esp,0fff8h
        mov es,bx

        mov ds,bx

        mov ebx,0

        call far [ds:bx]

        mov ebx,0
        mov ds,bx
        mov ss,bx
        mov esp,[esp_phase0]
        
        
        ret

esp_phase0      dd      0
    



and the version of boot1 I'm using is the following
which just selects 80 x 25 x 2 text and writes a
'Q' to the top left Razz

Code:

        org 10000h

        ; 80 x 25 x 2 text B8000
        mov ax,03h
        int 10h

        mov eax,0B8000h
        shr eax,4
        mov fs,ax

        mov eax,0

        mov byte [fs:eax],'Q'
        add eax,1
        mov byte [fs:eax],0fh

        ret

    


so boot0 is in sector 1, boot1 in sector 2,
boot0 reads boot1 to 10000h and then does "call far [ds:bx]" to
10000h, Q does not appear in the top left of the screen,

Now if I replace "org 10000h" by "org 7c00h" in boot1 and
put boot1 in sector 1 then it does echo Q in the top left
correctly Sad
Post 06 Feb 2006, 21:20
View user's profile Send private message Reply with quote
RedGhost



Joined: 18 May 2005
Posts: 443
Location: BC, Canada
RedGhost 07 Feb 2006, 04:05
you know you can just make your bootloader 2 sectors and rb to fill out 1024 (that's what i originally did for my OS, but then trimmed it to 512)
Post 07 Feb 2006, 04:05
View user's profile Send private message AIM Address MSN Messenger Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 07 Feb 2006, 14:17
RedGhost wrote:
you know you can just make your bootloader 2 sectors and rb to fill out 1024 (that's what i originally did for my OS, but then trimmed it to 512)


excuse my ignorance, but what is "rb"?

BTW I've resolved the problem, I was trying to call an address,
what I should have done was call a pointer to an address:

WRONG CODE:

Code:
=============WRONG:============
        mov ebx,01000h           
        mov ds,bx
        mov ebx,0 
        call far [ds:bx]  ; this isnt calling 010000h 
                               ; but is calling *010000h,
        ...
    


CORRECT CODE:

Code:
=============CORRECT:===========
        mov bx,ds
        mov gs,bx
        mov ecx,boot1
        ....           ; this part changes ds and ebx,
        mov ebx,ecx
        call far [gs:bx]  ; cx isnt allowed for this,
        ....
boot1    dw   0,01000h    ; 01000:0 == 10000h
    


I will improve this further to just:

MUCH BETTER CODE:

Code:
=========== EVEN BETTER boot0 fragment ===
      mov bx,boot1
      call far [ds:bx]
      ....

boot1  dw  0,01000h  ; 01000:0 == 10000h

============ CORRESPONDING boot1 fragment ===

       org 10000h

       push ds
       push es
       mov ebx,1000h
       mov ds,bx
       mov es,bx
       ...
       pop es
       pop ds
       retf   ; retf required to complement call far in boot0
    


in this improved code boot1 sets up its own segment registers
and restores the original values at the end,

this produces cleaner code as you can see Very Happy

trying to set up segment registers in boot0 was complicated.

The whole scheme now is very straightforward, the only complicated
part is the code to copy boot0 and boot1 to the disk,

actually once boot0 is setup copying boot1 to the disk is
just the reverse of the first part of boot0,

so setting up could be done easily as 2 programs write0 and write1
write0 copies boot0 to sector 1 with 55aa at the end and
write1 copies boot1 to sector 2 onwards,

doing it via 1 program is more complicated as you have to
deal with the shell arguments and detect different errors,

although the above looks like subroutines it is more than that
as it is 1 program calling another program like a
subroutine so it is a plugin boot,

I think I will upload the improved boot0 and boot1 later once
I've improved the code enough,

the earlier post asked why dont I use bootprog,

the answer is I want to hit the metal directly without referencing
any OS such as Linux or Windows and also to not reference any
filesystem such as FAT. Just hit the sectors directly.
I accept that bootprog is a more sophisticated path than I am
taking, its just that it is a very maximalist path.

as written the scheme allows bootcode of up to 32K, Cool
I can improve the scheme to allow bootcode of any size Twisted Evil
but the code will become more complicated.
Post 07 Feb 2006, 14:17
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 07 Feb 2006, 14:43
here are the new improved versions,
you assemble both, copy boot0 to sector 1 (LBA 0) with
55aa at the end of the sector,

and copy boot1 to sector 2 (LBA 1)

if you now boot with the floppy disk a Q will appear at the
top left of the screen,

boot0:

Code:

QUANTITY        equ     32768

        org 7c00h
        
        ;========= read QUANTITY bytes from sector 2 (LBA 1) to
                ; 10000h via int 13h ah=02h
        
        mov ebx,01000h  
        mov es,bx       ; <<4 = 10000h
        mov ebx,0       ; es:bx = buffer = 1000:0 == 10000h

        mov edx,0
        mov ecx,0
        mov cl,2        ; sector no. starts at 1!
        
        mov eax,QUANTITY
        shr eax,9       ; al = no. sectors
        mov ah,02h      ; read sectors
        
        int 13h
        
        ;========= far call to above code at 10000h: ===
        
        mov bx,phase1
        call far [ds:bx]        ; [orig_ds:phase1]
        
lab1:   jmp lab1
        
        ret

phase1  dw  0,01000h ; 1000:0 == 10000h

    


and boot1:

Code:

        org 10000h

        push ds
        push es
        push fs
        push eax 
        
               ; the above pushes arent actually necessary!
               ; as the caller doesnt reference any of them 
               ; afterwards

        mov eax,01000h
        mov ds,ax
        mov es,ax
        
        ; 80 x 25 x 2 text B8000
        mov ax,03h
        int 10h
        
        mov eax,0B8000h
        shr eax,4
        mov fs,ax
        
        mov eax,0
        
        mov byte [fs:eax],'Q'
        add eax,1
        mov byte [fs:eax],0fh
        
        pop eax
        pop fs
        pop es
        pop ds
        
        retf

  

    
Post 07 Feb 2006, 14:43
View user's profile Send private message Reply with quote
Mac2004



Joined: 15 Dec 2003
Posts: 314
Mac2004 11 Feb 2006, 14:11
Hi lazer1


'rb' stands for 'reserve byte'. With it you can reserve uninitialized variables. Smile

regards
Mac2004
Post 11 Feb 2006, 14:11
View user's profile Send private message Reply with quote
kake_zinger



Joined: 15 Jul 2004
Posts: 51
kake_zinger 01 Mar 2006, 07:15
There is no need to make separate programs just make 1 loader as big as you want and jmp over the dw aa55h at the end of the boot block (first 512 bytes) to the next part of the loader, which you of course have loaded at its proper place already.

Just use org nnn if you want the 2nd stage be loaded somewhere else than as a continuum to the boot block (at 7e00h) and jmp's and all will be just fine.

Extra bonus to whom can incorporate the 55AA boot signature as part of the boot code eliminating need for any jmp. That disassembles to PUSH BP / STOSB so an enterprising booter could use it for printing a successfull boot string in video memory or something similar. Now we only need a rationalization for doing the push and we'll set for the Perfect Boot Sector with not a byte wasted.
Post 01 Mar 2006, 07:15
View user's profile Send private message Reply with quote
Borsuc



Joined: 29 Dec 2005
Posts: 2465
Location: Bucharest, Romania
Borsuc 01 Mar 2006, 18:28
kake_zinger wrote:
Extra bonus to whom can incorporate the 55AA boot signature as part of the boot code eliminating need for any jmp. That disassembles to PUSH BP / STOSB so an enterprising booter could use it for printing a successfull boot string in video memory or something similar. Now we only need a rationalization for doing the push and we'll set for the Perfect Boot Sector with not a byte wasted.

Nice idea, but sadly, the jmp may be needed (altough not necessary for the signature), because BIOSes, sadly, load the code either at 07C0:0000, or at 0000:7C00, or every other combination...

Note also, that it also depends on the alignment.. i.e: you can as well write a 16-bit instruction like mov right before the signature, and use the signature as a immediate value or something like that.. that's possible because x86 has instructions with opcodes that vary in size between different instructions. Smile
Post 01 Mar 2006, 18:28
View user's profile Send private message Reply with quote
kake_zinger



Joined: 15 Jul 2004
Posts: 51
kake_zinger 02 Mar 2006, 08:17
No need to be sad because despite what cs is loaded with the size of the boot sector will never break a segment limit. You can also load 1 cylinder (2 tracks=18k) from fdd without worrying about this at all.

Besides it's a complete non-issue unless you will be staying in 16bit mode for some strange reason. Otherwise I'd think that a minimum of 32k (ffff-7c00)of 16bit code would be more than enough for anyone.

The idea of 55AA as part of some other op was good, just need to find out if something like that exists while being reasonably useful.
Post 02 Mar 2006, 08:17
View user's profile Send private message Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2139
Location: Estonia
Madis731 02 Mar 2006, 08:25
Code:
mov ax,0AA55h
    

at the $=509 for example Smile
You can also end one instruction with 55h as an immediate or whatever and start the next instruction (stosb) Wink
Post 02 Mar 2006, 08:25
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
tom tobias



Joined: 09 Sep 2003
Posts: 1320
Location: usa
tom tobias 02 Mar 2006, 08:53
Madis731 wrote:
....
at the $=509 for example ....
, or for those of us, unskilled at reading punctuation, and understanding CONCEPTS, the dollar symbol can be replaced with .....?????
Hmm. Isn't this the thread where rb was unknown???
Hmm. Gosh, if someone does not know rb, a mysterious assembler directive, isn't it also possible that someone (else, perhaps) might not fathom the meaning of $=509?????
rb: reserve byte. Does this literally mean, reserve storage for only 8 bits, not 16, not 32? If so, then what are the alternative expressions for reserving storage for more conventional data sizes? What is the advantage of having different directives for different data sizes, rather than a single directive to allocate memory of a size specified by the programmer, or "coder"--for those who prefer to create inscrutable accomplishments.
Smile
Post 02 Mar 2006, 08:53
View user's profile Send private message Reply with quote
kake_zinger



Joined: 15 Jul 2004
Posts: 51
kake_zinger 02 Mar 2006, 09:43
I think he's referring to the IP in decimal notation.

07C0:01FD B855AA MOV AX,0AA55H
07C0:0200 next instr here, 1st byte of next sector (sector 2) from floppy

It's funny how basic counting creates much problems in programming. Floppy cylinders are counted from 0-79 but sectors from 1-18, in bios call. But when actually programming the fdd controller I think sectors are numbered 0-17. Boot sector is 512 bytes but when starting from 0000 the 512th byte is at address 0511 decimal = 01FFh.

Ask an everyman what are the basic numbers of the decimal number system and they'll reply with 1-10. Of course that's not entirely their problem, that's what you get when kids are being taught simplified truths in school which actually are not truths at all. It all starts very early, kids counting in playing games 1-10 when they could do it 9-0 as well (the descending order down to zero for the dramatic "lift-off" effect, you know "...ZERO! I'M COMINGGG!!" when playing hide and seek Smile.
Post 02 Mar 2006, 09:43
View user's profile Send private message Reply with quote
kake_zinger



Joined: 15 Jul 2004
Posts: 51
kake_zinger 04 Mar 2006, 15:00
About the difficulty of correct counting:

Me and two of my friends went to that hotel and were told that there was only one room left and it would cost us $30 for the night. We each paid $10 and went to the room.

Later, the desk clerk realized he had made an error by overcharging us $5. He asked the bell-hop to return the $5 to us. This bell-hop was a bigger prick than the desk clerk and figured that since $5 was not easy to divide among 3 men, he would just return $3 to us - $1 to each. Therefore, each of us paid $9, which totals $27 for the room.

Add that to the $2 the bell-hop kept and the total is only $29!

Where is the missing $1? Who has it?

We beat the hell out of the bell-hop and took all his money so we actually made out fairly well on the deal.
Post 04 Mar 2006, 15:00
View user's profile Send private message Reply with quote
Adam Kachwalla



Joined: 01 Apr 2006
Posts: 150
Adam Kachwalla 02 Apr 2006, 02:34
Quote:
Extra bonus to whom can incorporate the 55AA boot signature as part of the boot code eliminating need for any jmp. That disassembles to PUSH BP / STOSB so an enterprising booter could use it for printing a successfull boot string in video memory or something similar. Now we only need a rationalization for doing the push and we'll set for the Perfect Boot Sector with not a byte wasted.


I really do not see why people whinge about adding "JMP [label]" to their code as if Godzilla or King Kong will JMP out of the computer and smash them to pieces... Can somebody please tell me the problem with adding that line of code?
Post 02 Apr 2006, 02:34
View user's profile Send private message Reply with quote
Borsuc



Joined: 29 Dec 2005
Posts: 2465
Location: Bucharest, Romania
Borsuc 05 Apr 2006, 18:49
Adam Kachwalla wrote:
I really do not see why people whinge about adding "JMP [label]" to their code as if Godzilla or King Kong will JMP out of the computer and smash them to pieces... Can somebody please tell me the problem with adding that line of code?

perfect code Wink
okay, I was joking, nothing is perfect..

jmp takes more space, and time.. even if it's not noticeable, just let's build something more original/perfect. Smile
Post 05 Apr 2006, 18:49
View user's profile Send private message Reply with quote
Adam Kachwalla



Joined: 01 Apr 2006
Posts: 150
Adam Kachwalla 05 Apr 2006, 21:30
I think that the 0x55AA at the end is also unnecessary, but you must have it. It will also make it easier to make the file exactly 512 bytes long. (because RB doesn't work unless there are some significant bytes after that). You can use the DB or DW directive, ot other instructions, to put extra bytes in. So, at the end, you should always have something like:
Code:
RB 510-$
DW 0xAA55    
Post 05 Apr 2006, 21:30
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.