flat assembler
Message board for the users of flat assembler.

Index > OS Construction > multi-stage bootloader on vmware workstation...

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
perhaps for clarity you should place an actual ORG directive at the start of your code. that said, you need to always initialize your segment registers as well as clear the direction flag (or set it) prior to using string instructions.
Post 19 Jun 2012, 06:48
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
CLD = Clear Direction Flag
Post 19 Jun 2012, 06:48
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
I'm not sure whether it's provided for you, but a stack is fundamental.

Code:
xor ax, ax
mov ss, ax
mov sp, 0x7C00;or somewhere else    


it also looks like you need to select the Drive Number. storing it to memory first will help.
Post 19 Jun 2012, 07:10
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
this works in VirtualBox:

Code:
    format binary as 'img.flp'
    use16
    ORG 0x7C00
    jmp 0:$+5
    
    ; boot sector code
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00
    
    movzx dx, dl
    mov[bootdrive], dx
    
    mov si, msg
get_msg:
lodsb
   or al, al

   jz keys_hang
   mov ah, 0Eh

   int 10h
   jmp get_msg

keys_hang:
        xor ax, ax
        mov ah, 0
        ;int 16h
        jz hang_end

hang_end:
    
    xor ax, ax
    mov es, ax
    
    mov dx,[bootdrive]
    mov ah, 02h      ;read disk sectors into memory
    mov al, 1        ;number of sectors to read/write
    mov ch, 0        ;cylinder number
    mov cl, 2        ;sector number
    
    mov bx, next     ;points to the data buffer
    int 13h
    jmp next


msg   db 'Welcome to My_OS BootLoader...', 13, 10
      db 'A newbie style boot loader...', 13, 10
      db ' ', 13, 10, 0
    bootdrive dw 0

   times 510 - ($-$$) db 0

   db 0x55
   db 0xAA
    next:
    
    cld
    xor ax, ax
    mov es, ax
    mov si, stage2msg
    
    
    ld_msg:
      lodsb
      or al, al
      jz inf_lp
      mov ah, 0Eh
      int 10h
      jmp ld_msg
    
    inf_lp:
    
      jmp inf_lp
    
    stage2msg db 'Second Stage following boot sector....', 13, 10, 0
    
    
    times 1024 - ($-$$) db 0    
Post 19 Jun 2012, 07:12
View user's profile Send private message Visit poster's website Reply with quote
newport



Joined: 08 Jun 2012
Posts: 86
Location: Kentucky, USA
newport
Thanks BAiC! I've been away for a little while...just caught back up...so direction flags cleared and segment registers initialized before every string function...and should I set up a stack for every sector I wish to read from?

and thanks for polishing up the code...seems I was a good ways off. Thanks to you I now have a working example I can study for when I get ready to actually start my OS construction. Right now I'm trying to understand how everything is implemented and why it works the way it does. This is a big help! Do you have any suggestions on the best reading material I could get that maybe explains things newbie friendly in relation to fasm? I think the programmers manual is good but would be better with more examples and explanations...

what I think I'm going to do is take the code you posted, cause it works great...is go through and comment on each line and then re-post it and let you see if my comments match up with what the code is actually doing? if you don't mind....does this sound like a good test? that way I'll seem to learn better I think....Thanks again! I really appreciate it!

_________________
It's the desire to learn that leads to success...

http://www.webicomp.com
Post 19 Jun 2012, 10:48
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
Quote:
should I set up a stack for every sector I wish to read from?
no. for the time being you can think of the stack as being owned exclusively by the processor. once it has been setup you can essentially forget it.

eventually, if you want threads/tasks/processes, you'll need to give each of them their own stack but until then don't worry about it.

Quote:
Do you have any suggestions on the best reading material I could get that maybe explains things newbie friendly in relation to fasm?
sorry, but the vast majority of how I learned was by testing on both VMs and real hardware. it's good that your using VMware; it is a very accurate representation of what (my) real hardware does.

Quote:
what I think I'm going to do is take the code you posted, cause it works great...is go through and comment on each line and then re-post it and let you see if my comments match up with what the code is actually doing? if you don't mind....does this sound like a good test? that way I'll seem to learn better I think
sounds good. I'll go over it when you're done.

Stefan
Post 19 Jun 2012, 13:06
View user's profile Send private message Visit poster's website Reply with quote
newport



