Ok I have all the framework done. Programs I want it to do all linked up in another program Done. A c++ program to write to boot sector DONE. All I need now is a simple (less than a gig of text:) way to start the other program from the Original booted program I also read (several) books on makeing a 32bit asembly languige (I just can'spell well) OS I have asked on yahoo answers google everywhere (for all you sas poster not literaly) I am using flat asembly or masm im flexibul and it on windows. Using iPod to type this so no smart grammarical remarks ether. HURRY and I have tried linux AND I DON'T LIKE IT!!!

Recommended Answers

All 15 Replies

What I gather out of all this is that you want to be able to write a loader for an executable file, correct? If so, then the reference text you want is Linkers and Loaders by John Levine. It covers several executable file formats in detail, including the DOS and Windows formats. You'll also need to be able to read the file system itself, at least to the point where you can find the file you want to load in, and trying to fit that into a single 512-byte sector is tricky at best.

Mind you, if all you need to be able to do is load a raw binary image, then all you really need is the ability to find the appropriate disk sector(s) and read them into memory. This is a much easier task, and a prerequisite of loading a file in the first place. I have an old sample bootloader which is able to read in the second sector from a disk (it assumes floppy disk, unfortunately, but I'm intending to work on a more advanced version RSN) and transfer control to the loaded binary. I can post this code if you'd like, as it may help you in working out what you're trying to do.

Ok that helps, if you can come up with a better/more direct solution from this (not trying to sound rude) I am trying to make an OS but to get around most of the asembly languige and other stuff have the bootloader (already have most the code for it ) load a c++ program as its first and only comand, like the system("a://watever.exe") in c++..
Edit: sorry hat sounded rude but by more direct I mean like easyer to fit in that bootsector I just want to feed my baby the adress of the thing like A:/OS.exe is there there a way to do that?

Unfortunately, if you're writing the boot sector yourself, then you'll need to have some way of loading the OS image file, which means writing at least a minimal version of the loader and enough of the file system to find the file in question. The usual solution is a two-stage boot loader, with the second stage being an assembly program which is loaded from a fixed position on the partition and contains enough of the file system and loader to get the actual boot image loaded. If you are using a 32-bit C++ compiler, you'd also need the code that sets up the GDT and switches to protected mode before jumping to the C++ code, as well.

Rather than rolling your own boot loader, you might consider using an existing multi-boot loader such as GRUB. I know that you had said you didn't want to deal with Linux, but GRUB is not for Linux alone: it should be able to load any conventional operating system, assuming that the image file was compiled to ELF format, or you can use chain-booting to load something in a different format (though in that case you'd still need to be able to load the file itself from scratch). Since it does a lot of the heavy lifting with regards to the memory setup and protected mode state, you'd save a great deal of effort in doing things this way.

I would recommend that you look into the information available at The OS-Dev Wiki, as it covers a great deal of the details of OS design and implementation.

If it helps any, I'm posting my own boot loader for you, in hopes that it might help. It was written for Netwide Assembler, but it should be similar enough to Flat Assembler that the code should at least be intelligible. I tested it using both Bochs and a live floppy disk.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Verbum boot loader for FAT12
; * sets the segments for use in the boot process.
; * loads and verifies the boot image from the second sector, 
;    then transfers control  to it.
;
; Version History (note: build versions not shown) 
; pre      - June 2002 to February 2004 - early test versions
;                * sets segments, loads image from second sector          
; v 0.01 - 28 February 2004 Joseph Osako 
;               * Code base cleaned up
;               * Added BPB data for future FAT12 support
;               * renamed "Verbum Boot Loader"
; v0.02 - 8 May 2004 Joseph Osako
;               *  moved existing disk handling into separate functions
; v0.03 - 7 Sept 2006 Joseph Osako
;               * resumed work on project. Placed source files under
;                 version control (SVN) 	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
;;constants
;

%define boot_base   0x0000      ; the segment:offset pair for the
%define boot_offset 0x7C00	;  boot code entrypoint

stage2_base   	equ 0x1000      ; the segment:offset to load 
stage2_offset   equ 0x0000	; the second stage into
stack_seg  	equ 0x9000
stack_top	equ 0xFFFC

VBIOS	        equ 0x10        ; BIOS interrupt vector for video services
ttype	        equ 0x0E        ; print character, teletype mode
NULL	        equ 0x00        ; end of string marker
CR	        equ 0x0D        ; carriage return
LF	        equ 0x0A        ; line feed 

DBIOS	        equ 0x13        ; BIOS interrupt vector for disk services
disk_reset	equ 0x00        ; disk reset service
disk_read	equ 0x02        ; disk read service
tries           equ 0x03        ; number of times to attempt to access the FDD
reset_failure   equ 0x01        ; error code returned on disk reset failure
read_failure    equ 0x02        ; error code returned on disk read failure

cyl             equ 0x00        ; cylinder to read from
head	        equ 0x00        ; head to read from
startsector	equ 0x02        ; sector to start reading at
numsectors	equ 0x01        ; number of sectors to read


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; macros
;
%define zero(x) xor x, x

%macro write 1
   mov si, %1
   call printstr
%endmacro


[bits 16]
[org boot_offset]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; entry - the entrypoint to the code. Make a short jump passed the BPB.
entry:
  jmp short entry2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; FAT12 Boot Parameter Block - required by filesystem
OEM_ID                  db "Verb0.02"
Bytes_Per_Sector	dw 0x0200
Sectors_Per_Cluster	dw 0x0001
Reserved_Sectors	dw 0x0001
FATs		        db 0x02
Root_Entries		dw 0x00FF
Sectors_Short		dw 0x0B40
Media_Descriptor	db 0xF0		   ; assumes 3.5" 1.44M disk
Sectors_Per_FAT_Short	dw 0x0007
Sectors_Per_Track	dw 0x0012
Heads		        dw 0x02
Hidden_Sectors	        dd 0x00000000
Sectors_Long		dd 0x00000000
Sectors_Per_FAT_Long	dd 0x00000000
Extension_Flags	        dw 0x0000

; extended BPB section
Drive_Number		db 0x00
Current_Head		db 0x00
BPB_Signature		db 0x28
Serial_Number		dd 0x000001
Disk_Label              db "Verbum Boot"    ; must be exactly 11 characters
File_System		db "FAT12   "       ; must be exactly 8 characters


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; entry2 - do a far jump to ensure that you have the desired 
;          segment:offset location
entry2:
   jmp boot_base:start

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; start
; This is the real begining of the code. The first order of
; business is clearing the interrupts, then setting the
; segment registers and the stack pointer.  

start:
  mov ax, stack_seg
  cli
  mov ss, ax          ; and the stack at an arbitrarily high point past ES.
  mov sp,  stack_top  ; put the stack pointer to the top of SS
  sti                 ; reset ints so BIOS calls can be used
  mov ax, cs
  mov ds, ax          ; set DS == CS

  write testnumber   
  mov [bootdrv], dl   ; save boot drive info for later use
  write reset

; read in the data from disk and load it to ES:BX (already initalized)
  write loading
  call read_disk
  cmp ax, reset_failure
  jne good_reset
  write reset_failed
  jmp short shutdown
good_reset:
  cmp ax, read_failure
  jne good_read
  write read_failed
  jmp short shutdown

good_read:
  write done

; set up fake return frame for code returning from second stage
  mov ax, cs
  push ax
  mov ax, re_enter
  push ax  

; fake a jump to the second stage entry point
  mov ax, stage2_base
  mov es, ax
  mov bx, stage2_offset
  push es
  push bx
  write snd_stage
  retf

re_enter:
  mov ax, cs
  mov ds, ax
  write returned

shutdown:
   write exit 
   jmp short $

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Auxilliary functions      

;; printstr - prints the string point to by SI

printstr:
  push ax
  mov ah, ttype        ; set function to 'teletype mode'
  .print_char:   
    lodsb               ; update byte to print
    cmp al, NULL        ; test that it isn't NULL
    jz short .endstr
    int  VBIOS          ; put character in AL at next cursor position
    jmp short .print_char
.endstr:
  pop ax
  ret


; reset_disk
reset_disk:
  mov dl, [bootdrv]
  zero (ah)
  mov al, disk_reset
  int DBIOS
  ret

; read_disk
read_disk:
  mov cx, tries        ; set count of attempts for disk reads
  .try_read:
    push cx
    mov cx, tries      ; set count of attempts to reset disk
    .try_reset:
      call reset_disk
      jnc short .read
      loop .try_reset       ; if the reset fails, try up to three times
      mov ax, reset_failure ; if all three fail, set an error code and return
      pop cx                ; make sure that the stack is correctly aligned
      jmp short .end_fail
  .read:
    mov ax, stage2_base
    mov es, ax
    mov dl, [bootdrv] 
    mov ch, cyl          ; cylinder
    mov dh, head         ; head
    mov cl, startsector  ; first sector 
    mov al, numsectors   ; number of sectors to load   
    mov ah, disk_read
    mov bx, stage2_offset
    int DBIOS
    jnc short .end_success
    pop cx
  loop .try_read
  mov ax, read_failure ; if attempts to read the disk fail, report error code
  jmp short .end_fail
.end_success:
  pop cx               ; make sure that the stack is correctly aligned
  zero(ax)
.end_fail:
  ret
   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; data
testnumber	db 'Verbum bootloader v0.03.0', CR, LF, NULL
reset           db 'Resetting disk drive.', CR, LF, NULL
loading         db 'Loading stage two... ', NULL
done            db 'done.', CR, LF, NULL
snd_stage	db 'Second stage loaded, proceeding to switch context.', CR, LF, NULL
returned	db 'Control returned to first stage, ', NULL
reset_failed	db 'Could not reset drive,', NULL
read_failed	db 'Could not read second stage, ', NULL
exit            db 'system halted.', NULL

bootdrv	        resb 1  ; byte reserved for boot drive ID number

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pad out to 510, and then add the last two bytes needed for a boot disk

space   times (0x0200 - 2) - ($-$$) db 0
bootsig   dw 0xAA55

The test second stage I used with this to make sure it worked was this:

;;;;;;;;;;;;;;;;;
;; stagetwo.asm - second stage boot loader
;; 
;; v 0.01  Joseph Osako 3 June 2002
;; v 0.02  Joseph Osako 7 Sept 2006
;;         * restarted project, files place under source control.
;;         * Modifications for FAT12 based loader begun. 
;;
;; 

%define stage2_base 0x1000      ; the segment:offset to load 
%define stage2_offset 0x0000	; the second stage into
	
VBIOS	        equ 0x10        ; BIOS interrupt vector for video services
ttype	        equ 0x0E        ; print character, teletype mode
NULL	        equ 0x00        ; end of string marker
CR	        equ 0x0D        ; carriage return
LF	        equ 0x0A        ; line feed 

DBIOS	        equ 0x13        ; BIOS interrupt vector for disk services
disk_reset	equ 0x00        ; disk reset service
disk_read	equ 0x02        ; disk read service
tries           equ 0x03        ; number of times to attempt to access the FDD
reset_failure   equ 0x01        ; error code returned on disk reset failure
read_failure    equ 0x02        ; error code returned on disk read failure

cyl             equ 0x00        ; cylinder to read from
head	        equ 0x00        ; head to read from
startsector	equ 0x02        ; sector to start reading at
numsectors	equ 0x01        ; number of sectors to read


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; macros
;	
%define zero(x) xor x, x
			
%macro write 1
   mov si, %1
   call printstr
%endmacro

[bits 16]
[org stage2_offset]
	
entry:
   mov ax, cs
   mov ds, ax
   write success
;  jmp $
  ; 'return' to the first stage via a faked call frame set up earlier
  retf


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Auxilliary functions      

;; printstr - prints the string point to by SI

printstr:
  push ax
  mov ah, ttype        ; set function to 'teletype mode'
  .print_char:   
    lodsb               ; update byte to print
    cmp al, NULL        ; test that it isn't NULL
    jz short .endstr
    int  VBIOS          ; put character in AL at next cursor position
    jmp short .print_char
.endstr:
  pop ax
  ret


; reset_disk
reset_disk:
  mov dl, [bootdrv]
  zero (ah)
  mov al, disk_reset
  int DBIOS
  ret

	
;;;;;;;;;;;;;;;;;;;;;;;;;
;; data
success   db 'Control successfully transferred to second stage.', CR, LF, NULL

bootdrv	  db 0x00  ; byte reserved for boot drive ID number
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pad out to 512

space   times 0x0200 - ($-$$) db 0

Ok just one more question my c++ write to bootsector program had sOme probles during a test the other day (I have literaly 100 floppy disks and got them cheap so getting it to boot from usb/cd is not my consern) Is there a standered 3rd-party (like 7zip above a day to day program but If theres a micrsoft one I'll take it also I don't want to modiphy the MS-DOS files on my computer I know I sound picky but I just love DOS. So... Can't wait to hear......
Edit:Sorry as you can clearly see I am made for c++ and not asembly but do I put the .bin or the .asm on my floppy too I have not found an answer on the other question ether and thanks in advance!!

There are two programs available for this purpose, RawWrite and DD. both can be gotten from chrysocome.net for free, and while dd is a bit of a pain to use, RawWrite is fairly easy.

Mind you, even with large numbers of floppies, you might want to do some testing using Bochs and a file image, which would give a much faster turn-around during debugging. You can't use RawWrite with disk images, AFAIK, but dd will do the trick fairly easily.

As for which to load to the boot sector, you definitely want the binary file, not the source file.

Ok I thought I had software for this but I dont where do I get a simple img creater/converter for floppies the one I have is to iso. I know I dont need one for one file but for the other programs n stuff.. Oh and if there is an exe2bin (why does that sound so familer) where can I get it because acording to your above post. That would be easyer. I think I got one with Digital Mars but it didn't work so thankss again in advance again.

As it happens, the dd utility I mentioned earlier is convenient for this purpose as well, as you can use it to copy individual files into another file which can act as an image file.

Exe2Bin should be part of the MASM package, if you have that, at least it used to be. As I said, I use NASM, which can generate binaries for different formats directly, so I haven't needed that particular utility.

Well as Flat Asembler is givging me grif so I hqve to use the flat asembler for getting the asm file then half of nasam to get the bin file <usless info| So how would I do that in dd?

I'm not sure what you're asking, but I assume you mean, how would you create a disk image using dd? As it happens, the home page for the Windows version describes exactly how to do this. First, you need to make a blank image file, which can easily be done by copying the image of an empty floppy:

dd if=\\.\a: of=blankdisk.img bs=1440k

You would probably want to save this blank original and make copies of it for your actual disk images. Assuming you've made a copy named 'boot.img', you can then copy your binary to the beginning of the file like so:

dd if=kernel.bin of=boot.img

Finally, you can write this image file to the floppy like so:

dd if=boot.img of=\\.\a: bs=1440k

I hope this is what you needed, your previous post wasn't terribly clear.

You can also use the bximage utility which comes with Bochs to create blank floppy disk images. I'd nearly forgotten about that.

Also, what sort of trouble are you having with FASM? Is it with the assembler itself (the command-line tool, that is) or the editor that comes with it?

Ok the problem is in flat asembler it has a problem with the way your boot program is written so I just save the asm file and put it through nasm (not fasm... mabey) asm to bin thing and it works. In twelve hours I will post this as answred so all comments should be posted by then!

Ok all this is fine and dandy but how do I start the exe after your bootstuff is on the diskett and do I combine your two boots to One bin?

To answer the second question first, yes, you'll want to copy both of the binary sections into the boot image, then copy that to the floppy. Assuming you have a blank image file already, and have already assembled the source files to the binaries, the following batch file should do the trick:

copy blankdisk.img boot.img
dd count=1 if=verbum.bin of=boot.img seek=0
dd count=1 if=stagetwo.bin of=boot.img seek=1

This copies the blank disk image to the file being created, then copies the first binary into the boot sector, then copies the second stage into the second sector of the disk image. You can then use the following batch command to copy the boot.img file to the floppy:

dd if=boot.img of=\\.\a: bs=1440k

I recommend keeping them as separate batch files, as you may want to create disk images without writing to a disk immediately (e.g., if you are using an emulator such as Bochs for testing), and conversely you might want to be able to write to a disk without rebuilding the whole file every time.

As for the first question, well, as I've said before, what I have here is just the starting point. You'll need to have code in the second part of the boot loader which can read the filesystem on the disk to find the location of the file being loaded, then be able to not only read the file into memory, but be able to interpret the file format and load the linked file into a suitable location in memory. That's assuming you find a real-mode C++ compiler to work with which can produce executable files without the normal headers; if you are using a 32-bit compiler, then the boot loader will need to set up high memory and switch the system into protected mode before you load the file, otherwise it won't run correctly.

All of these steps depend on a lot of decisions which you need to make about the kind of system you want to design. As the OS Dev wiki says, there are no tutorials for this sort of thing; it is your operating system, so you have to set the rules. At the very least, you need to know what file system you're going to use, and what executable format you are using.

Given your stated preference for MS-DOS, you might want to start with FAT12 as your floppy disk filesystem, and go from there. FAT12 has the advantage of being easy to implement and designed for bootable systems, and has the added advantage that the files would be readable by Windows, if you do it right.

Thank you with all my heart! You should be promoted! I downloaded a asembly IO header (%define) so thanks from the posts Ive read you are the smartest person on this fourm in asembly languige!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.