I know basic masm syntax and concepts. The reason I've learned it is to write my own operating system. For now all I want is something very minimalistic, but I have no idea where to begin. Do I have to create an .ISO image. If so, what do I put it in and where? How do I boot from it? All I really want the os to be capable of doing for now is booting up and displaying a message such as "hello world." All help is appreciated,
Broduer235
Hi brodeur235,
Welcome to the forum.
Creating operating systems is an advanced task. You should start with studying Iczelion's Win32asm tutorial set (http://win32assembly.online.fr)
if you want to write an OS eventually, i also suggest you become very familiar with the BIOS code to start off
having done that, you will know what process the machine goes through at start-up
also, DOS is a simple OS - take a look at how it works - it is much simpler than trying to figure out how a win OS works
EDIT:
in fact, you can write a 16-bit program and name it command.com
use io.sys and msdos.sys and the boot sector from DOS
that will do the "diplay a message at start-up" that you wanted
You will need to create a program that able to boot before you write it to a CD. THat program should be writen to the first track. I guess FASM board have all the info.
I need to tell you this, re-read the MASM license, it are not allowed you to write a program for another OS except Windows.
If you PC doesn't have a floppy, I like the flexibility of a USB flash drive (if your computer supports booting from one) so that you don't burn through CD's every time. Then, like it was said, you just have to put executable code into the first byte of the first sector, and 55 AA in bytes 510 and 511, respectively (so the BIOS knows its a valid image). I like the HxD Hex editor to do so (http://mh-nexus.de/en/hxd/); you can just copy and paste the hex codes from a debuggers memory dump.
-r
brodeur235,
Virtual PC and Vmware are other suitable environments to test operating systems.
Redskull, you would probably be the one for this job. Someone needs to make a simple "beginner's" package which will write a boot sector + loader to a floppy. Then we could just say "here, take a look at this" to these kinds of questions. Either one of two things will happen: one, the learner will experiment with it, learn from it, and make the next greatest OS. Or two, become overwhelmed at the innocuous complexity of it all and go back to visual basic. :bg
Hey, I'm still scared by innocuous complexity! There's no loader, but there is a simple, bootable "Hello World" with a longwinded explanation of how it came to be. Hopefully it helps someone.
-r
[attachment deleted by admin]
Redskull, thank you. That picked up at exactly how much I knew, e.g. general purpose and function of a bootable OS, and filled me in on the much needed technicalities of it. I especially liked that you used a usb to boot. Also, you left me with some great ideas to play around and work with such as interrupt 10 text color, etc. Excellent help. Anyways, I do have a couple questions, mostly about debug.exe. When I use it am I actually altering registers and memory while the current OS (windows now) is running? This doesn't seem possible, yet the memory addresses accessed by debug contained hardware specific info, which is to the contrary. Very confused there. A few minutes ago I had a couple more questions, but after carefully reviewing your explanation, I just found the answer to both... So, sorry if you already answered that last question somewhere in the rtf. All help appreciated,
Brodeur235
I have 1 fairly problematic dilemma.... My firmware won't boot from it. My regular boot menu, which detects bootable partitions (hd, cd drive, usb drive) does not detect the bootable flash. However, rEFIt does. (If you don't already know, rEFIt is what most mac users use as a boot menu if more than 2 HD partitions are present, otherwise all partitions after the first osx partition are seen as windows. with rEFIt you can see linux, windows, dos, solaris, etc.) As I said before, rEFIt does see my bootable OS. When I try to boot from the USB in rEFIt, i get this error message:
(http://img15.imageshack.us/img15/7320/13954493.jpg)
I'll let you interpret this to the best of your abilities because I can't seem to make much more of it than I'm ******, and that's not what I want to hear. It says:
STARTING LEGACY LOADER
USING LOAD OPTION 'USB'
ERROR: NOT FOUND RETURNED FROM LEGACY LOADER
THE FIRMWARE REFUSED TO BOOT FROM THE SELECTED VOLUME. NOTE THAT EXTERNAL
HARD DRIVES ARE NOT WELL SUPPORTED BY APPLE'S FIRMWARE FOR LEGACY OS BOOTING.
* HIT ANY KEY TO CONTINUE *
Hitting any key takes me back to the boot menu.
Just use Virtualbox or another VM product. I can't believe someone actually would bootload this proof of concept "OS" in a real machine, messing with bootloaders etc.
It would appear as though your BIOS isn't capable of booting from a USB device; It has to support 'legacy mode', which is more-or-less a way that the BIOS maps the USB device to appear as a hard drive so it can work through the old school INT 13. As far as using it with rEFIt goes, I've never used it so I can't say for certain, but there's a strong possibility that it depends on the functions the BIOS provides (e.g. no BIOS support, no bootloader support). Also, perhaps I should have clarified, but I have absolutely no idea if the Intel Macs boot up the same way as the Intel PC's. You options are to either A) get a BIOS update and hope it supports USB, B) use a different computer that does, C) do everything on a floppy disk instead, or D) use a virtual machine program (though its often less fullfilling to see something 'emulated' instead of for real)
-r
***EDIT***
a quick search turned up this: http://refit.sourceforge.net/doc/c4s1_notfound.html
Again just a pedantic note, we are assuming JWASM or POASM is being used, because the MASM license prohibits creating new OS with it. (JWASM has identical syntax to MASM, so just call jwasm.exe instead of ml.exe.)
I've also seen this USB behavior (my box won't boot from a USB stick natively either, even though it properly recognizes them in the BIOS.) For fun, tried to install Windows to one, and it said that it was not a proper bootable device. I think Redskull's hit the nail on the head however, that loader should do the trick.
Another added benefit of VMware is that you don't need to physically reboot the computer each time a test is made; I think it would be much nicer to only wait 15 seconds instead of 2-5 minutes for the test and reboot, plus inserting and removing the flash stick...
I am very sorry to be asking so many - probably annoying - questions but I'm literally working at this 24/7... I stayed up all night and still haven't found a solution: I want to boot the os in virtualbox. Virtualbox can't boot from usb's either so that idea's out. My thinking: make an iso. However, all I have is a 512 byte binary(.bin) file that I want loaded as the boatloader @ 0:7C. How do I go from this .bin to an iso. Apparently cds boot differently than regular HD partitions and USB drives. As far as I have read/found you don't write your bootloader code to the first sector of a cd to make it bootable. I have found a few .img to .iso tuts/walkthroughs, but I don't even have an .img (pretty sure that's the extension for a bootable floppy image..) Again, how can I translate my 512 byte bin into ANY bootable device,image,etc to be booted up in virtualbox. (I'm not interested in just iso's, thats just one option I found while researching and lord knows I'm not the best at researching). Help appreciated,
Brodeur235
well - you could use almost any cd boot image for that
the one for windows xp install cd, for example
now - if you want to see what the boot image does, it is only 2 kb and easy to disassemble or modify
when you create the cd, you must go into the cd burner program and tell it you want to make a bootable cd
it is 2 kb - you have to load it at segment 0 and tell the cd burner it is 2 kb (4 sectors)
i use CDBurnerXP
http://www.cdburnerxp.se/
EDIT
here is another site you might find helpful...
http://www.bootdisk.com/
you can create your own bootable image by making it similar to a
.COM program, except it is ORG'ed at 7C00h instead of 100h
another program i use for stuff like this is 7-zip
you can use your cd burner program to make an ISO image of a bootable cd
then, use 7-zip to extract all the files from the ISO
when you do, it creates the boot IMG file for you
once you have that, you may delete the ISO and other extracted files
http://www.7-zip.org/
Bootable CD's are a lot different than bootable floppy/usb/drive, read through the spec at http://www.phoenix.com/NR/rdonlyres/98D3219C-9CC9-4DF5-B496-A286D893E36A/0/specscdrom.pdf. It has to be in a special track, and I think instead of 512 it has to be around 2000? Again, I have no knowledge. As far as virtual boxes, I'm no expert; perhaps the easiest thing to do might be to just install DOS virtually, and then write over the boot sector of the 'virtual hard drive' itself, which i assume could be done from debug.exe under dos under a VM under windows (that's a mouthful) I assume you don't have a floppy drive, or spare second hard drive?
-r
that is for el torito - he doesn't want that, i don't think
still a lot of good material in there
i did find another doc on that site...
http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
At least up to 2003 the Adaptec and later Roxio CD-burning applications had the capability of creating bootable CDs in multiple formats.
most cd burner programs do - on some of em, you have to look for it - lol
i lucked into CDBurnerXP - it is written by a Swede who is very good
he is continually updating it and adding features/formats
it is good for cd's and dvd's
and - the price is right - $0
there are a lot of good boot images out there
hirens - barts pe - etc
windows IMG is a bit tricky to burn, but it can be easily modified to suit your needs and can be found all over the place
i am trying to figure out what this guy is trying to do - lol
when someone says they want to write an OS, i begin to wonder
i am sure that sounds like fun, but not really - lol
Well you guys are all awesome. I booted from an OS that I WROTE!!!! MY OS output MY NAME! :cheekygreen: I used the cdburnerxp and actually had to chase dependencies on windows... Usually that happens mostly to me in linux package manager... CDBXP required .NET, .NET required some INSTALLER 3.1, and INSTALLER 3.1 required INSTALLER 1. But... 72 hours ago my understanding of boot sectors, boot devices/images, and the boot sequence was less than half of what I know now. This is SO much fun. I just want to know if there is some way I can create the bootable image without going through a CD every time. Remember that all I have at point >A< is a .bin, and by >B< I need a bootable image. And it'd be awesome if there was a utility to do this for ubuntu. Props for all your help :clap:
Brodeur235
i suggest you uninstall windows installer 3.1 right away
it will say "the following programs might not operate if you remove it"
and give you a list
uninstall it anyways
then, install windows installer version 4.5
if you want to play with boot code (without burning a cd every time),
use a floppy disk - if you don't have a floppy drive,
i suggest you use a spare hard drive - and format it as FAT 32 (or FAT 16 if it's small)
FAT formatted disks are much easier to access and set up for tests and trials than NTFS
of course there are other approaches
bootable SSDs, etc
I do have an external HD, but it plugs into my comp via usb. Wouldn't it be interpreted in the same manner as my usb flash drive was? (virtual box AND my BIOS not supporting this type of boot).
Tell me if I'm wrong and that using an external HD plugged in via usb will be different that a usb flash drive. If that's the case I will definetely back up the info I have on my HD and test this. But until I get word that someone else thinks that might work I don't want to go thru the hassle of risking/backing up my external HD's data.
Brodeur235
I would say your best option is to go buy an internal 3.5 floppy drive; you can get a brand new one for less than $20, but most likely you can find people giving them away for free, or from a junked PC. With as much as you'll have to write the boot sector and reboot, it's worth the investment to not burn a CD everytime. Also, as was said, a virtual machine is also a great setup for saving you time between reboots.
-r
well - even though the BIOS will not boot from USB, there is likely to be some boot cd out there that will allow it
i have never had a desire to do this, but i think some of the "multi-boot" cd's boot up - then let you select a boot drive
hiren's boot cd comes to mind - or - the website bootdisk.com may have something
Went to Best Buy and got a floppy drive. Inserted an old floppy and found a games I made in the third grade in QBasic and a ppt game with hyperlinked slides. Wow, memories. [/nostalgia]. Anyways, I have ghex in ubuntu, but it doesn't have that 'extras' menu in this os's version... What's a good ubuntu app to edit a floppy byte by byte?
Brodeur235
me no speak ubuntu
i am sure there must be a better place than masm32 forum to ask that one
although, someone in here may know
one of the places i learned much about slipstreaming, boot disks, all that sort of thing is MSFN
there are a lot of sharp guys hanging out in there
you will want to register
http://www.msfn.org/
that'll cost ya $50 (not to register - pay me for the info)
EDIT
a couple other places to look....
http://www.osdcom.info/content/view/28/38/
http://www.osdever.net/tutorials/pm.php
A trip to the official ubuntu forums and with the help of some guys that respond withing 2 minutes of original thread posting, I'm all set. I can create, revise, and test an OS in >>>Nasm<<< all from ubuntu in a matter of seconds. I recently found out that the .bin file outputed by an assembler/DEBUG.exe could have it's extension changed to .img and then easily booted from in VBox, without a burn, floppy, partition, or usb. Thanks for all your help, especially redskull and dedndave, who helped me with issues that have drifted so far from the main purpose of these forums I can hardly find my way back. I can now develop my own OS, with my only restriction being my knowledge of asm, which is much easier to learn than what this thread has helped me through. Thanks again,
Brodeur235
Glad to see you got it all worked out, I was following this thread for a bit. I remember when I first started in os development its a very difficult task to take on and prepare for much MUCH harder complications to overcome. I remember reading the osdev information 20x over and over. Be sure to post results its always fun to see what people come up with. Keep at it! :U
First I want to say thanks to everyone who posted helpful replies, especially redskull and dedndave. Redskull, that simple bootloader with debug got the ball rolling for me. Now I osdev in ubuntu with nasm (don't worry masm license people :P). I'm keeping a list of the people who help me out and links to the thread in which they helped, so that one day when I've got my kickass os all together, you guys will get help points :). Anyways, this post is for anyone who cares how far I've gotten with my OS. Technically, I haven't really done much of a kernel except print and clear screen functions, but I'm on my 3rd bootloader version. The first bl was just a simple real mode bootloader that loader a fixed size, 1 sector kernel, and jumped to it. The second one added a gdt and protected mode, and the third one added a special kernel loading function that loads a variable size kernel to anywhere in memory.
[EDIT: If you copy and paste the following code into an editor, it looks better; all the comments are lined up neatly.. If you need better readability]
Here's my earliest bootloader, which I sort of went crazy with commenting for my own understanding:
;||======================================================================================||
;||-----------------------------SYNERGY OS BOOTLOADER VERSION 1--------------------------||
;||======================================================================================||
[ORG 0x7C00] ; ORIGIN = 0x0000:0x7C00
;
;procedures ; ==Procedures Section==
; *NOTE: First data MUST be code: BIOS loads bootloader and jumpts to FIRST byte.
; If first byte is data, BIOS jumps to find unexecutable statements.
;
main: ; | MAIN: PROCEDURE (First code executed, because it's located @ 0x0000:0x7C00)
xor ax,ax ; | AX = 0x0000
mov ds,ax ; | DS = AX (mov ds,0 is invalid. immediate value can't be loaded into segment registers)
; |
mov si,bl_loaded_msg ; | si = OFFSET of bl_loaded_msg
call print_si ; | calls procedure print_si (jmps there, pushing ret addr onto stack)
; |
call load_kernel ; | calls procedure load_kernel (jmps there, pusing ret addr onto stack)
jmp kernel ; V JMPS to kernel (statement could also be JMP 0x7E00)
;
print_si: ; | PRINT_SI: PROCEDURE (Prints a null delimited string to the screen using BIOS call)
mov bh,0x00 ; | BH = 0x00 (BH = page #, always 0h for our purposes)
mov bl,0x07 ; | BL = 0x07 (BL = text/bg color, 7h for white on black)
mov ah,0x0E ; | AH = 0x0E (AH Determines BIOS function we call, Eh = print single character)
.next_char ; | ".next_char" internal code label (only addressable by this name in this function)
lodsb ; | lodsb is a cool command. (1) loads BYTE [si] into al (2) increments si by 1
cmp al,0x00 ; | set flags according to comparison between al and 0
jz .done ; | if al == 0, reached string's null delimiter: (1) stop outputting chars (2) jmp to .done
int 0x10 ; | if al != 0, call BIOS function to output character in al
jmp .next_char ; | jmp to ".next_char", outputting chars until null delimiter is reached.
.done ; | ".done" internal code label (only addressable by this name in this function)
ret ; V return to where function was called (identified by double word on the top of the stack)
;
load_kernel: ; | LOAD_KERNEL: PROCEDURE (loads kernel into memory)
mov dh,0x00 ; | DH = 0 (DH = drive #. 0 is floppy drive. Can use 0 if booting from floppy .img in emu.)
mov dl,0x00 ; | DL = 0 (DL = head #. Head 0 is top of disk, head 1 is bottom of disk. <-- For floppies)
mov ch,0x00 ; | CH = 0 (CH = track #. Track 0 is first)
mov cl,0x02 ; | CL = 2 (CL = sector #. Sector 1 is where we are -boot loader- 2 is where kernel is)
xor bx,bx ; | BX = 0
mov es,bx ; | ES = BX (Again, segment registers cannot be set with an immediate value)
mov bx,kernel ; | BX = kernel (kernel = 0x0000:0x7E00, because boot loader is 0x7C-0x7DF. kernal after)
mov ah,0x02 ; | AH = 2 (AH Determines BIOS function we call, 2h= load data specified by registers)
mov al,0x01 ; | AL = 1 (AL = # of sectors to load into memory)
int 0x13 ; | call BIOS function to load drive 0, head 0, track 0, sector 2 into mem @ 0000:7E00h
ret ; V return to where function was called (identified by double word on the top of the stack)
;
;data ; ==Data Section==
;
bl_loaded_msg db "Bootloader loaded.",0xA,0xD,0 ; simple string data.
;
;padding ; ==Padding Secion==
;
times 512-2-($-$$) db 0x0000 ; Boot Loader MUST be EXACTLY 512 bytes. We used some with out code and data, pad rest w/ 0.
bootable db 0xAA, 0x55 ; Last 2 bytes of bootloader must be AA55h, signaling to BIOS that this drive is bootable.
;||======================================================================================||
;||-----------------------------SYNERGY OS KERNEL VERSION 1------------------------------||
;||======================================================================================||
;procedures
kernel:
mov si,kl_loaded_msg
call print_si
jmp $
;data
kl_loaded_msg db "Kernel loaded.",0xA,0xD,0
;padding
times 512-($-kernel) db 0x0000
Here's the latest bootloader/kernel I have (I compile with: nasm source.asm -f bin -o image.img, and use VBox to test):
;||=====================================================||
;|| BOOT LOADER ||
;||=====================================================||
;general disk info
%define HD_SECTORS_PER_TRACK 0xFF
;kernel disk info
%define KERNEL_DRIVE 0x0000
%define KERNEL_HEAD 0x0000
%define KERNEL_TRACK 0x0000
%define KERNEL_SECTOR 0x0002
%define KERNEL_SIZE (52*1024)
;kernel memory info
%define KERNEL_OFFSET 0xD000
[BITS 16]
[ORG 0x7C00]
;||====||
;||code||
;||====||
bootloader_main:
xor ax,ax
mov ds,ax
mov ss,ax
mov sp,0x100
mov si,bl_loaded_msg
call print_16b
call load_custom_kernel
lgdt [gdt_desc]
mov si,gdt_loaded_msg
call print_16b
mov eax,cr0
or eax,1
mov cr0,eax
jmp 0x8:0xD000
print_16b:
mov bh,0x00
mov bl,0x07
mov ah,0x0E
.p16b_next_char:
lodsb
cmp al,0x00
jz .p16b_done
int 0x10
jmp .p16b_next_char
.p16b_done:
ret
load_custom_kernel:
mov dx,0x0000
mov ax,KERNEL_SIZE
mov bx,0x200 ;512 decimal
div bx
cmp dx,0
jnz .lck_error_kl_size
mov BYTE [hd_sector],KERNEL_SECTOR
mov BYTE [hd_track],KERNEL_TRACK
mov WORD [kern_off],KERNEL_OFFSET
mov cx,ax ; # of sectors to copy
.lck_copy_next_sector:
push cx
cmp BYTE [hd_sector],HD_SECTORS_PER_TRACK ;if 1 greater than 2, adjust
jz .lck_continue_copying
jc .lck_continue_copying
inc BYTE [hd_track]
mov BYTE [hd_sector],0x01
.lck_continue_copying:
mov dh,KERNEL_DRIVE
mov dl,KERNEL_HEAD
mov ch,BYTE [hd_track]
mov cl,BYTE [hd_sector]
xor bx,bx
mov es,bx
mov bx,[kern_off]
mov ah,0x02
mov al,0x01
int 0x13
add WORD [kern_off],0x200
inc BYTE [hd_sector]
pop cx
loop .lck_copy_next_sector
jmp .lck_no_error
.lck_error_kl_size:
mov si,error_kl_size
call print_16b
jmp $
.lck_no_error:
mov si,kl_loaded_msg
call print_16b
jmp .lck_done
.lck_done:
ret
;||===||
;||gdt||
;||===||
gdt_entries:
;null entry
dd 0x0,0x0
;code segment descriptor: OFFESET = 0x8
dw 0xFFFF,0x0000
db 0x00,10011010b
db 11001111b,0x0
;data segment descriptor: OFFSET = 0x10
dw 0xFFFF,0x0000
db 0x00,10010010b
db 11001111b,0x0
;stack segment descriptor: OFFSET = 0x18
db 00000000b
db 11010000b
db 00000000b
db 00000000b ;Stack is 52 KB (read/writable) growing downwards from 0xD000 to 0x0000
db 00000000b
db 10010110b
db 11000000b
db 00000000b
gdt_desc:
size dw ($-gdt_entries-1)
offset dd gdt_entries
;||====||
;||data||
;||====||
;vars
hd_sector db 0x00
hd_track db 0x00
kern_off dw 0x0000
;regular updates
bl_loaded_msg db "Bootloader loaded.",0XA,0xD,0
gdt_loaded_msg db "Global Descriptor Table loaded.",0xA,0xD,0
kl_loaded_msg db "Kernel loaded.",0xA,0xD,0
;errors
error_kl_size db "Error: Kernel size not an even number of sectors!",0xA,0xD,0
;||=========================||
;||padding (512 BYTES total)||
;||=========================||
times 512-2-($-$$) db 0
;||========||
;||bootable||
;||========||
db 0xAA,0x55
;||=====================================================||
;|| END BOOT LOADER ||
;||=====================================================||
;||=====================================================||
;|| KERNEL ||
;||=====================================================||
[BITS 32]
;code
kernel_main:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
;mov ax,0x18 ;SS descriptor (offset 0x18 in GDT) doesn't work for some reason...
mov ss,ax
mov esp,0xD000 ; 52 kb stack
mov al,0x1B
call k_set_screen_colors
mov eax,0x03
mov si,((kl_exec_msg-kernel_main)+KERNEL_OFFSET)
call k_print
jmp (($-kernel_main)+KERNEL_OFFSET)
k_print:
mov ebx,0x000B8000
imul eax,160d
add ebx,eax
.kp_next_char:
lodsb
cmp al,0x00
jz .kp_done
mov BYTE [ds:ebx],al
add ebx,0x2
jmp .kp_next_char
.kp_done:
ret
k_clear_screen:
mov ebx,0x00B8000
mov ecx,(80*25)
.kcs_clear_next:
mov BYTE [ds:ebx],' '
add ebx,0x2
loop .kcs_clear_next
ret
k_set_screen_colors:
mov ebx,0x00B8001
mov ecx,(80*25)
.kssc_set_next:
mov BYTE [ds:ebx],al
add ebx,0x2
loop .kssc_set_next
ret
;data
kl_exec_msg db "Kernel Executing.",0
;padding (52 KILOBYTES total)
times (52*1024)-($-kernel_main) db 0
;||=====================================================||
;|| END KERNEL ||
;||=====================================================||
;||=====================================================||
;|| MEMORY MODEL ||
;||=====================================================||
; ______________________________________________________
;| |
;| { 52 KB stack } { 52 KB Kernel Space }
;|______________________________________________________|
I'm currently working on adding paging. And..., yeah I named the thing already... That was a fun part :P
Brodeur235
Looking good; you might want to check out the INT 13 extensions (41 and 42), which are a little more flexible than the original ones and could streamline the "load_custom_kernel" function (space is at a premium in the bootloader). You might also try downloading the source code for ReactOS (a Windows clone), which can give a nice overview of how everything fits together.
-r