Joined: 08 Jun 2012
Posts: 86
Location: Kentucky, USA
newport
Thanks!

_________________
It's the desire to learn that leads to success...

http://www.webicomp.com
Post 19 Jun 2012, 13:42
View user's profile Send private message Visit poster's website Reply with quote
newport



Joined: 08 Jun 2012
Posts: 86
Location: Kentucky, USA
newport
OK BAiC...

Here's the code with my comments. My questions concerning my comments made to the code are in RED. And also, I modified the code slightly at the end because I wanted to see if I could write a functional macros to print a string,... but other than that it's the same. Thanks for taking the time to review this! I really appreciate yours and everyone else's help that I have received through these forums. Look forward to hearing from ya!


Code:
;;;;;;;;;;BEGIN BOOTABLE SECTOR...AS DEFINED BY BIOS THE ORIGIN(start point);;;;;;;;;;
;;;;;;;;;;IS REQUIRED TO BE [0x7C00] AND THE END OF THE BOOT SECTOR IS......;;;;;;;;;;
;;;;;;;;;;DEFINED BY [dw 0xAA55] OR [db 0x55 and db 0xAA]...................;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    format binary as 'img.flp'          ;set binary output for use with vmware.
    use16                               ;instuct compiler to generate 16-bit code.
    ORG 0x7C00                          ;memory address bios assigns boot sector to.
    jmp 0:$+5                           ;jump to value of current offset + 5 --- 0:$+5.    

;;;;;;;;;;Why current location +5?
;;;;;;;;;;+5 is the only one that seems to work...not +2 or +3 or +10, etc...???.
Code:
    
    ; boot sector code
    xor ax, ax                          ;zeros out or clears ax register
    mov ds, ax                          ;reset or set data segments' address to ax(0)
    mov es, ax                          ;reset or set extra segments' address to ax(0)
    mov ss, ax                          ;reset or set stack segments' address to ax(0)
    mov sp, 0x7C00                      ;set stack point to memory address 7C00
    

;;;;;;;;;;Why set 'segment registers' ds, es, and ss to ax(0) value?
;;;;;;;;;;Is it just to have a fresh start on everything?
Code:
    
    movzx dx, dl                        ;converts byte to word or double word using a zero extension
                                        ;(fills extra bits of larger item with zeros)    

;;;;;;;;;;How do we know what 'dl' current value is before performing this operation?
;;;;;;;;;;Why not xor dl, dl prior to this?
Code:
    mov[bootdrive], dx                  ;defined word bootdrive is given the value of dx
                                        ;Modify's the second byte of 'bootdrive' with the value of 'dx' which I believe are zeros...    

;;;;;;;;;;What purpose does this serve if 'bootdrive' has only been declared a dw and filled with zeros?
;;;;;;;;;;Does defining 'bootdrive' also automatically give it an address location in memory?

Code:
    mov si, msg                         ;store location of message in the source index
get_msg:                                ;define label get_msg
    lodsb                               ;loads a memory byte addressed by si into the accumlator(al)
    or al, al                           ;compares al to itself but doesn't alter al's value and if al=0
                                        ;then loop is complete
    jz keys_hang                        ;if the value of al is zero then jump to label keys_hang
    mov ah, 0Eh                         ;mov sub-function 0Eh into ah
                                        ;to retrieve the value stored in al
    int 10h                             ;using int 10h
    jmp get_msg                         ;if value of al is not zero loop back to start of label get_msg to retrieve next character

keys_hang:                              ;define label keys_hang
    xor ax, ax                          ;clears out register ax
    ;mov ah, 0                          ;move sub-function 0 into ah and
    ;int 16h                            ;call int 16h to get keystroke from keyboard - ascii value is stored in al
    ;jz hang_end                        ;test for zero flag and if true jump to hang_end
    jmp hang_end                        ;I commented out the above and replaced it with an unconditional jump
                                        ;since there was no need
                                        ;to detect keypress since testing of this section of code was complete.

hang_end:                               ;define label hang_end
    
    xor ax, ax                          ;clear out the ax register( ax is assigned a value of 0 )
    mov es, ax                          ;reset or set extra segments' address to ax(0)
    
    mov dx,[bootdrive]                  ;I'm assuming move the address or offset of bootdrive into the data register    

