Simple 16b real-mode 'os'
Posted: Mon Dec 10, 2007 9:17 am
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:
save as kernel.asm:
save as makefs.cpp
Save to root/ls.asm:
Compile script for linux&qemu:
Compile the ls.asm and other programs separately. Compile makefs.cpp to makefs.
In the OS, type the program name to start it.
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
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
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;
}
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
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
In the OS, type the program name to start it.