Title
-Intro
-File Table
-Function Table
-Basic $AX Program
-Correct $AX Program
-boot_start
-start
-print_string
-read_file
-write_file
-disk_manage
-get_key_press
-get_string_and_print
-string_compare
-error
-find_file
-write_allocation_table
-print_char
-remove_file
-Bugs

$AX OS

Programmer Guide

Intro

File Table

The file table consists of 12 sectors and points to 1440 positions on the disk, each corresponding to a seperate file or program or 512 bytes. It is not advised but if greater amounts of space are required multiple files can be stringed together with the same filename. (This does make the task of deleteing such files much more difficult). Each filename is 4 characters long. A filename with just zeros indicate a free space. Filenames shouldn't contain spaces at the begginning but may contain spaces elsewhere in the filename. Spaces don not appear different from zeros in the ls program and may cause confusion when trying to run or load any programs or files.

Function Table

Below is the function table that all the code example below will refer to with ... Function table here. If you want to make sure you have all of the functions available from the kernel, make sure that you check the newest released kernel for the most up-to-date list. The syntax functon_name equ 0123h basically means that you don't have to call or jump to 0123h. It makes a meaningful name equal to that number making your program code more meaningful also. Please note that this table takes up no space and only increases readability in your code.
; ------------------------------
; ## FUNCTION CALLS ##

  boot_start equ 0000h ; Generally not used, completely restarts the OS
  start equ 0003h ; Generally not used, allows user to start a program one layer down
  print_string equ 0006h ; Prints a zero terminated string to the screen
  read_file equ 0009h ; Allows user to load a program from disk to RAM using a filename
  write_file equ 000Ch ; Allows user to load a program from RAM to disk using a filename
  disk_manage equ 000Fh ; Allows for custom use of the disk - USE WITH CARE!
  get_key_press equ 0012h ; Waits for the user to press a key and returns it
  get_string_and_print equ 0015h ; Gets a string of maximum length from the user and returns it
  string_compare equ 0018h ; Compares two strings and tells the user if they are equal
  error equ 001Bh ; Prints an OS error to the screen. If jumped to this will also exit the user from the program
  find_file equ 001Eh ; Searches for a file in the file table and returns whether it was found or not
  write_allocation_table equ 0021h ; Places a filename in a position that corresponds to a given sector
  print_char equ 0024h ; Prints a single character to the screen
  remove_file equ 0027h ; Allows for a given filename to deleted from the file allocation table. Note the contents remain until over-written

Basic $AX Program

Below is an example of one of the most basic $AX programs. This program will run but breaks the current $AX program format.

BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

Breakdown of Code

BITS 16 ; Program MUST be set to 16 bits
This tells the compiler that we want 16 bit binary output. As the $AX OS is currently 16 bit, 32 bit code will not work without major modification.

ORG 7168 ; Where the program is loaded, highly recommended not to be changed
This tells the compiler that we want all of our code to be compiled relative to this RAM offset. If this is removed, the offset is automativally set to zero. This can make for some interesting but unwanted results.

... Function table here
Please refer to 'Function table' for information on how this works.

main_program:
This is a label. In this case it isn't needed, but is useful for a point of refference so others looking at your code can jump straight to where the interesting stuff is happening. Usually, the main 'loop' of your program will be here. This will call (or jump) to other parts of your code and always return here as a general rule of thumb.

  ret ; Return to OS
This is the end of the executed program. When your program has finished, a simple return will return back to the OS.

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
This pads the rest of your code with zeros so that it is a sector.

dw 0AA55h ; Boot signature (DO NOT CHANGE!)
The signature is usually used for a bootsector, and indicates that it is executable. In this case, it also indicates to the kernel that a file loaded into program space is executable or not.

Correct $AX Program

Below is a better example of a $AX program.

BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

; ------------------------------
; ## PARAM CODE ##

main:
  add si, length_of_name + 1 ; Gives the program the position to start searching for parameters

.param:
  cmp byte [si], '-' ; Check for a dash as an indication there may be parameters
  jne main_program ; If no dash, run program normally

  inc si ; Check next position for parameter letter