;;;;;;;;;;But if not the address or offset, then why move the value of dw bootdrive into 'dx' when the reverse
;;;;;;;;;;was done early and no 'dx' alterations in between?
Code:
    mov ah, 02h                         ;read disk sectors into memory ... sub-function of int 13h
    mov al, 1                           ;number of sectors to read/write
    mov ch, 0                           ;cylinder number
    mov cl, 2                           ;sector number
    
    mov bx, next                        ;points to the data buffer ... [ES:BX]    

;;;;;;;;;;I'm assuming the use of a label instead of an address location because this allows
;;;;;;;;;;the compiler to figure out the next address buffer's location for us...Is this correct?

Code:
    int 13h                             ;bios interrupt to read disk sectors into memory with aid of sub-function 02h
    jmp next                            ;jump to label next after sectors have been read into memory


msg db 'Welcome to My_OS BootLoader...', 13, 10      ;standard message define byte with carriage return and newline
    db 'A newbie style boot loader...', 13, 10       ;same
    db ' ', 13, 10, 0                                ;same but zero (null) terminated (hence end of string)
    bootdrive dw 0                                   ;define word bootdrive ...    

;;;;;;;;;;Does the '0' mean null terminated or is '0' the
;;;;;;;;;;assigned value of the defined word bootdrive?

Code:
    times 510 - ($-$$) db 0                          ;calculate remaining area to be filled with zeros
                                                     ;after the end of our program

    db 0x55                                          ;also could be written as dw 0xAA55 instead of two 8-bit db's.
    db 0xAA                                          ;The boot signature. Tells bios that our 512b sector is bootable

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;The end of the bootsector - on to stage two;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
next:
      cld                                            ;clear direction flag and sets forward direction
      xor ax, ax                                     ;clear register ax
      mov es, ax                                     ;reset or set extra segments' address to ax(0)
      mov si, stage2msg                              ;store location of stage2msg in the source index
    
ld_msg:                                              ;define ld_msg label
      lodsb                                          ;loads a memory byte addressed by si into the accumlator(al)

      or al, al                                      ;compares al to itself but doesn't alter al's value and if al=0
                                                     ;then loop is complete
      jz illusBootMacs                               ;if 'al' is zeroed out then jump to label illusBootMacs

      mov ah, 0Eh                                    ;sub-function of int 10h which basically instructs int 10h
                                                     ;to display the value in 'al'
                                                     ;which contains the current value in the keyboard buffer
      int 10h                                        ;executes sub-function OEH of int 10h

      jmp ld_msg                                     ;continue loop until 'al' is zeroed out


      stage2msg db 'Second Stage following boot sector....', 13, 10, 0    ;output message with carriage return,
                                                                          ;newline, and zero termination

illusBootMacs:
     xor ah, ah
     include 'bootmacs.inc'
     echo ' '
     echo 'Welcome to BootMacs....'
     echo 'BootMacs are Macros written with FASM syntax...'
     echo ' '
     echo ' '
     echo 'Press any key to reboot....'
     echo ' '
     xor ah, ah
     mov ah, 00h
     int 16h
     jnz inf_lp

    inf_lp:
      int 19h
      jmp inf_lp


times 1474560 - ($ - $$) DB 0             ;marks end of second stage....pretty much rest of floppy...    

;;;;;;;;;;By using times 1474560 instead of times 510 or times 1024, etc...
;;;;;;;;;;Does this basically tell the compiler that from the end of our program
;;;;;;;;;;to the end of the floppy is virtually sector 2?

_________________
It's the desire to learn that leads to success...

http://www.webicomp.com
Post 21 Jun 2012, 05:46
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
Quote:

;;;;;;;;;;Why current location +5?
;;;;;;;;;;+5 is the only one that seems to work...not +2 or +3 or +10, etc...???.


"$" is the address of the current instruction.. just imagine a label before the instruction:
Code:
label: jmp 0:label+5    

the instruction itself, "jmp 0:$+5" is 5 bytes long:
JMP: 1 byte
0 : 2 bytes
$+5: 2 bytes
if you add them together, then add that to the current instruction, you get the address of the next instruction.

Code:
jmp 0:addr
addr:    
is one of the ways to reset the CS (Code Segment) register.


Quote:
;;;;;;;;;;Why set 'segment registers' ds, es, and ss to ax(0) value?
;;;;;;;;;;Is it just to have a fresh start on everything?
you need to initialize your registers. the proceeding use of the "bootdrive" variable, for example, is sensitive to the value in DS. if you place a non-zero value in DS when that instruction is executed the data will end up writing elsewhere (16*DS + bootdrive). zero is chosen since all memory currently accessed by the bootsector code is within the lowest 64k.

