Simple 16b real-mode 'os'

This forums is for OS project announcements including project openings, new releases, update notices, test requests, and job openings (both paying and volunteer).
Post Reply
0z0
Posts: 4
Joined: Sat Oct 27, 2007 11:21 am

Simple 16b real-mode 'os'

Post by 0z0 »

Made this while ago, after which I got bored to OS developing. Maybe sometimes I will get more inspiration to continue, but for now a simple 'OS', where you can execute a binary program. I post this in case anyone finds it useful.

save as boot.asm:

Code: Select all

;=====================
;real mode boot loader
;=====================

[BITS 16]
[ORG 0x7C00]


main:
	;BIOS sets dl to contain the right device
	mov [bdrive],dl
	
	;clear screen and set up video mode
	mov al,03h ;80x25, 16color
	mov ah,00
	int 10h
	
	;print message
	mov si,boots
	call bootp


	;reset floppy for reading
	resetd:
		mov ah, 0
		mov dl,[bdrive]

		int 13h
		jc resetd


	;loop until sectors read
	readd:
		mov ax,1000h
		mov es,ax
		mov bx,0 ;ES:BX = 1000:0
			;load kernel to this address

		mov ah,02h ;read sectors
		mov al,18 ;read 18 sectors = 1 track
		mov ch,0 ;cylinder 0
		mov cl,02h ;sector 2 onwards
		mov dh,0 ;head 0
		mov dl,[bdrive]
		
		int 13h
		jc readd

	;stop floppy disk motor
	mov dx,0x3f2
        mov al,0
        out dx,al 

	;jump to kernel
	jmp 1000h:0


;boot loader data
bdrive db 0
boots db 'NawiOS loading kernel.',13,10,0


;print for boot loader
bootp:
	mov ah,0x0E
	mov bh,0x00

	.bootl
 		lodsb
 		or al,al
 		jz .bootldone
 		int 10h
 	jmp .bootl
	.bootldone
	ret




;boot sig
times 510-($-$$) db 0
dw 0xAA55
save as kernel.asm:

Code: Select all

;===========================
;START OF ACTUAL KERNEL CODE
;===========================
	start:

	;set registers
	 cli
         mov     ax, 1000h
         mov     ds, ax
         mov     es, ax
         mov     fs, ax
         mov     gs, ax

	;stack to 0x9000:0xFFFE
	mov ax,0x9000
	mov ss,ax
	mov sp, 0XFFFE
	sti

	;read hard-drive a
	resethd:
		mov ah, 0
		mov dl,80h
		int 13h
		jc resethd


	mov si,string4
	call print

	readhd:
		mov ax,3000h
		mov es,ax
		mov bx,0 ;ES:BX = 3000:0
			;load HD to this address

		mov ah,02h ;read sectors
		mov al,60 ;read 60 sectors for 30kB, should be enough :)
		mov ch,0 ;cylinder 0
		mov cl,01h ;sector 1 onwards
		mov dh,0 ;head 0
		mov dl,80h
		
		int 13h
		jc readhd


	mov si, string1
	call print

	.mainloop
		call getinput
		call execute
	jmp .mainloop
	
	.halt
	jmp .halt