.test:
  cmp byte [si], 'h' ; Check for 'h' - meaning help
  je print_help ; If 'h' found print help

  cmp byte [si], 'v' ; Check for 'v' - meaning version
  je print_version ; If 'v' found print the version

  jmp error ; If no correct parameter was found jump to error and exit program

; ------------------------------
; ## MAIN CODE ##

main_program: ; If the parameters have been sorted out, start running our program
  ret ; We are finnished, return to the OS

; ------------------------------
; ## PARAM CALLS ##

print_help:
  mov si, help
  call print_string ; Print help

  ret ; We are finnished, return to the OS

print_version:
  mov si, version
  call print_string ; Print the version

  ret ; We are finnished, return to the OS

; ------------------------------
; ## VARIABLES ##

version db 10, 13, 'ver 0', 0 ; It's important to keep your version up to date for everybody else!
help db 10, 13, 'Very small desciption of how to use your program.'
help2 db 10, 13, 'eg. edit [file]'
help3 db 10, 13, '-h Help'
help4 db 10, 13, '-v Version', 0 ; Note how it's only zero terminated at the end

length_of_name equ 4 ; The length of the Filename

; ## SIGNATURE ##

  times 510-($-$$)db 0 ; Pad remainder of boot sector with zeros
  dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file: ; If we were to load another file as part of the program, this is where we would load it

Breakdown of Code

The most noteable difference is the use of parameters. This allows for information to be passed from the OS prompt to the program itself.

BITS 16 ; Program MUST be set to 16 bits
This tells the compiler that we want 16 bit binary output. As the $AX OS is currently 16 bit, 32 bit code will not work without major modification.

ORG 7168 ; Where the program is loaded, highly recommended not to be changed
This tells the compiler that we want all of our code to be compiled relative to this RAM offset. If this is removed, the offset is automativally set to zero. This can make for some interesting but unwanted results.

... Function table here
Please refer to 'Function table' for information on how this works.

; ------------------------------
; ## PARAM CODE ##

main:
  add si, length_of_name + 1 ; Gives the program the position to start searching for parameters

.param:
  cmp byte [si], '-' ; Check for a dash as an indication there may be parameters
  jne main_program ; If no dash, run program normally

  inc si ; Check next position for parameter letter

.test:
  cmp byte [si], 'h' ; Check for 'h' - meaning help
  je print_help ; If 'h' found print help

  cmp byte [si], 'v' ; Check for 'v' - meaning version
  je print_version ; If 'v' found print the version

  jmp error ; If no correct parameter was found jump to error and exit program
Basically, all this does is checks if the user added additional parameters when running the program. If they did, print the information they requested. If not, continue to the main_program.

; ------------------------------
; ## MAIN CODE ##
main_program:
This is a label. In this case it isn't needed, but is useful for a point of refference so others looking at your code can jump straight to where the interesting stuff is happening. Usually, the main 'loop' of your program will be here. This will call (or jump) to other parts of your code and always return here as a general rule of thumb. The only real difference between this and one program above is the use of comments to make it stand out more.

  ret ; Return to OS
This is the end of the executed program. When your program has finished, a simple return will return back to the OS.

; ------------------------------
; ## PARAM CALLS ##

print_help:
  mov si, help
  call print_string ; Print help

  ret ; We are finnished, return to the OS

print_version:
  mov si, version
  call print_string ; Print the version

  ret ; We are finnished, return to the OS
This code just ensures that the requested information is printed.

; ------------------------------
; ## VARIABLES ##

version db 10, 13, 'ver 0', 0 ; It's important to keep your version up to date for everybody else!
help db 10, 13, 'Very small desciption of how to use your program.'
help2 db 10, 13, 'eg. edit [file]'
help3 db 10, 13, '-h Help'
help4 db 10, 13, '-v Version', 0 ; Note how it's only zero terminated at the end

length_of_name equ 4 ; The length of the Filename
This is where the variables are generally kept. Please not that it is your responsibility to keep the version up to date and Make sure that the help actually provides basic direction on how to use your program.

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
This pads the rest of your code with zeros so that it is a sector.

