initial commit, asm operating system with the MikeOS bootloader

This commit is contained in:
DeaDvey 2025-06-07 14:58:48 +01:00
commit c99ecaa620
28 changed files with 13146 additions and 0 deletions

70
build-linux.sh Executable file
View File

@ -0,0 +1,70 @@
#!/bin/sh
# This script assembles the CrawOS bootloader, kernel and programs
# with NASM, and then creates floppy and CD images (on Linux)
# Only the root user can mount the floppy disk image as a virtual
# drive (loopback mounting), in order to copy across the files
# (If you need to blank the floppy image: 'mkdosfs disk_images/crawos.flp')
if test "`whoami`" != "root" ; then
echo "You must be logged in as root to build (for loopback mounting)"
echo "Enter 'su' or 'sudo bash' to switch to root"
exit
fi
if [ ! -e disk_images/crawos.flp ]
then
echo ">>> Creating new CrawOS floppy image..."
mkdosfs -C disk_images/crawos.flp 1440 || exit
fi
echo ">>> Assembling bootloader..."
nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit
echo ">>> Assembling CrawOS kernel..."
cd source
nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit
cd ..
echo ">>> Assembling programs..."
echo ">>> Adding bootloader to floppy image..."
dd status=noxfer conv=notrunc if=source/bootload/bootload.bin of=disk_images/crawos.flp || exit
echo ">>> Copying CrawOS kernel and programs..."
rm -rf tmp-loop
mkdir tmp-loop && mount -o loop -t vfat disk_images/crawos.flp tmp-loop && cp source/kernel.bin tmp-loop/
sleep 0.2
echo ">>> Unmounting loopback floppy..."
umount tmp-loop || exit
rm -rf tmp-loop
echo ">>> Creating CD-ROM ISO image..."
rm -f disk_images/crawos.iso
mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.flp disk_images/ || exit
echo '>>> Done!'
sudo qemu-system-i386 -drive file=disk_images/crawos.flp,index=0,if=floppy,format=raw

117
build-macos.sh Executable file
View File