Quote:
;;;;;;;;;;How do we know what 'dl' current value is before performing this operation?
;;;;;;;;;;Why not xor dl, dl prior to this?
the BIOS gives you a "key" to whatever disk was used to boot your boot sector. it's basically "position independence" in a multiple floppy/hard-drive situation. the key is in DL only. from what I know DH is undefined (the high 8bits of DX).

Quote:
;;;;;;;;;;What purpose does this serve if 'bootdrive' has only been declared a dw and filled with zeros?
the point is to initialize the memory location for later. DL is a runtime value. just because one BIOS gives a zero in DL doesn't mean they all will. if you "sample" the output from one BIOS it's liable to break on a different BIOS or, more likely, a different configuration.
Quote:
;;;;;;;;;;Does defining 'bootdrive' also automatically give it an address location in memory?
when you declare "bootdrive dw 0" you tell FASM to generate space in the image for it. you also tell FASM to assign "bootdrive" the address of the memory.
Quote:
;;;;;;;;;;But if not the address or offset, then why move the value of dw bootdrive into 'dx' when the reverse
;;;;;;;;;;was done early and no 'dx' alterations in between?

in FASM: "bootdrive" is a symbolic constant. it's the address of the memory.
"[bootdrive]" is a runtime value. it means: "read the value from bootdrive into the register"

as to the "no alterations": I assume that DX is modified between "int" usage so it needs to be re-initialized. I don't think ES needs to be re-initialized; that was a slip on my part.
Quote:
;;;;;;;;;;I'm assuming the use of a label instead of an address location because this allows
;;;;;;;;;;the compiler to figure out the next address buffer's location for us...Is this correct?
FASM is simply writing the memory address (a constant) in the BX register. BX is an input to "int 13h". it, along with ES (which is zero), tells the BIOS where to write the sector you've asked for.
Quote:
;;;;;;;;;;Does the '0' mean null terminated or is '0' the
;;;;;;;;;;assigned value of the defined word bootdrive?
when FASM generates the image for you it needs to know what numeric value should be placed into those 2 bytes (1 word).
Quote:
;;;;;;;;;;By using times 1474560 instead of times 510 or times 1024, etc...
;;;;;;;;;;Does this basically tell the compiler that from the end of our program
;;;;;;;;;;to the end of the floppy is virtually sector 2?
you can have FASM initialize 1.4mb of diskspace/memory for you. however its not required by any serious tools. VMware can easily handle images that are smaller than 1.4mb. as for the actual hardware; they don't know any better. the BIOS only looks at the boot signature to validate the presence of a boot sector. the data beyond doesn't need to be zeros.

Stefan
Post 21 Jun 2012, 09:36
View user's profile Send private message Visit poster's website Reply with quote
newport



Joined: 08 Jun 2012
Posts: 86
Location: Kentucky, USA
newport
BAiC...you are the man!

Thanks man. It's starting to make a lot more sense. Now I'm gonna take your answers to my questions and study them so I completely understand them, then I'm gonna try to re-write this multi-stage bootloader to see if I can develop it on my own using the knowledge that I've gained here. --without peeking at the code of course--lol

You don't know how much I appreciate you helping and taking time out of your own endeavors to help me understand. Also, I think this thread will serve as some great information to help other newcomers who want to get into OS design and construction. (IMO) I have found that most assembly tutorials and books, etc. simply tell you what is happening.. 'somewhat', but very few actually tell you why the instructions and code are implemented the way they are...

One day I hope to know enough about x86 assembly to write a .pdf/book entitled, "x86 Assembly for Extreme Dummies"..LOL!

Once again..., I'm sure that many others and definitely myself appreciate the information that has risen from this thread!

_________________
It's the desire to learn that leads to success...

http://www.webicomp.com
Post 21 Jun 2012, 10:31
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC
you're welcome. I'm glad I could help.

- Stefan
Post 21 Jun 2012, 21:48
View user's profile Send private message Visit poster's website Reply with quote
ksanjeet



Joined: 27 May 2012
Posts: 3
ksanjeet
very useful thread for a begineer like me..
Post 14 Sep 2012, 19:12
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.