dw 0AA55h ; Boot signature (DO NOT CHANGE!)
The signature is usually used for a bootsector, and indicates that it is executable. In this case, it also indicates to the kernel that a file loaded into program space is executable or not.

boot_start

Summary

Generally not used, completely restarts the OS.

In

-

Out

-

Used

All

Detailed Explanation

This function exists simply for the fact that it is needed in order to skip over the other jumps available and start the OS. It is not advised to use this function as a reboot does everything this function does and clears the program space RAM.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  call boot_start
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

start

Summary

Generally not used, allows user to start a program one layer down.

In

-

Out

-

Used

All

Detailed Explanation

This function is slightly more useful than boot_start as it offers the opportunity for the text mode to be reset, the OS's prompt to be displayed and the file table to be reloaded. Be careful about running this from a program as programs are called, meaning the position is stored on the stack. Using this in a program could potentially lead to a stack overflow. A much better way of achieving similar results is to simply use ret, where the OS deals with everything for you.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  call start
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

print_string

Summary

Prints a zero terminated string to the screen.

In

SI : Position of the string

Out

-

Used

SI

Detailed Explanation

The print_string function is one of the most effective ways to display output to the user in the $AX OS. Being very simple to use and not effecting any registers other than SI this function proves to be a useful debugging tool. As long as a string is ended with a zero it will be printed. Something to note is the fact that the function prints the zero it's terminated with. In most cases this isn't visible but it's something to keep in mind when designing your program.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov si, message ; Move the location of our message into SI
  call print_string
  ret ; Return to OS

message db 10, 13, 'Hello World!', 0 ; The 10 and 13 makes a new line

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

read_file

Summary

Allows user to load a program from disk to RAM using a filename.

In

BX : Position of the string containg the filename to read
SI : Position to load the file

Out

-

Used

All

Detailed Explanation

This function reads a file selected by a given name into a given space. Most programs will be loaded into program space at 1C00h (7168), with files other than the loaded program likely being higher than this number as not to overwrite any system space in RAM. If a file is not found, the function outputs a double explanation mark to the side of the screen (!!). There currently isn't any offical way of knowing if a file was correctly loaded. A method that can be used is placing something where it's going to be loaded and checking whether the data placed is still there once loaded. In most programs it will be obvious that the file wasn't correctly loaded.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov bx, filename ; Load the filename
  mov si, file ; Point to space after program
  call read_file
  ret ; Return to OS

  filename db 'test'

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

write_file

Summary

Allows user to load a program from RAM to disk using a filename.

In

BX : Position of the string containg the filename to read
SI : Position of file to write

Out

-

Used

All

Detailed Explanation

This function writes a file from RAM (determined by SI) to a given filename (determined by BX). Please note the fact that if the a file exists, it will be overwritten and if it does not then it will be created. If your program requires the knowledge of whether it exists prior to writing it then use find_file. If there is a need to know whether the file was written, your program could load the file in a different position and perform a comparison. The only known point at which this function can fail is if there is no space on the disk or there is no disk. If there is no disk there will be no warning. If there is no space an error to the left hand side of the screen will be printed (!!).

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov bx, filename ; Load the filename
  mov si, file ; Point to space after program
  call write_file
  ret ; Return to OS

  filename db 'test'

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

disk_manage

Summary

Allows for custom use of the disk - USE WITH CARE!

In

AL : Number of sectors to edit [1 to 18]
AH : Mode to perform disk Operation [Write=03h Read=02h]
CX : Sector to perform disk operation [0 to 1439]
SI : Position to read to or write from [0 to 1439]

Out

-

Used

All

Detailed Explanation

This function allows for a custom number of sectors to be read or written at any place on the disk. The file table is not updated. This function can be extremely dangerous. If you are able to use another function then please do. The reason disk_manage has been left open for programs to use if for potential file recovery programs or efficent disk wiping. The kernel uses this function to load the 12 sector file table from the disk at kernel first load.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov al, 12 ; Load 12 sectors
  mov ah, 02h ; Read sectors from disk
  mov cx, 2 ; Where to read the sectors from
  mov si, file ; Where to read the sectors from
  call disk_manage
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