execute:
	;get cursor position
	mov ah,3
	int 10h
	sub dh,1
	mov dl,2
	mov ah,2
	int 10h ;put cursor to cmd beginning

	;get ascii
	mov ah,8
	int 10h
	cmp al,' '


	jne .epstart
		mov ah,3
		int 10h
		add dh,1
		mov dl,0
		mov ah,2
		int 10h
		ret
	.epstart

	mov ah,3
	int 10h
	sub dl,1
	mov ah,2
	int 10h

	
	;get HD letter
	mov bx,3000h
	mov ds,bx
	mov si,0
	;3000h:0000

	jmp .skipgth
	;AL=HD CHAR
	;CL=SCREEN CHAR

	.bfchd
	mov ah,3
	mov bh,0
	int 10h
	mov dl,1
	mov ah,2
	int 10h


	.skipgth
	.hdloop
		;get cursor position
		mov ah,3
		mov bh,0
		int 10h
		add dl,1 ;next ascii
		mov ah,2
		int 10h 
		mov ah,8
		int 10h ;get ascii to AL
		mov bl,al ;put to bl

		lodsb
		or al,al		
		jz .hddone ;char is zero, exit
		cmp bl,al
		jne .hexit ;if different, exit
		;mov ah,0x0E
		;mov al,'q'
		;int 10h
	jmp .hdloop
	.hexit
		;loop until 0
		.hsbl
			lodsb
			or al,al
			jz .hsbx ;read next file
		jmp .hsbl
		.hsbx

		lodsb
		lodsb
		lodsb
		lodsb
		lodsb
		or al,al
		jnz .bfchd
	

		;put cursor
		mov bh,0
		mov ah,3
		int 10h
		add dh,1
		mov dl,0
		mov ah,2
		int 10h
	
		;put DS back
		mov ax,1000h
		mov ds,ax

		mov si,string5
		call print

		jmp .hddex
	
	.hddone
	cmp bl,' '
	je .chdp

	cmp bl,al
	jne .hsbx ;if different, exit

	.chdp

	;cursor
	mov bh,0
	mov ah,3
	int 10h
	add dh,1
	mov dl,0
	mov ah,2
	int 10h

	lodsb
	mov ah,al
	lodsb
	;int 10h
	xchg al,ah

	;ax has offset, move to bx
	mov bx,ax

	lodsb
	mov ah,al
	lodsb
	xchg al,ah
	;ax has size in bytes, move to cx
	mov cx,ax

	;put address to source 3000h:offset
	mov ax,3000h
	mov ds,ax
	mov si,bx

	;put address to destination 4000h:0000h
	mov ax,4000h
	mov es,ax
	mov ax,0
	mov di,ax

	;loop size times
	.cploop
		movsb
	loop .cploop

	;set registers
	;cli
        mov     ax, 4000h
        mov     ds, ax
        mov     es, ax
        mov     fs, ax
        mov     gs, ax
	sti

	;jump to: 4000h:0 (program code)
	call 4000h:0

	
	;put DS back
	cli
        mov     ax, 1000h
        mov     ds, ax
        mov     es, ax
        mov     fs, ax
        mov     gs, ax
	sti


	.hddex
	ret


print:

	mov ah,0x0E
	mov bh,0x00

	.printl
		lodsb
 		or al,al
 		jz .printdone
 		int 10h
 	jmp .printl
	.printdone
 	ret

getinput:
	mov si,string2
	call print

	.nextkey
		;wait for keypress and put to al
		mov ah,00h
		int 16h
	



		;if not backspace, skip
		cmp al,8
		jne .skipbs
			.foundbs
			;get cursor position
			mov ah,3
			int 10h

			;if x is 2 then skip
			cmp dl,2
			je .nextkey

			;subtract one from x
			sub dl,1

			;reposition
			mov ah,2
			int 10h

			;print empty
			mov al,0
			mov ah,0x0E
			int 10h

			;position -1
			mov ah,3
			int 10h
			sub dl,1
			mov ah,2
			int 10h

			jmp .nextkey
		.skipbs

		;print letter
		mov ah,0x0E
		int 10h
				

		cmp al,13 ;check for enter
		je .inputdone

		;check for max length
		mov ah,3
		int 10h
		cmp dl,79
		jne .nextkey
		sub dl,1
		mov ah,2
		int 10h
		mov al,0
		mov ah,0x0E
		int 10h
		mov ah,3
		int 10h
		sub dl,1
		mov ah,2
		int 10h
				

	jmp .nextkey
	.inputdone
	
	mov si,string3
	call print
	;mov si,string2
	;call print

	ret

pchar:
	mov ah,0Eh
	int 10h
	ret


clearscreen:
	mov al,03h ;80x25, 16color
	mov ah,00
	int 10h
	ret


;DATA
string1 db 'Kernel loading complete.',13,10,0
string2 db '> ',0
string3 db 13,10,0
string4 db 'Loading hard-drive.',13,10,0
string5 db 'File not found.',13,10,0

times 512 db 0
save as makefs.cpp

Code: Select all

//quick hack for temporary filesystem, worst. code. ever.

#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>

#include <iostream>
#include <fstream>
//#include <stdio>
//#include <stdlib>

using namespace std;

/*function... might want it in some class?*/
int getdir (string dir, vector<string> &files)
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir.c_str())) == NULL) {
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    }

    while ((dirp = readdir(dp)) != NULL) {
    	if(string(dirp->d_name).compare(".") && string(dirp->d_name).compare(".."))
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    return 0;
}