@ -0,0 +1,117 @@
#!/bin/bash -u
if ! [ "$(id -u)" -eq 0 ]; then
echo "[halt] Not running with superuser privileges."
exit 1
fi
echo "[okay] running as superuser."
vercomp() {
[ "$1" = "$2" ] && return 0
local IFS=.
local i ver1=($1) ver2=($2)
unset IFS
if [ "${#ver1[@]}" -ne "${#ver2[@]}" ]; then
echo "[halt] versions being compared don't have the same form!" >&2
echo "[halt] '$1' vs '$2'" >&2
exit 1
fi
for ((i = 0; i < ${#ver1[@]}; ++i)); do
(( ${ver1[i]} > ${ver2[i]} )) && return 1
(( ${ver1[i]} < ${ver2[i]} )) && return 2
done
return 0
}
nasm_version_check () {
vercomp $1 $2
case $? in
0) op='=';;
1) op='>';;
2) op='<';;
esac
if [ $op = '=' ] || [ $op = '>' ]; then
echo "[okay] nasm version at least '$2'"
return 0
else
echo "[halt] nasm version is too low" >&2
return 1
fi
}
# Main
declare -r NASM_VER_REGEX='[0-9]+\.[0-9]+\.[0-9]+'
declare -r MINIMUM_NASM_VERSION=2.10.09
declare -r NASM_PATH=$(which nasm)
declare current_nasm_version=
if [ -z "$NASM_PATH" ]; then
echo "[halt] nasm was not found on the system! Make sure it is named nasm and is in the path."
exit 1
fi
current_nasm_version=$(nasm -v)
[ $? -ne 0 ] && echo '[halt] error calling nasm' >&2 && exit 1
if [[ "$current_nasm_version" =~ $NASM_VER_REGEX ]]; then
current_nasm_version=${BASH_REMATCH[0]}
echo "[okay] found current nasm version of '$current_nasm_version'"
else
echo "[halt] could not determine nasm version" >&2
exit 1
fi
nasm_version_check "$current_nasm_version" "$MINIMUM_NASM_VERSION"
[ $? -ne 0 ] && echo "[halt] nasm not found or version is incompatible" >&2 && exit 1
"$NASM_PATH" -O0 -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit 1
echo "[okay] assembled bootloader"
cd source
"$NASM_PATH" -O0 -f bin -o kernel.bin kernel.asm || exit 1
echo "[okay] assembled kernel"
cd ..
cd programs
for i in *.asm; do
"$NASM_PATH" -O0 -f bin $i -o "$(basename $i .asm).bin" || exit 1
echo "[okay] assembled program: $i"
done
echo "[okay] assembled all programs"
cd ..
cp disk_images/mikeos.flp disk_images/mikeos.dmg
echo "[okay] copied floppy image"
dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.dmg || exit 1
echo "[okay] added bootloader to image"
tmp_file=$(mktemp -d /tmp/$(basename $0).XXXXXX)
[ $? -ne 0 ] && echo "[halt] error creating a temp file" >&2 && exit 1
dev=$(echo -n $(hdid -nobrowse -nomount disk_images/mikeos.dmg))
[ $? -ne 0 ] && echo "[halt] could not create disk from image" >&2 && exit 1
mount -t msdos "$dev" "$tmp_file"
[ $? -ne 0 ] && echo "[halt] could not mount "$dev"" >&2 && exit 1
cp source/kernel.bin "$tmp_file/"
cp programs/*.bin programs/*.bas programs/sample.pcx programs/vedithlp.txt programs/gen.4th programs/hello.512 "$tmp_file"
echo "[okay] added programs to image"
diskutil umount "$tmp_file"
hdiutil detach "$dev"
rm -rf "$tmp_file"
echo "[okay] unmounted floppy image"
rm -f disk_images/mikeos.iso
mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/mikeos.iso -b mikeos.dmg disk_images/ || exit 1
echo "[okay] converted floppy to ISO-8859-1 image"
echo "[done] build completed"

80
build-openbsd.sh Executable file
View File

@ -0,0 +1,80 @@
#!/bin/sh
# This script assembles the MikeOS bootloader, kernel and programs
# with NASM, and then creates floppy and CD images (on OpenBSD)
# Only the root user can mount the floppy disk image as a virtual
# drive (loopback mounting), in order to copy across the files
echo "Experimental OpenBSD build script..."
if test "`whoami`" != "root" ; then
echo "You must be logged in as root to build (for loopback mounting)"
echo "Enter 'su' to switch to root"
exit
fi
if [ ! -e disk_images/mikeos.flp ]
then
echo ">>> Creating new MikeOS floppy image..."
dd if=/dev/zero of=disk_images/mikeos.flp bs=512 count=2880 || exit
vnconfig vnd3 disk_images/mikeos.flp && newfs_msdos -f 1440 vnd3c && vnconfig -u vnd3 || exit
fi
echo ">>> Assembling bootloader..."
nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit
echo ">>> Assembling MikeOS kernel..."
cd source
nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit
cd ..
echo ">>> Assembling programs..."
cd programs
for i in *.asm
do
nasm -O0 -w+orphan-labels -f bin $i -o `basename $i .asm`.bin || exit
done
cd ..
echo ">>> Adding bootloader to floppy image..."
dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.flp || exit
echo ">>> Copying MikeOS kernel and programs..."
rm -rf tmp-loop
vnconfig vnd3 disk_images/mikeos.flp || exit
mkdir tmp-loop && mount -t msdos /dev/vnd3c tmp-loop && cp source/kernel.bin tmp-loop/
cp programs/*.bin programs/*.bas programs/sample.pcx programs/vedithlp.txt programs/gen.4th programs/hello.512 tmp-loop
echo ">>> Unmounting loopback floppy..."
umount tmp-loop || exit
vnconfig -u vnd3 || exit
rm -rf tmp-loop
echo ">>> Creating CD-ROM ISO image..."
rm -f disk_images/mikeos.iso
mkisofs -quiet -V 'MIKEOS' -r -J -o disk_images/mikeos.iso -b mikeos.flp disk_images/ || exit
echo '>>> Done!'

40
buildwin.bat Executable file
View File

@ -0,0 +1,40 @@
@echo off
echo Build script for Windows
echo.
echo Assembling bootloader...
cd source\bootload
nasm -O0 -f bin -o bootload.bin bootload.asm
cd ..
echo Assembling MikeOS kernel...
nasm -O0 -f bin -o kernel.bin kernel.asm
echo Assembling programs...
cd ..\programs
for %%i in (*.asm) do nasm -O0 -f bin %%i
for %%i in (*.bin) do del %%i
for %%i in (*.) do ren %%i %%i.bin
cd ..
echo Adding bootsector to disk image...
cd disk_images
dd count=2 seek=0 bs=512 if=..\source\bootload\bootload.bin of=.\mikeos.flp
cd ..
echo Mounting disk image...
imdisk -a -f disk_images\mikeos.flp -s 1440K -m B:
echo Copying kernel and applications to disk image...
copy source\kernel.bin b:\
copy programs\*.bin b:\
copy programs\sample.pcx b:\
copy programs\vedithlp.txt b:\
copy programs\gen.4th b:\
copy programs\hello.512 b:\
copy programs\*.bas b:\
echo Dismounting disk image...
imdisk -D -m B:
echo Done!

BIN
disk_images/crawos.flp Normal file

Binary file not shown.

BIN
disk_images/crawos.iso Normal file

Binary file not shown.

1057
doc/CHANGES.TXT Executable file

File diff suppressed because it is too large Load Diff

41
doc/CREDITS.TXT Executable file
View File

@ -0,0 +1,41 @@
==================================================================
MikeOS -- Open source 16-bit operating system for x86 PCs
Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT
==================================================================
PROJECT ADMIN (MAIN CODE AND HANDBOOKS)
* Mike Saunders -- okachi@gmail.com
DEVELOPMENT
* E Dehling
* Ian Seyler
* John Endler
* Joshua Beck
* Justin Tokarchuk
* Mark M
* Matej Horvat
* Michael van Tellingen
* Mike Gonta
* Pablo Gonzales
* Peter Nemeth
* Paulo Valongo
* Takayoshi Sasano
* Tomasz Gorol
* Tslil Clingman
* Walt Nagel
* Yutaka Saiko
WEBSITE, DOCS AND ARTWORK
* Nitin Reddy Katkam -- logo and site design
* Paul Sommers -- Handbook API reference
* Helen Ewart -- MikeOS cat mascot
==================================================================

37
doc/LICENSE.TXT Executable file
View File

@ -0,0 +1,37 @@
==================================================================
MikeOS -- License
==================================================================
Copyright (C) 2006 - 2022 MikeOS Developers -- http://mikeos.sourceforge.net
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name MikeOS nor the names of any MikeOS contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY MIKEOS DEVELOPERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL MIKEOS DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==================================================================

1210
doc/handbook-appdev-asm.html Executable file

File diff suppressed because it is too large Load Diff

1537
doc/handbook-appdev-basic.html Executable file

File diff suppressed because it is too large Load Diff

7277
doc/handbook-forth.html Executable file

File diff suppressed because it is too large Load Diff

505
doc/handbook-sysdev.html Executable file
View File

@ -0,0 +1,505 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The MikeOS System Developer Handbook</title>
<style type="text/css">
body {
font-family: sans-serif;
}
h1 {
margin-top:5px;
color: #A00000;
}
h2 {
color: #A00000;
}
h3 {
margin-top:5px;
color: #A00000;
}
hr {
border: 0;
color: #A00000;
background-color: #A00000;
height: 3px;
}
pre {
background-color: #F0F0F0;
border: 5px solid #F0F0F0;
}
a {
text-decoration: none;
color: #0000F0;
}
a:visited {
text-decoration: none;
color: #0000F0;
}
a:hover {
text-decoration: underline;
}
li {
margin-left: -1ex;
}
</style>
</head>
<body>
<table border="0" cellpadding="10">
<tr>
<!-- NAVIGATION PANEL -->
<td style="border:1px solid black; width:160px;" valign="top">
<h3>Navigate</h3>
<p><strong>Overview</strong></p>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#structure">Structure</a></li>
<li><a href="#memorymap">Memory map</a></li>
<li><a href="#codepath">Code path</a></li>
</ul>
<p><strong>Building</strong></p>
<ul>
<li><a href="#buildlinux">Linux</a></li>
<li><a href="#buildwindows">Windows</a></li>
<li><a href="#buildothers">Others</a></li>
</ul>
<p><strong>Modifying</strong></p>
<ul>
<li><a href="#modoverview">Overview</a></li>
<li><a href="#systemcalls">System calls</a></li>
<li><a href="#patches">Patches</a></li>
</ul>
<p><strong>Extra</strong></p>
<ul>
<li><a href="#help">Help</a></li>
<li><a href="#license">License</a></li>
</ul>
</td>
<!-- MAIN CONTENT PANEL -->
<td valign="top">
<h1>The MikeOS System Developer Handbook</h1>
<h3>For version 4.7, 9 April 2022 - (C) MikeOS Developers</h3>
<p>This documentation file explains how to build MikeOS from the source code, make changes
to the kernel, and add new system calls. If you have any questions, see
<a href="http://mikeos.sourceforge.net">the MikeOS website</a> for contact details
and mailing list information.</p>
<p>Click the links on the left to navigate around this guide.</p>
<br />
<hr noshade="noshade" />
<h2>Overview</h2>
<a name="introduction"></a>
<h3>Introduction</h3>
<p>The MikeOS kernel is written in 16-bit x86 real mode assembly language. This provides easy access
to BIOS routines for handling the keyboard, screen and floppy drive, so that we don't need complicated
drivers. Therefore most of the code is focused on actual OS aspects: loading programs,
system calls and so forth.</p>
<p>Additionally, MikeOS avoids the real mode segmentation complications by existing in a single 64KiB segment.
The first 32KiB (0 - 32767) of RAM is reserved for the kernel; the second 32KiB is for external program code
and memory.</p>
<br />
<a name="structure"></a>
<h3>Structure</h3>
<p>These are the most important files and directories in the MikeOS zip file:</p>
<ul>
<li><strong>source/</strong> -- Contains the entire OS source code</li>
<li><strong>source/bootload/</strong> -- Source to generate BOOTLOAD.BIN, which is added to the disk image when building</li>
<li><strong>source/features/</strong> -- Components of MikeOS such as FAT12 support, string routines, the BASIC interpreter etc</li>
<li><strong>source/kernel.asm</strong> -- The core kernel source file, which pulls in other source files</li>
<li><strong>programs/</strong> -- Source code for programs added to the disk image</li>
</ul>
<br />
<a name="memorymap"></a>
<h3>Memory map</h3>
<p>This is the makeup of the 64KiB memory segment after MikeOS has loaded:</p>
<br />
<center>
<table border="1" cellpadding="10">
<tr><td><center><br />
<strong>0 - 24575 (hex: 0h - 5FFFh)</strong><br />
24KiB kernel executable code<br />
<br />- - - - - - - - - - - - - - -<br /><br />
<strong>24576 - 32767 (hex: 6000h - 7FFFh)</strong><br />
8KiB kernel disk operation buffer<br /><br />
</center></td></tr>
<tr><td><center>
<strong>32768 - 65535 (hex: 8000h - FFFFh</strong><br />
32KiB space for external programs</center></td></tr>
</table>
</center>
<br />
<p>So, the first 32KiB is devoted to the MikeOS kernel code and its 8KiB buffer for performing disk operations.
After that we have another 32KiB of memory, this time for external programs. These are loaded at the 32KiB point
and hence need to be ORGed to 32768 as described in the App Developer Handbook.</p>
<br />
<a name="codepath"></a>
<h3>Code path</h3>
<p>When the PC starts up, it loads the bootblock, <strong>BOOTLOAD.BIN</strong>, that was inserted into
the first sector (512 bytes) of the floppy disk image by the build script. It loads this at memory location
31744 (7C00h in hex) and begins executing it.</p>
<p><strong>BOOTLOAD.BIN</strong> then scans the floppy disk for <strong>KERNEL.BIN</strong> and loads it at
memory location <strong>2000h:0000h</strong>. Here, the 2000h is the segment and 0000h is the offset
in that segment -- you don't need to concern yourself with this, but effectively it means that the kernel is
loaded at location 131072 (128KiB) in the PC's RAM. (You get a complete memory location by multiplying the segment
by 16 and adding the offset.)</p>
<p>Once the bootloader has loaded the kernel, it jumps to memory location 131072 (aka 2000h:0000h)
to begin executing it. After this, for simplicity we ignore segments and just use offsets (0000h to FFFFh),
thereby giving us 64KiB of RAM to use.</p>
<p>At the start of the kernel we have a series of <strong>jmp</strong> instructions.
Why are these here? Well, the system calls are in semi-random places in the kernel executable.
As MikeOS evolves, the exact locations of these system calls shifts around; an external program can't guarantee
where they are. So we have a list of vectors right at the very start of the kernel which <strong>jmp</strong> to these
calls, so an external program can <strong>call</strong> these vectors and know that they'll never move!</p>
<p>There's a <strong>jmp</strong> just before these vectors to skip over them, and then the main kernel execution
starts, setting up various things and offering the user a choice of a program list or command line interface.</p>
<br />
<hr noshade="noshade" />
<h2>Building</h2>
<a name="buildlinux"></a>
<h3>Linux</h3>
<p><strong>Build requirements:</strong> the NASM assembler, dosfstools package, 'mkisofs' utility and root access. We need root
access because we loopback-mount the floppy disk image to insert our files.</p>
<p>To build MikeOS, open a terminal and switch into the expanded MikeOS package. Enter <strong>sudo bash</strong>
in Ubuntu-flavoured distros, or just <strong>su</strong> in others, to switch to the root user. Then enter:</p>
<pre>
./build-linux.sh
</pre>
<p>This will use NASM to assemble the bootloader, kernel and supplied programs, then write the bootloader to the
<strong>mikeos.flp</strong> floppy disk image in the <strong>disk_images/</strong> directory. (It writes the 512-byte
bootloader to the first sector of the floppy disk image to create a boot sector and set up a DOS-like
filesystem.) Next, the build script loopback-mounts the <strong>mikeos.flp</strong> image onto the filesystem - in other
words, mounting the image as if it was a real floppy. The script copies over the kernel (<strong>kernel.bin</strong>)
and binaries from the <strong>programs/</strong> directory, before unmounting the floppy image.</p>
<p>With that done, the script runs the 'mkisofs' utility to generate a CD-ROM ISO image of MikeOS, injecting
the floppy image as a boot section. So we end up with two files in the <strong>disk_images/</strong> directory:
one for floppy disks and one for CD-Rs. You can now use them in an emulator or on a real PC as described in
the Running section above.</p>
<br />
<a name="buildwindows"></a>
<h3>Windows</h3>
<p>Get the latest version of NASM for Windows from <a href="http://www.nasm.us/pub/nasm/releasebuilds/">this site</a>
(look for the 'win32' package. Then extract the <strong>nasm.exe</strong> file into your Windows folder (or somewhere in the path).</p>
<p>The ImDisk Virtual Disk Driver is needed since Windows does not have a
built-in mechanism for loopback drives. Get it from <a href="http://www.ltr-data.se/files/imdiskinst.exe">here</a>
(or Google it if the link is outdated). After downloading run imdiskinst.exe to install. Follow the default prompts
during the install. Also get <a href="http://www.osdever.net/downloads/other/pcopy02.zip">PartCopy</a> for copying
the bootloader on to the disk image.</p>
<p>To build MikeOS, double-click on <strong>build-win.bat</strong> or run it from the command line.
This batch file calls NASM to do the work needed to compile MikeOS and its applications.
This script mounts the floppy disk image as if it were a real disk, using:</p>
<pre>
imdisk -a -f mikeos.flp -s 1440K -m B:
</pre>
<p>You can use that command outside of <strong>build-win.bat</strong> if you want to add files to <strong>mikeos.flp</strong>,
and unmount it with:</p>
<pre>
imdisk -d -m B:
</pre>
<p>Lastly, to test in the <a href="http://www.omledom.com">QEMU PC emulator</a>,
Extract QEMU to somewhere on your computer -- <strong>C:\</strong> is best. Then enter: the following to run MikeOS under QEMU:</p>
<pre>
qemu.exe -L . -m 4 -boot a -fda mikeos.flp -soundhw all -localtime
</pre>
<p>Make sure you put the proper path names in! Ask on the mailing list if you have any problems.</p>
<br />
<a name="buildothers"></a>
<h3>Others</h3>
<p>Along with the scripts for building on Linux and Windows, you'll also find scripts for macOS and OpenBSD.
These have not been as thoroughly tested as the others, so if you find any glitches, please let us know!</p>
<p>If you want to make a build script for a new platform, it needs to:</p>
<ol>
<li>Assemble the bootloader and add it to the first sector of <strong>mikeos.flp</strong></li>
<li>Assemble the kernel and copy it onto the floppy</li>
<li>Assemble the add-on programs and copy them onto the floppy</li>
</ol>
<p>So you will need some way of copying the 512 byte bootsector into a floppy image, and loopback mounting the
image to copy across the kernel and programs.</p>
<br />
<hr noshade="noshade" />
<h2>Modifying</h2>
<a name="modoverview"></a>
<h3>Overview</h3>
<p>To test out code, the simplest approach is to create a new app in the <strong>programs/</strong> directory, build
MikeOS and run your program. You can then be guaranteed that your code isn't interfering with the kernel code (at least
at the assembling stage!). When you're happy with it, you may want to introduce it into <strong>source/kernel.asm</strong>
or a specific file in <strong>source/features/</strong>.</p>
<p>Note that the files in <strong>source/features/</strong> correspond to the system calls in <strong>programs/mikedev.inc</strong>
(and detailed in the App Developer Handbook), but those source files also include internal calls that are used by the kernel and
are not accessible to user programs. So use 'grep' or the search tool of your choice to find specific calls if they're not
available through the API.</p>
<br />
<a name="systemcalls"></a>
<h3>System calls</h3>
<p>Adding new system calls is easy and fun - it extends MikeOS! So if you want to help out, this is the best way to start.
Open up <strong>source/features/screen.asm</strong> in a text editor and paste in the following after the header text:</p>
<pre>
; -----------------------------------------------------------------
; os_say_hello -- Prints 'Hello' to the screen
; IN/OUT: Nothing
os_say_hello:
pusha
mov si, .message
call os_print_string
popa
ret
.message db 'Hello', 0
</pre>
<p>There we have it: a new system call that prints 'Hello' to the screen. Hardly a much-needed feature, but it's
a starting point. The first three lines are comments explaining what the call does, and what registers it accepts
or returns (like variable passing in high-level languages). Then we have the <strong>os_say_hello:</strong> label
which indicates where the code starts, before a <strong>pusha</strong>.</p>
<p>All system calls should start with <strong>pusha</strong> and end with <strong>popa</strong> before <strong>ret</strong>:
this stores registers on the stack at the start, and then pops them off at the end, so that we don't end up changing
a bunch of registers and confusing the calling program. (If you're passing back a value, say in AX, you should
store AX in a temporary word and drop it back in between the <strong>popa</strong> and <strong>ret</strong>, as
seen in <strong>os_wait_for_key</strong> in <strong>keyboard.asm</strong>.)</p>
<p>The body of our code simply places the location of our message string into the SI register, then calls another
MikeOS routine, <strong>os_print_string</strong>. You can freely call other routines from your own system call.</p>
<p>Once we've done this, we can access this routine throughout the kernel. But what about external programs? They
have no idea where this call is in the kernel! The trick we use is <strong>vectors</strong> - a bunch of <strong>jmp</strong>
instructions at the start of our kernel code, which jump to these routines. Because these vectors are at the start,
they never change their position, so we always know where they are.</p>
<p>For instance, right now, your new system call may be at 0x9B9D in the kernel. But if you add another call before it,
or someone else does, it may move to 0x9FA6 in the kernel binary. We simply don't know where it's going to be. But
if we put at vector at the start of our kernel, before anything else happens, we can use that as the starting point
as the vector will never move!</p>
<p>Open up <strong>source/kernel.asm</strong> and scroll down to the list of system call vectors. You can see they start
from 0003h. Scroll to the bottom of the list and you'll see something like this:</p>
<pre>
jmp os_string_tokenize ; 00CFh
</pre>
<p>The comment here indicates where this bit of code lies in the kernel binary. Once again, it's static, and
basically says: if your program wants to call <strong>os_string_tokenize</strong>, it should call 00CFh, as
this jumps to the required routine and will never change position.</p>
<p>Let's add a vector to our new call. Add this beneath the existing vectors:</p>
<pre>
jmp os_say_hello ; 00D2h
</pre>
<p>How do we know this <strong>jmp</strong> is at 00D2h in the kernel binary? Well, just follow the pattern in the
<strong>jmp</strong>s above - it's pretty easy to guess. If you're unsure, you can always use
<strong>ndisasm</strong> to disassemble the kernel and look for the location of the final
<strong>jmp</strong> in the list.</p>
<p>That's all good and well, but there's one last thing: people writing external programs don't want to
call an ugly number like 00C9h when they run our routine. They want to access it by name, so we need
to add a line to <strong>mikedev.inc</strong> in the <strong>programs/</strong> directory:</p>
<pre>
os_say_hello equ 00D2h ; Prints 'Hello' to screen
</pre>
<p>Now, any program that includes <strong>mikedev.inc</strong> will be able to call our routine by name.
Et voila: a brand new system call for MikeOS!</p>
<br />
<a name="patches"></a>
<h3>Patches</h3>
<p>If you've made some improvements or additions to MikeOS and wish to submit them, great! If they're small changes -
such as a bugfix or minor tweak - you can paste the altered code into an email. Explain what it does and where it
goes in the source code, and if it's OK, we'll include it.</p>
<p>If your change is larger (e.g. a system call) and affects various parts of the code, you're better off with a
patch. On UNIX-like systems such as Linux, you can use the <strong>diff</strong> command-line utility to generate
a list of your changes. For this, you will need the original (release) source code tree of MikeOS, along with the
tree of your modified code. For instance, you may have the original code in a directory called
<strong>mikeos-4.2/</strong> and your enhanced version in <strong>new-mikeos-4.0/</strong>.</p>
<p>Switch to the directory beneath these, and enter:</p>
<pre>
diff -ru mikeos-4.2 new-mikeos-4.2 &gt; patch.txt
</pre>
<p>This collates the differences between the two directories, and directs the output to the file <strong>patch.txt</strong>.
Have a look at the file to make sure it's OK (you can see how it shows which lines have changed), and then attach the
file to an email.</p>
<p>Please post fixes and patches to the MikeOS mailing list (see <a href="http://mikeos.sourceforge.net">the website</a>).</p>
<br />
<hr noshade="noshade" />
<h2>Extra</h2>
<a name="help"></a>
<h3>Help</h3>
<p>If you have any questions about MikeOS, or you're developing a similar OS and want
to share code and ideas, go to <a href="http://mikeos.sourceforge.net/">the MikeOS website</a>
and join the mailing list as described.</p>
<br />
<a name="license"></a>
<h3>License</h3>
<p>MikeOS is open source and released under a BSD-like license (see <strong>doc/LICENSE.TXT</strong>
in the MikeOS <strong>.zip</strong> file). Essentially, it means you can do anything you like with the
code, including basing your own project on it, providing you retain the license file and give credit
to the MikeOS developers for their work.</p>
<br />
<hr noshade="noshade" />
</td>
</tr>
</table>
</body>
</html>

469
doc/handbook-user.html Executable file
View File

@ -0,0 +1,469 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The MikeOS User Handbook</title>
<style type="text/css">
body {
font-family: sans-serif;
}
h1 {
margin-top:5px;
color: #69A000;
}
h2 {
color: #69A000;
}
h3 {
margin-top:5px;
color: #69A000;
}
hr {
border: 0;
color: #69A000;
background-color: #69A000;
height: 3px;
}
pre {
background-color: #F0F0F0;
border: 5px solid #F0F0F0;
}
a {
text-decoration: none;
color: #0000F0;
}
a:visited {
text-decoration: none;
color: #0000F0;
}
a:hover {
text-decoration: underline;
}
li {
margin-left: -1ex;
}
</style>
</head>
<body>
<table border="0" cellpadding="10">
<tr>
<!-- NAVIGATION PANEL -->
<td style="border:1px solid black; width:160px;" valign="top">
<h3>Navigate</h3>
<p><strong>Booting</strong></p>
<ul>
<li><a href="#diskimages">Disk images</a></li>
<li><a href="#writing">Writing</a></li>
<li><a href="#realpcs">Real PCs</a></li>
<li><a href="#emulators">Emulators</a></li>
</ul>
<p><strong>Running</strong></p>
<ul>
<li><a href="#usage">Usage</a></li>
<li><a href="#programs">Programs</a></li>
<li><a href="#copyingfiles">Copying files</a></li>
<li><a href="#monitor">Monitor</a></li>
<li><a href="#serialport">Serial port</a></li>
</ul>
<p><strong>Extra</strong></p>
<ul>
<li><a href="#help">Help</a></li>
<li><a href="#license">License</a></li>
</ul>
</td>
<!-- MAIN CONTENT PANEL -->
<td valign="top">
<h1>The MikeOS User Handbook</h1>
<h3>For version 4.7, 9 April 2022 - (C) MikeOS Developers</h3>
<p>This documentation file explains how to boot and use the MikeOS operating system on a real PC or an
emulator. If you have just downloaded MikeOS and want to run it, this is the guide you need. If you have
any questions, see <a href="http://mikeos.sourceforge.net">the MikeOS website</a> for contact details
and mailing list information.</p>
<p>Click the links on the left to navigate around this guide.</p>
<br />
<hr noshade="noshade" />
<h2>Booting</h2>
<a name="diskimages"></a>
<h3>Disk images</h3>
<p>After you have extracted the MikeOS <strong>.zip</strong> file, switch into the
<strong>disk_images/</strong> directory and you'll see three files:</p>
<ul>
<li><strong>mikeos.flp</strong> -- Floppy disk image containing MikeOS and programs</li>
<li><strong>mikeos.dmg</strong> -- Same as above, but with a Mac-friendly extension</li>
<li><strong>mikeos.iso</strong> -- CD ISO image built using the floppy disk image</li>
</ul>
<p>So, these files are virtual disk images that you can write to real floppy disks or
CD-Rs, or run in a PC emulator as described in a moment.</p>
<br />
<a name="writing"></a>
<h3>Writing</h3>
<p>For running MikeOS on a real PC, you will need to write one of the virtual disk images
to physical media. If you have a USB key then this is simple -- we can write the floppy disk
image to the USB key, and the PC will boot it like a virtual floppy.</p>
<p>On Linux, insert your USB key and unmount it when it appears (but don't remove it). Then open a command line
window and enter <strong>dmesg</strong> to view the kernel messages. You will see an indication at the end of the messages of the device you just plugged
in -- eg <strong>/dev/sdb</strong>. Note that you just need the device, eg /dev/sdb, rather than the number (eg /dev/sdb1). Then enter (in the disk_images directory):</p>
<pre>dd if=mikeos.flp of=/dev/sdb</pre>
<p>Of course, replace sdb with the device node. The key is now ready for booting.</p>
<p>On Windows, download the open source <a href="http://translate.google.com/translate?u=http%3A%2F%2Fshounen.ru%2Fsoft%2Fflashnul%2F&amp;hl=en&amp;ie=UTF8&amp;sl=ru&amp;tl=en">Flashnul</a> program, plug in your USB key and
enter <strong>flashnul -p</strong> to get a list of drives. When you've spotted your USB key, enter
<strong>flashnul [number] -L mikeos.flp</strong> (in the disk_images directory), replacing [number]
with the number you got before. The key is now ready for booting.</p>
<p>Note: if you plug your USB key back into the machine, the operating system may try to alter the
partition structure and stop it from working properly. So treat it as a MikeOS-only key until you
want to reformat it for normal use.</p>
<p>For floppy disks, on Windows you can use a program called <a href="http://www.chrysocome.net/rawwrite">RawWrite</a>
to copy <strong>mikeos.flp</strong> to a floppy disk. On Linux, use the <strong>dd</strong>
utility like this:</p>
<pre>dd if=mikeos.flp of=/dev/fd0</pre>
<p>If you want to run MikeOS on a machine that doesn't have a floppy drive and doesn't
boot from USB keys, you can burn and boot the <strong>mikeos.iso</strong> CD image. Any decent Windows CD burning software will
allow you to write an ISO image to a CD-R; if you don't have one, try <a href="http://infrarecorder.org">InfraRecorder.</a></p>
<p>On Linux, a graphical burning program such as K3b should do the trick, or you can use
the command line:</p>
<pre>cdrecord -dao dev=/dev/cdrom mikeos.iso</pre>
<br />
<a name="realpcs"></a>
<h3>Real PCs</h3>
<p>At a minimum, any 386 PC with 1MB of memory and a keyboard should be able to run MikeOS. In
fact, you may be able to get it running on an older machine -- please do let us know if so! Just
start your PC with the MikeOS floppy, CD-ROM or USB key inserted, and you should see the initial
dialog screen.</p>
<p>On some systems, you may need to change the boot order in your BIOS so that the PC boots
from the floppy, CD or USB key rather than the hard drive.</p>
<br />
<a name="emulators"></a>
<h3>Emulators</h3>
<p>A quick way to try MikeOS, and one that doesn't involve writing disk images to physical media,
is to use an emulator. This is particularly useful if you're writing MikeOS software or changing
the OS as described in the other two Handbooks.</p>
<p>Some of the best emulators:</p>
<ul>
<li><strong>QEMU</strong> -- Small, simple and open source (<a href="http://www.qemu.org">link</a>)</li>
<li><strong>VirtualBox</strong> -- Very powerful with a good GUI (<a href="http://www.virtualbox.org">link</a>)</li>
<li><strong>VMware</strong> -- Popular proprietary virtualisation app (<a href="http://www.vmware.com">link</a>)</li>
<li><strong>Bochs</strong> -- Takes a bit of work to set up, but good debugging tools (<a href="http://bochs.sourceforge.net">link</a>)</li>
</ul>
<p>For VirtualBox and VMware, configure the boot device to use the MikeOS floppy disk or CD ISO image.
With QEMU on Linux, run <strong>test-linux.sh</strong>, or for QEMU on Windows switch into the directory
where you installed the emulator and enter:</p>
<pre>
qemu.exe -L . -m 4 -boot a -fda mikeos.flp -soundhw all -localtime
</pre>
<p>You will need to change the path to <strong>mikeos.flp</strong> accordingly.</p>
<br />
<hr noshade="noshade" />
<h2>Running</h2>
<a name="usage"></a>
<h3>Usage</h3>
<p>When MikeOS starts up, you'll see a dialog box which gives you the option of a program
list of a command line interface. Using the cursor keys and Enter, choose OK for the former
and Cancel for the latter.</p>
<p>In the program list you can select a <strong>.BIN</strong> or <strong>.BAS</strong> program with the up/down cursor
keys and hit Enter to run it. Also, you can press Esc to return back to the original list/CLI
selection screen.</p>
<p>At the command line, enter <strong>DIR</strong> to show a list of programs, and <strong>HELP</strong>
to display inbuilt commands. You can run a program by entering the full filename (eg <strong>EDIT.BIN</strong>)
or just the name without the extension (eg <strong>EDIT</strong>). There are also file management commands such
as COPY, REN, DEL and SIZE.</p>
<br />
<a name="programs"></a>
<h3>Programs</h3>
<p>MikeOS includes several programs to perform various tasks and demonstrate features of the OS, such as:</p>
<ul>
<li><strong>EDIT.BIN</strong> -- Simple full-screen text editor (Unix-type text files only)</li>
<li><strong>VEDIT.BIN</strong> -- An alternative Vi-like editor</li>
<li><strong>EXAMPLE.BAS</strong> -- Demonstration of BASIC features (open it in EDIT.BIN to explore)</li>
<li><strong>FILEMAN.BIN</strong> -- Delete, rename and copy files on the floppy disk</li>
<li><strong>HANGMAN.BIN</strong> -- Guess the names of cities around the world</li>
<li><strong>MEMEDIT.BAS</strong> -- Colourful, powerful memory editor</li>
<li><strong>DRAW.BAS</strong> -- ASCII art drawing program</li>
<li><strong>CALC.BAS</strong> -- Powerful calculator</li>
<li><strong>SUDOKU.BAS</strong> -- Sudoku game</li>
<li><strong>LIFE.BIN</strong> -- An implementation of Conway's Game of Life</li>
<li><strong>CF.BAS</strong> -- Cosmic Flight game</li>
<li><strong>FORTH.BIN</strong> -- Forth interpreter</li>
<li><strong>PONG.BIN</strong> -- Pong game (press Esc to exit)</li>
<li><strong>LINES.BIN</strong> -- VGA video mode demo (press F to speed up, S to slow down, C to clear and Esc to exit)</li>
<li><strong>MUNCHER.BAS</strong> -- Snake-like game (use WASD keys)</li>
<li><strong>ADVNTURE.BAS</strong> -- A text adventure</li>
<li><strong>KEYBOARD.BIN</strong> -- Musical keyboard; use the bottom row of keys to play and Q to quit</li>
<li><strong>MONITOR.BIN</strong> -- Simple machine code monitor (see below)</li>
<li><strong>TERMINAL.BIN</strong> -- Minicom-like serial terminal program (see below)</li>
<li><strong>VIEWER.BIN</strong> -- Views text files and 320x200x16 PCX images such as <strong>SAMPLE.PCX</strong></li>
<li><strong>CODEBYTE.BIN</strong> -- Machine code editor; load <strong>HELLO.512</strong> for an example</li>
</ul>
<p>Note that <strong>FILEMAN.BIN</strong> and <strong>EDIT.BIN</strong> try to write to the floppy drive,
so if you've booted from a CD-R and try to manipulate files you will see write errors as it's a read-only
medium after burning.</p>
<br />
<a name="copyingfiles"></a>
<h3>Copying files</h3>
<p>If you've written MikeOS to a real floppy disk, you can just copy extra files
onto that disk in your file manager. But if you want to add files to the floppy disk images,
that requires a bit of extra work -- you need to access the disk image as if it was a real
floppy. First up is Linux: switch to the MikeOS main directory, then enter the following
commands as root:</p>
<pre>
mkdir looptmp
mount -o loop -t vfat disk_images/mikeos.flp looptmp
</pre>
<p>Now the contents of the MikeOS virtual floppy disk image are accessible in the newly-created <strong>looptmp/</strong>
directory. (We have loopback-mounted the disk image onto our filesystem.) Copy your programs into that directory, for example:</p>
<pre>
cp MYPROG.BIN looptmp/
</pre>
<p>When you're done, unmount the virtual floppy image and remove the temporary directory:</p>
<pre>
umount looptmp
rm -rf looptmp
</pre>
<p>You can now write <strong>mikeos.flp</strong> to a floppy disk or boot it in an emulator. If you want
to recreate the CD ISO image, run <strong>build-linux.sh</strong> as root; this will update <strong>mikeos.iso</strong>
with the new floppy contents.</p>
<p>If you're running Windows, you will need a special program to access <strong>mikeos.flp</strong> as if it
was a real floppy. One tool you can use is the <a href="http://www.ltr-data.se/files/imdiskinst.exe">ImDisk
Virtual Disk Driver</a>; download and run it to install. You can then mount the floppy disk image like this:</p>
<pre>
imdisk -a -f mikeos.flp -s 1440K -m B:
</pre>
Copy your files into the <strong>B:</strong> drive. When you are finished, enter:
<pre>
imdisk -d -m B:
</pre>
<p>Now the files that you copied to <strong>B:</strong> have been written into <strong>mikeos.flp</strong>.</p>
<br />
<a name="monitor"></a>
<h3>Monitor</h3>
<p>Yutaka Saito has contributed a MikeOS program that lets you enter machine code in hexadecimal format
and execute it. Run <strong>MONITOR.BIN</strong> from the command line and you'll be presented
with a '=' prompt. Now you can enter your instructions, or just 'x' to exit back to the OS.</p>
<p>MikeOS programs are loaded at the 32KiB (32768) point. The monitor converts hex code and executes
it at location 36864 in RAM -- that is, 4KiB after the where the monitor program is loaded. This is
so that your code doesn't overwrite the monitor! Consequently, any code you run should
be ORGed to 36864. For example, this is a small MikeOS program which displays the letter 'M' on
the screen. After we've assembled it, we can run <strong>ndisasm</strong> on the resulting binary
to see the hexadecimal codes:</p>
<br />
<center>
<table width="50%" cellpadding="3" border="1">
<tr><td><strong>Source code</strong></td><td><strong>Hexadecimal</strong></td></tr>
<tr><td>BITS 16</td><td>&nbsp;</td></tr>
<tr><td>%INCLUDE "mikedev.inc"</td><td>&nbsp;</td></tr>
<tr><td>ORG 36864</td><td>&nbsp;</td></tr>
<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td>mov si, message</td><td>BE0790</td></tr>
<tr><td>call os_print_string</td><td>E8FD6F</td></tr>
<tr><td>ret</td><td>C3</td></tr>
<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td>message db 'M', 0</td><td>4D00</td></tr>
</table>
</center>
<br />
<p>(The first three lines are merely assembly directives, so they don't generate any code.) Now
that we have the hex codes, we can enter them into the monitor. Note that the code must be terminated
with a dollar sign ($) character, and spaces are allowed. So, you can enter at the '=' prompt:</p>
<pre>BE0790 E8FD6F C3 4D00$</pre>
<p>When you enter this, the monitor will convert the hex codes to machine code at location 36864 in
RAM, and call that location to execute it. (Just like normal MikeOS programs, you should finish with
a <strong>ret</strong> instruction.) After execution, you'll be returned to the monitor. You can then
enter 'r' to re-run the converted code, or 'x' to exit.</p>
<br />
<a name="serialport"></a>
<h3>Serial port</h3>
<p>You can use MikeOS as a Minicom-like serial terminal emulator with <strong>TERMINAL.BIN</strong>. This lets
you connect a MikeOS machine to, for instance, a UNIX machine, and operate the UNIX machine from
MikeOS. Connect a serial (null-modem) cable between the two machines, then set up your UNIX machine
with a terminal session on the serial port.</p>
<p>For instance, if you have a Linux machine, you would add a line like this to /etc/inittab:</p>
<pre>
T0:2345:respawn:/sbin/getty/ -L ttyS0 9600 vt100
</pre>
<p>When you restart your Linux machine, it will wait for a login on the serial port. Connect
the null-modem cable to a MikeOS machine, and run TERMINAL.BIN in MikeOS. You can now enter your
username and password to log in.</p>
<p>Note that MikeOS configures the serial port to be 9600 baud, no parity, 8 data bits, 1 stop
bit. If you wish to change these settings, edit <strong>source/features/serial.asm</strong> and see the port
port setup code at the start of the file (then rebuild MikeOS as described in the <em>System Developer Handbook</em>).
Also note that only a handful of VT100 commands have been implemented at present, so programs which do complicated
things with the screen (such as Emacs) may not display properly.</p>
<p>To exit the program, press the F8 key. (You can change this to a different key by editing
the source code near the start of <strong>programs/terminal.asm</strong>.)</p>
<br />
<hr noshade="noshade" />
<h2>Extra</h2>
<a name="help"></a>
<h3>Help</h3>
<p>If you have any questions about MikeOS, or you're developing a similar OS and want
to share code and ideas, go to <a href="http://mikeos.sourceforge.net/">the MikeOS website</a>
and join the mailing list as described.</p>
<br />
<a name="license"></a>
<h3>License</h3>
<p>MikeOS is open source and released under a BSD-like license (see <strong>doc/LICENSE.TXT</strong>
in the MikeOS <strong>.zip</strong> file). Essentially, it means you can do anything you like with the
code, including basing your own project on it, providing you retain the license file and give credit
to the MikeOS developers for their work.</p>
<br />
<hr noshade="noshade" />
</td>
</tr>
</table>
</body>
</html>

BIN
source/bootload/.bootload.asm.swp Executable file

Binary file not shown.

BIN
source/bootload/.hexdump.swp Executable file

Binary file not shown.

BIN
source/bootload/.swp Executable file

Binary file not shown.

357
source/bootload/bootload.asm Executable file
View File

@ -0,0 +1,357 @@
; ==================================================================
; The Mike Operating System bootloader
; Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT
;
; Based on a free boot loader by E Dehling. It scans the FAT12
; floppy for KERNEL.BIN (the MikeOS kernel), loads it and executes it.
; This must grow no larger than 512 bytes (one sector), with the final
; two bytes being the boot signature (AA55h). Note that in FAT12,
; a cluster is the same as a sector: 512 bytes.
; ==================================================================
BITS 16
jmp short bootloader_start ; Jump past disk description section
nop ; Pad out before disk description
; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5" diskette
OEMLabel db "MIKEBOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
NumberOfFats db 2 ; Number of copies of the FAT
RootDirEntries dw 224 ; Number of entries in root dir
; (224 * 32 = 7168 = 14 sectors to read)
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerFat dw 9 ; Sectors per FAT
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for floppy
VolumeID dd 00000000h ; Volume ID: any number
VolumeLabel db "MIKEOS "; Volume Label: any 11 chars
FileSystem db "FAT12 " ; File system type: don't change!
; ------------------------------------------------------------------
; Main bootloader code
bootloader_start:
mov ax, 07C0h ; Set up 4K of stack space above buffer
add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader)
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
; NOTE: A few early BIOSes are reported to improperly set DL
cmp dl, 0
je no_change
mov [bootdev], dl ; Save boot device number
mov ah, 8 ; Get drive parameters
int 13h
jc fatal_disk_error
and cx, 3Fh ; Maximum sector number
mov [SectorsPerTrack], cx ; Sector numbers start at 1
movzx dx, dh ; Maximum head number
add dx, 1 ; Head numbers start at 0 - add 1 for total
mov [Sides], dx
no_change:
mov eax, 0 ; Needed for some older BIOSes
; First, we need to load the root directory from the disk. Technical details:
; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19
; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14
; Start of user data = (start of root) + (number of root) = logical 33
floppy_ok: ; Ready to read first block of data
mov ax, 19 ; Root dir starts at logical sector 19
call l2hts
mov si, buffer ; Set ES:BX to point to our buffer (see end of code)
mov bx, ds
mov es, bx
mov bx, si
mov ah, 2 ; Params for int 13h: read floppy sectors
mov al, 14 ; And read 14 of them
pusha ; Prepare to enter loop
read_root_dir:
popa ; In case registers are altered by int 13h
pusha
stc ; A few BIOSes do not set properly on error
int 13h ; Read sectors using BIOS
jnc search_dir ; If read went OK, skip ahead
call reset_floppy ; Otherwise, reset floppy controller and try again
jnc read_root_dir ; Floppy reset OK?
jmp reboot ; If not, fatal double error
search_dir:
popa
mov ax, ds ; Root dir is now in [buffer]
mov es, ax ; Set DI to this info
mov di, buffer
mov cx, word [RootDirEntries] ; Search all (224) entries
mov ax, 0 ; Searching at offset 0
next_root_entry:
xchg cx, dx ; We use CX in the inner loop...
mov si, kern_filename ; Start searching for kernel filename
mov cx, 11
rep cmpsb
je found_file_to_load ; Pointer DI will be at offset 11
add ax, 32 ; Bump searched entries by 1 (32 bytes per entry)
mov di, buffer ; Point to next entry
add di, ax
xchg dx, cx ; Get the original CX back
loop next_root_entry
mov si, file_not_found ; If kernel is not found, bail out
call print_string
jmp reboot
found_file_to_load: ; Fetch cluster and load FAT into RAM
mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster
mov word [cluster], ax
mov ax, 1 ; Sector 1 = first sector of first FAT
call l2hts
mov di, buffer ; ES:BX points to our buffer
mov bx, di
mov ah, 2 ; int 13h params: read (FAT) sectors
mov al, 9 ; All 9 sectors of 1st FAT
pusha ; Prepare to enter loop
read_fat:
popa ; In case registers are altered by int 13h
pusha
stc
int 13h ; Read sectors using the BIOS
jnc read_fat_ok ; If read went OK, skip ahead
call reset_floppy ; Otherwise, reset floppy controller and try again
jnc read_fat ; Floppy reset OK?
; ******************************************************************
fatal_disk_error:
; ******************************************************************
mov si, disk_error ; If not, print error message and reboot
call print_string
jmp reboot ; Fatal double error
read_fat_ok:
popa
mov ax, 2000h ; Segment where we'll load the kernel
mov es, ax
mov bx, 0
mov ah, 2 ; int 13h floppy read params
mov al, 1
push ax ; Save in case we (or int calls) lose it
; Now we must load the FAT from the disk. Here's how we find out where it starts:
; FAT cluster 0 = media descriptor = 0F0h
; FAT cluster 1 = filler cluster = 0FFh
; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user)
; = (cluster number) + 31
load_file_sector:
mov ax, word [cluster] ; Convert sector to logical
add ax, 31
call l2hts ; Make appropriate params for int 13h
mov ax, 2000h ; Set buffer past what we've already read
mov es, ax
mov bx, word [pointer]
pop ax ; Save in case we (or int calls) lose it
push ax
stc
int 13h
jnc calculate_next_cluster ; If there's no error...
call reset_floppy ; Otherwise, reset floppy and retry
jmp load_file_sector
; In the FAT, cluster values are stored in 12 bits, so we have to
; do a bit of maths to work out whether we're dealing with a byte
; and 4 bits of the next byte -- or the last 4 bits of one byte
; and then the subsequent byte!
calculate_next_cluster:
mov ax, [cluster]
mov dx, 0
mov bx, 3
mul bx
mov bx, 2
div bx ; DX = [cluster] mod 2
mov si, buffer
add si, ax ; AX = word in FAT for the 12 bit entry
mov ax, word [ds:si]
or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd
jz even ; If [cluster] is even, drop last 4 bits of word
; with next cluster; if odd, drop first 4 bits
odd:
shr ax, 4 ; Shift out first 4 bits (they belong to another entry)
jmp short next_cluster_cont
even:
and ax, 0FFFh ; Mask out final 4 bits
next_cluster_cont:
mov word [cluster], ax ; Store cluster
cmp ax, 0FF8h ; FF8h = end of file marker in FAT12
jae end
add word [pointer], 512 ; Increase buffer pointer 1 sector length
jmp load_file_sector
end: ; We've got the file to load!
pop ax ; Clean up the stack (AX was pushed earlier)
mov dl, byte [bootdev] ; Provide kernel with boot device info
jmp 2000h:0000h ; Jump to entry point of loaded kernel!
; ------------------------------------------------------------------
; BOOTLOADER SUBROUTINES
reboot:
mov ax, 0
int 16h ; Wait for keystroke
mov ax, 0
int 19h ; Reboot the system
print_string: ; Output string in SI to screen
pusha
mov ah, 0Eh ; int 10h teletype function
.repeat:
lodsb ; Get char from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp short .repeat
.done:
popa
ret
reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error
push ax
push dx
mov ax, 0
mov dl, byte [bootdev]
stc
int 13h
pop dx
pop ax
ret
l2hts: ; Calculate head, track and sector settings for int 13h
; IN: logical sector in AX, OUT: correct registers for int 13h
push bx
push ax
mov bx, ax ; Save logical sector
mov dx, 0 ; First the sector
div word [SectorsPerTrack]
add dl, 01h ; Physical sectors start at 1
mov cl, dl ; Sectors belong in CL for int 13h
mov ax, bx
mov dx, 0 ; Now calculate the head
div word [SectorsPerTrack]
mov dx, 0
div word [Sides]
mov dh, dl ; Head/side
mov ch, al ; Track
pop ax
pop bx
mov dl, byte [bootdev] ; Set correct device
ret
; ------------------------------------------------------------------
; STRINGS AND VARIABLES
kern_filename db "KERNEL BIN" ; MikeOS kernel filename
disk_error db "Floppy error! Press any key...", 0
file_not_found db "KERNEL.BIN not found!", 0
bootdev db 0 ; Boot device number
cluster dw 0 ; Cluster of the file we want to load
pointer dw 0 ; Pointer into Buffer, for loading kernel
; ------------------------------------------------------------------
; END OF BOOT SECTOR AND BUFFER START
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
buffer: ; Disk buffer begins (8k after this, stack starts)
; ==================================================================

BIN
source/bootload/bootload.bin Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

49
source/features/cli.asm Normal file
View File

@ -0,0 +1,49 @@
os_start_cli:
pusha
mov si, prompt
call os_print_string
mov di, user_input
call os_display_input
popa
ret
; ------------------------------------------------
os_read_cli:
pusha
.output_the_user_input:
call os_print_newline
mov si, command_result_text
call os_print_string
mov si, user_input
call os_print_string
call os_print_newline
.check_matches: ; Check if the user input matches any internal commands
mov si, user_input
mov di, help_string
call os_compare_strings
cmp cl, 1
je print_help_text
.finish:
call os_start_cli
print_help_text:
mov si, help_text
call os_print_string_nl
user_input times 20 db 0
prompt db 'CrawOS > ', 0
help_string db 'HELP', 0
help_text db 'This is CrawOS', 0
command_result_text db 'You typed: ', 0

View File

@ -0,0 +1,6 @@
os_reboot:
mov ax, 0x5307
mov bx, 0x0001
mov cx, 0x0003
int 0x19

152
source/features/screen.asm Executable file
View File

@ -0,0 +1,152 @@
; ==================================================================
; MikeOS -- The Mike Operating System kernel
; Copyright (C) 2006 - 2021 MikeOS Developers -- see doc/LICENSE.TXT
;
; SCREEN HANDLING SYSTEM CALLS
; ==================================================================
; ------------------------------------------------------------------
; os_print_string -- Displays text
; IN: SI = message location (zero-terminated string)
; OUT: Nothing (registers preserved)
os_print_string:
pusha
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
.repeat:
lodsb ; Get char from si into al
cmp al, 0 ; Compare al to 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat ; And move on to next char
.done:
popa
ret
; Exact same as the above procedure, but this adds a newline
; after priting, similar to the difference between Rust's print! and println!
os_print_string_nl: pusha
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
.repeat:
lodsb ; Get char from si into al
cmp al, 0 ; Compare al to 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat ; And move on to next char
.done:
call os_print_newline
popa
ret
; --------------------------------------------
os_print_newline:
pusha
mov ah, 03h
int 10h
mov ah, 02h
add dh, 1
mov dl, 0
int 10h
popa
ret
; -------------------------------------------
os_clear_screen:
pusha
mov ah, 00h
mov al, 03h ; Set video mode to textmode (80x25). 16 colors, 8 pages
int 10h
mov ah, 02h
mov dh, 0
mov dl, 0
int 10h
popa
ret
; -------------------------------------------
; AX = key pressed
os_read_input:
mov ah, 11h ; BIOS call to check for key
int 16h ; Interrupt
jnz .key_pressed ; Jump if input isn't 0
hlt
jmp os_read_input
.key_pressed:
mov ah, 10h
int 16h
ret
; -------------------------------------------
os_display_input:
pusha
call .check_key_pressed
jmp os_display_input
.check_key_pressed:
call os_read_input
cmp al, 08h
je .backspace
cmp al, 0Dh
je .enter_key
cmp al, 1Bh
je .esc_key
call .print_current_input
ret
.esc_key:
call os_reboot
.enter_key:
mov al, 0
stosb
mov di, user_input
call os_read_cli
.backspace:
mov ah, 0Eh
mov al, 08h
int 10h
mov al, 20h
int 10h
mov al, 08h
int 10h
dec di
jmp os_display_input
.print_current_input:
stosb
mov ah, 0Eh
int 10h
ret

View File

@ -0,0 +1,28 @@
; How string comparison works
; DI => scasb compares value stored in DI which is 's' with 's' stored in AX register
; and then increments DI if DF is 0
; v
; memory address 1: |s|n|a|t|0|
; memory address 2: |s|n|a|k|e|0|
; ^
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
os_compare_strings:
pusha
.compare:
lodsb
scasb ; Compare di to si
jne .unequal ; If they are no equal, jump to .unequal
cmp al, 0 ; Check if string is finished
je .equal ; If it has, return true
jmp .compare ; Finally, repeat
.unequal:
mov cl, 0 ; Change to 0 if unquality is proven
popa
ret
.equal:
mov cl, 1
popa
ret

108
source/kernel.asm Executable file
View File

@ -0,0 +1,108 @@
; ==================================================================
; MikeOS -- The Mike Operating System kernel
; Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT
;
; This is loaded from the drive by BOOTLOAD.BIN, as KERNEL.BIN.
; First we have the system call vectors, which start at a static point
; for programs to use. Following that is the main kernel code and
; then additional system call code is included.
; ==================================================================
BITS 16
CPU 386 ; pusha offsets depends on a 386 or better
; FS and GS require a 386 or better
%DEFINE CRAWOS_VER '0.0.2' ; OS version number
%DEFINE CRAWOS_API_VER 1 ; API version for programs to check
; This is the location in RAM for kernel disk operations, 24K
; after the point where the kernel has loaded; it's 8K in size,
; because external programs load after it at the 32K point:
disk_buffer equ 24576
; ------------------------------------------------------------------
; OS CALL VECTORS -- Static locations for system call vectors
; Note: these cannot be moved, or it'll break the calls!
; The comments show exact locations of instructions in this section,
; and are used in programs/mikedev.inc so that an external program can
; use a CrawOS system call without having to know its exact position
; in the kernel source code...
os_call_vectors:
jmp os_main ; 0000h -- Called from bootloader
jmp os_print_string ; 0003h
jmp os_read_input
jmp os_display_input
jmp os_start_cli
; ------------------------------------------------------------------
; START OF MAIN KERNEL CODE
os_main:
cli ; Clear interrupts
mov ax, 0
mov ss, ax ; Set stack segment and pointer
mov sp, 0FFFFh
sti ; Restore interrupts
cld ; The default direction for string operations
; will be 'up' - incrementing address in RAM
mov ax, 2000h ; Set all segments to match where kernel is loaded
mov ds, ax ; After this, we don't need to bother with
mov es, ax ; segments ever again, as MikeOS and its programs
mov fs, ax ; live entirely in 64K
mov gs, ax
cmp dl, 0
je no_change
mov [bootdev], dl ; Save boot device number
push es
mov ah, 8 ; Get drive parameters
int 13h
pop es
and cx, 3Fh ; Maximum sector number
mov [SecsPerTrack], cx ; Sector numbers start at 1
movzx dx, dh ; Maximum head number
add dx, 1 ; Head numbers start at 0 - add 1 for total
mov [Sides], dx
no_change:
call os_clear_screen
call os_start_cli
bootdev db 0
SecsPerTrack dw 18
Sides dw 2
; ------------------------------------------------------------------
; SYSTEM VARIABLES -- Settings for programs and system calls
; Time and date formatting
fmt_12_24 db 0 ; Non-zero = 24-hr format
fmt_date db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D
; Bit 7 = use name for months
; If bit 7 = 0, second byte = separator character
; ------------------------------------------------------------------
; FEATURES -- Code to pull into the kernel
%INCLUDE "features/screen.asm"
%INCLUDE "features/cli.asm"
%INCLUDE "features/power.asm"
%INCLUDE "features/strings.asm"
; ==================================================================
; END OF KERNEL
; ==================================================================

6
test-linux.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
# This script starts the QEMU PC emulator, booting from the
# MikeOS floppy disk image
qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/mikeos.flp,index=0,if=floppy