get_key_press

Summary

Waits for the user to press a key and returns it.

In

-

Out

AX : Details about key press [AL=Character AH=Attribute]

Used

AX

Detailed Explanation

get_key_press allows for the program to wait until a user presses a key. This is extremely useful for programs that require a 'Press any key to continue' scenario or to get a 'y/n' from the user. It also allows for normally unsupported keys to be seen. If you wish to get a number of characters greater than one it is recommended you use get_string_and_print for both efficiency and ease of use. A bug seen a few times on a small number of Virtual Machines is the keyboard buffer not being cleared correctly meaning that the next key press is the residue of the previous key press. If it is a large problem for your program simply making sure the keyboard buffer is empty after each key press solves the issue. On real hardware this problem has not been seen.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  call get_key_press ; Get a key stroke from the user
  cmp al, 'y' ; Has y been pressed?
  je .done ; If so exit
  jmp main_program ; If not, ask the user for input again

.done:
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

get_string_and_print

Summary

Gets a string of maximum length from the user and returns it.

In

BL : Maximum size of string to collect [0 to 255]

Out

BH : Size of string user returned [0 to 255]
SI : Position of generated user response which is zero terminated

Used

AX

Detailed Explanation

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov si, message1 ; Message to ask user for name
  call print_string

  mov bl, 32 ; Restrict name to be 32 characters long
  call get_string_and_print

  push si ; Move the position of the name to the stack
  mov si, message2 ; Print a message to nicely display their name
  call print_string
  pop si ; Get the position of their name back from the stack

  call print_string ; Print their name
  ret ; Return to OS

message1 db 10, 13, 'What is your name?', 0
message2 db 10, 13, 'Your name is', 0

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

string_compare

Summary

Compares two strings and tells the user if they are equal.

In

AX : Location of Variable 1
BX : Location of Variable 2
CH : Amount of string to compare [0 to 255]
DH : Exit charcater (stops checking if this character found)

Out

BX : Result [0=Not Equal Other=Equal]

Used

AX
BX
CH
DX

Detailed Explanation

This function is very useful for quickly comparing two strings. It comes with some useful features also, such as the ability to limit the amount of the strings to compare and an exit character to save time. When the comparison finds two characters that do not match it returns. This is because if one part of the string doesn't match then there is no point on searching any further. The result is returned in BX, where anything greater than zero means they are equal and if BX equals zero then they are not equal. Other than whether BX tells you if the two strings are equal, the number output is not very useful and any correlation between input and output is not offically supported.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov si, message1 ; Print a prompt for password
  call print_string

  mov bl, 32 ; Get a response from the user
  call get_string_and_print

  mov ax, si ; Put user's response into AX
  mov bx, password ; Put string to compare with into BX
  mov ch, 8 ; Maximum number of characters to check
  mov dh, 0 ; Exit character
  call string_compare

  cmp bx, 0 ; Are they equal?
  jne .done ; If they are equal done

  mov si, message3 ; If not print it was incorrect
  call print_string
  jmp main_program ; Ask for password again

.done:
  mov si, message2 ; Print the fact it was correct
  call print_string
  ret ; Return to OS

password db 'password'
message1 db 10, 13, 'Password:', 0
message2 db 10, 13, 'Correct', 0
message3 db 10, 13, 'Incorrect!', 0

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

error

Summary

Prints an OS error to the screen. If jumped to this will also exit the user from the program.

In

-

Out

-

Used

-

Detailed Explanation

error is $AX's standard method of telling the user there is an error. It's part of an attempt to standardise error messages. Although this doesn't tell the user much, it's a very subtle way of letting the user know something bad happened without causing disruption to the screen as it is always printed to the left. Most of the disk functions will print this error to the screen if you use them wrong. Jumping to this function from a program instead of calling it will not only print the error message but will also exit the program. This can be useful if the error in question is a major error that shouldn't have occured and the program can no longer progress. It also saves on code space, as 512 bytes is a rather tight squeeze for most programs.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov al, 0
  cmp al, 0 ; Compare AL with zero
  je error ; If AL is zero there is an error
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