int main()
{
    string dir = string("./root");
    vector<string> files = vector<string>();

    getdir(dir,files);

	ofstream systemfile;
	systemfile.open("hd");
	//BB=2 bytes unsigned offset from 0
	//SS=2 bytes unsigneed size
	//NIMI0BBSS1NIMI0BBSS0

	int partsize[files.size()];
	
	    for (unsigned int i = 0;i < files.size();i++) {
    	if(files[i].compare(".")&&files[i].compare("..")) {

			string filli="root/";
			filli.append(files[i]);

			long begin,end;
			ifstream myfile;
			myfile.open(filli.c_str(), ios::in | ios::binary);
			if (myfile.is_open()) {
				begin = myfile.tellg();
				myfile.seekg(0,ios::end);
				end = myfile.tellg();
				myfile.close();
			}
			
			partsize[i]=end-begin;
			//cout << partsize[i] << endl;
			
        	
    	}
    }


    for (unsigned int i = 0;i < files.size();i++) {
    	if(files[i].compare(".")&&files[i].compare("..")) {

			//CALCULATE OFFSET
			int offset=files.size()*6; //6bytes for offset and marks
			for(unsigned int y=0;y < files.size();y++) {
				offset=offset+files[y].length();//name
			}
			for(unsigned int y=0;y < i;y++) {
		//		cout << "processing " << files[y] << endl;
				offset=offset+partsize[y];
				//cout << files[y] << partsize[y] << endl;
			}
				
			systemfile << files[i];
			unsigned char number = 0;
			unsigned char kaks = 1;
			systemfile.write((char *)(&number), 1);
			unsigned short int ffx=offset;//(end-begin);
			unsigned short int ffy=partsize[i];
			cout << files[i] << " size " << partsize[i] << "b offset: " << offset << endl;
			if(ffx==0) {
				systemfile.write((char *)(&number),1);
				systemfile.write((char *)(&number),1);
			} else {
				systemfile.write((char *)(&ffx), 2);
			}
			systemfile.write((char *)(&ffy), 2);
			if(files.size()-i == 1)
				systemfile.write((char *)(&number), 1);
			else
				systemfile.write((char *)(&kaks), 1);
        	
    	}
    }
    

    
    for (unsigned int i = 0;i < files.size();i++) {
    	if(files[i].compare(".")&&files[i].compare("..")) {

			string filli="root/";
			filli.append(files[i]);

			ifstream::pos_type size;
			char * memblock;


			ifstream myfile;
			myfile.open(filli.c_str(), ios::in | ios::binary);
			if (myfile.is_open()) {
				size = partsize[i];//myfile.tellg();
				memblock = new char [size];
				myfile.seekg (0, ios::beg);
				myfile.read (memblock, size);
				myfile.close();
			}
			systemfile.write(memblock, partsize[i]);
    	}
    }
    
    systemfile.close();
    return 0;
}
Save to root/ls.asm:

Code: Select all

	;simple list files command
	[BITS 16]

start:

	;get HD letter
	mov bx,3000h
	mov ds,bx
	mov si,0

	.hdloop
		;load byte
		lodsb
		or al,al

		;if zero, print space
		jnz .putspace
			;skip 4 bytes
			lodsb
			lodsb
			lodsb
			lodsb
			lodsb
			;if zero, exit
			or al,al
			jz .hddone

			;put space
			mov al,' '
		.putspace

		mov ah,0x0E
		mov bh,0
		int 10h ;print letter

	jmp .hdloop
	.hddone

	;print newline
	mov ah,0x0E
	mov al,10
	int 10h
	mov al,13
	int 10h


	retf
Compile script for linux&qemu:

Code: Select all

#!/bin/bash
rm boot
rm kernel
rm os
rm hd
nasm boot.asm -o boot
nasm kernel.asm -o kernel
cat boot kernel >os
./makefs
qemu -fda os -hda hd -boot a
Compile the ls.asm and other programs separately. Compile makefs.cpp to makefs.
In the OS, type the program name to start it.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

hint: we do have an "attach file" feature.. allows .ZIP files (up to 64kB) too..
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
0z0
Posts: 4
Joined: Sat Oct 27, 2007 11:21 am

Post by 0z0 »

Ok, check the attachment.
Attachments
nawios.zip
(17.77 KiB) Downloaded 110 times
SonOFBelial
Posts: 8
Joined: Fri Dec 07, 2007 2:46 pm

Cool.

Post by SonOFBelial »

That's a nice little OS. Good work!
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Post by AndrewAPrice »

Wow, that's cool!

Btw - You can use something like Mediafire (>100MB - no registration required) if you want to upload a disk image.
My OS is Perception.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

MessiahAndrw wrote:Wow, that's cool!

Btw - You can use something like Mediafire (>100MB - no registration required) if you want to upload a disk image.
Most hobby OS's images aren't likely to be larger then ~5/10M.. posting them here shouldn't be a big deal.

If you have an image >100M, Compress it... uploading zeros is a waist of bandwidth.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
Post Reply