find_file

Summary

Searches for a file in the file table and returns whether it was found or not.

In

BX : File to be searched for

Out

BX : Result [0=Not Equal Other=Equal]
CX : Sector file exists [0 to 1439]

Used

AX
BX
CX

Detailed Explanation

The find_file function mostly used with internal disk functions. The reason that it has been allowed to be used at program level is the fact that it is non-harmful and could be useful for a 'Are you sure you want to overwrite the file? (y/n)' feature of a program. The ability to know whether a file exists prior to trying to do disk operation with it could potentially stop your program from crashing. Please bare in mind that if a filename is repeated in the file table (dangerous) then it will return the first instance of the filename it comes accross.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov bx, filename ; Load the filename
  call find_file

  cmp bx, 0 ; Was the file found?
  je error ; If it wasn't then error
  ret ; Return to OS

  filename db 'test'

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

write_allocation_table

Summary

Places a filename in a position that corresponds to a given sector.

In

CX : Sector to write filename for [0 to 1439]
DX : Filename to be written into the file table

Out

-

Used

All

Detailed Explanation

This is yet another function that should be used with extreme care. Writing a filename for the wrong sector position could potentially wipe important OS data from the disk. This could lead to files being lost. Potentially you are able to carelessly wipe up to 312 files from your disk with slim chances of recovery. Without doubt, you should use find_file prior to using this function. If possible, please use write_file, as it's much safer and gives less opportunity to dangerous disk acts.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov bx, filename ; Load the filename
  call find_file

  cmp bx, 0 ; Was the file found?
  je error ; If it wasn't then error

  mov dx, bx
  call write_file_allocation_table

  ret ; Return to OS

  filename db 'test'

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

print_char

Summary

Prints a single character to the screen.

In

AL : Character to print

Out

-

Used

AX

Detailed Explanation

This function prints a single character to the screen from the register AL using teletype. This means that the next character's position is updated if there is a requirement to print multiple characters. This function also serves as part of the print_string function. If you only wish to print one character to the current position it is highly reccomended that you use this function over print_string which requires a zero terminator. Also this function doesn't change SI which may make it more attractive as a solution to a given problem.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov al, ' ' ; Print space
  call print_char
  mov al, ':' ; Print eyes
  call print_char
  mov al, ')' ; Print mouth
  call print_char
  ret ; Return to OS

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

remove_file

Summary

Allows for a given filename to deleted from the file allocation table. Note the contents remain until over-written.

In

BX : File to be removed

Out

BX : Result [0=Not Equal Other=Equal]

Used

All

Detailed Explanation

This function simply removes the filename (and therefore the refference to the file) from the file table. It is worth noting that the sector on the disk that contains the data is not wiped until written over, leaving for possibility for recovery if no other actions are taken after the deletion. To make sure that all the data is removed, simply write zeros to the data section of the file using write_file and then use remove_file to remove the filename from the file allocation table. In most cases using just this function is effective enough to achieve a file deletion. Once a file is removed from the file allocation table it's space is then freed for another file or program to overwrite it.

Example of Use


BITS 16 ; Program MUST be set to 16 bits

ORG 7168 ; Where the program is loaded, highly recommended not to be changed

... Function table here

main_program:
  mov bx, filename ; Load the filename
  call remove_file

  cmp bx, 0 ; Was the file removed?
  je error ; If it wasn't then error
  ret ; Return to OS

  filename db 'test'

times 510-($-$$)db 0 ; Pad remainder of program sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)

file:

Bugs

If you are using the OS on either real hardware or a virtual machine and encounter a bug, please feel free to submit a bug in the issues section, along with what the bug is and how we can repeat it. If you think the bug may be specific to your system please also give us the details of your hardware.

Bugs and suggestions can be submitted at http://www.heluxresearch.info.