ZeX/OS

Developer's book for v0.4.1
                             writed by ZeXx86




1. System calls
2. Assembler tutorial
3. C tutorial
4. Glibc
5. Filesystem driver tutorial




1.       System calls

In computing, a system call is the mechanism used by an application program to request service from the operating system.
ZeX/OS uses this implementation on x86 where the system call number is placed in the EAX register before interrupt 0x80 is executed.
 
Name Description %eax %ebx %ecx %edx $0x9000
sys_exit Exit app at call point 1 int - - -
sys_getch Get a pressed character 2 - - - unsigned char
sys_sleep Wait until time (in sec) pass 3 unsigned int - - -
sys_putch Print a character on the screen 4 char - - -
sys_color Set color to next text 5 unsigned int unsigned int - -
sys_cls Clear a screen 6 - - - -
sys_getkey Get a keycode 7 - - - unsigned char
sys_gotoxy Move a cursor to another place 8 unsigned int unsigned int - -

2.       Assembler tutorial  

For people interested in assembler programming for ZeX/OS is small example of source code for nasm compiler.

>File start.asm<
[BITS 32]              ; first, we need tell to compiler, that we want work in 32bit mode
global _start            ; entry point
_start:                     ; define of _start function
    jmp main             ; jump to main function


cls:                           ; clear screen function
    mov eax, 6           ; system call number 6
    int 0x80                ; call interrupt for system call - 0x80
    ret                        ; end of cls function

putch:                        ; print chatacter on the screen
    mov ebx, '.'            ; we want print character '.'
    mov eax, 4             ; this is system call number 6
    int 0x80                 ; system call interrupt
    ret                         ; end of putch function


main:                       ; main function
    call cls                 ; this clear a screen

    mov cl, 10           ; set number 10 to register cl
nav:
    dec cl                  ; decrease one number from register cl
    call putch             ; print charecter '.' on the screen
    jnz nav                 ; will be jump to nav until cl is'nt zero

    ret                        ; here ends our program

For compile, you need nasm compiler and ld for link object.
nasm -f elf -ostart.o start.asm
ld -m elf_i386 -s -omyapp start.o


3.      C tutorial

For people interested in C programming language for ZeX/OS is small example of source code for gcc compiler.

>File main.c<
#include <stdio.h>

int main ()
{
        puts ("Hello world !");
        putch ('\n');

        int a = 8;
        int b = 5;
        int result = a + b;

        printf ("a + b = result\n%d + %d = %d", a, b, result);

        return 1;
}



4.      Glibc

The GNU C Library, commonly known as glibc, is the C standard library released by the GNU Project. Originally written by the Free Software Foundation (FSF) for the GNU operating system, the library's development has been overseen by a committee since 2001, with Ulrich Drepper as the lead contributor and maintainer.

This version of glibc is completly written by ZeXx86 for light compatibility with GNU programs written in C programming languague on ZeX/OS.

Include layout

#include <stdio.h>
void putch (char c); // Print a character on the screen
void puts (unsigned char *text); // Print a string
void printf (const char *fmt, ...); // Same as puts but with arguments
void cls (); // Clear a screen
unsigned char getch (); // Get a pressed character
unsigned char getkey (); // Get a keycode
void gotoxy (int x, int y); // Move a cursor to another place
void setcolor (int t, int f); // Set color to next text
int sprintf(char *buffer, const char *fmt, ...); // Copy string fmt with args to buffer

#include <stdlib.h>
void *malloc (size_t size); // Allocate block of memory
void *realloc (void *blk, size_t size); // Allocate next block of memory
void free (void *blk); // Free a block of allocated memory
void exit (); // Exit app at call point

#include <unistd.h>
unsigned int sleep (unsigned int) // Wait until time (in sec) pass

#include <string.h>
void *memcpy (void *dst_ptr, const void *src_ptr, size_t count); // Copy block of memory
void *memsetw (void *dst, int val, size_t count); // Put to memory block of some character
void *memset (void *dst, int val, size_t count); // Put to memory block of some character
size_t strlen (const char *str); // Get length of string
char *strcpy (char *to, const char *from); // Copy string
char *strncpy (char *s1, const char *s2, size_t n); // Copy string with declared length
char *strcat (char *s, const char *add); // Add string to another string
int strcmp (const char *cs, const char *ct); // Compare two strings
int strncmp (const char *cs, const char *ct, size_t count); // Compare two strings with defined length
char *strdup (const char *s); // Alloc new block of memory for string s

#include <x86.h>
unsigned inportb (unsigned short port); // Get byte from port
void outportb (unsigned port, unsigned val); // Set byte on port
unsigned disable (void); // Disable interrupts
void enable (void); // Enable interrupts
void enable_irq (unsigned short irq_num); // Enable irq
void disable_irq (unsigned short irq_num); // Disable irq


5.      Filesystem driver tutorial

ZeX/OS is developed for no one filesystem, so it supports fs handlers, disk handlers, etc..
As you should see, in this short tutorial, you will learn how it works


Base function to read/write data over disk
/* partition_t is defined in partition.h, addr is 28bit (32) address of block, easy addr = 1 is block 1, etc .. buffer is classical char * for getting data after calling */
int lba28_drive_read (partition_t *p, unsigned int addr, unsigned char *buffer);

/* same, but for writing data from buffer */
int lba28_drive_write (partition_t *p, unsigned char addr, unsigned char *buffer);

/* when you want device metod, use this */
dev_t *dev = dev_findbypartition (p);

if (!dev) // check for existing device
    return 0;

if (!dev->handler (DEV_ACT_READ, p, block, more, n))
    return 0; // error ?

/* handler is defined in drive.c and function shows like this */
bool ide_acthandler (unsigned act, partition_t *p, char *block, char *more, int n)


myfs.c
#include <partition.h>
#include <system.h>
#include <string.h>
#include <dev.h>
#include <fs.h>


bool myfs_read_dir (partition_t *p, char *block, int n)
{
           /* its your space for create function, which read directory and put it to dir[] structure,
               dir is defined in system.h include */
           return 1;
}

/*
           ...
*/

/** MyFS handler for handling disk operations
 *  act - action; arg - argument; block - chunk of data for input/output; n - number of block; l - lenght of  output
 */
bool myfs_handler (unsigned act, unsigned arg, char *block, unsigned n, unsigned long l)
{
    switch (act) {
        case FS_ACT_INIT:
        {
            /* something, what you need to initialize, e.g. memory stacks */
            return 1;
        }
        break;
        case FS_ACT_READ:
        {
            switch (arg) {
                case FS_ARG_FILE:
                {
                    myfs_read_file (curr_part, n); // this have to read file at n block on partition_t *curr_part
                    /* ... some stuff for get new data on char *block */
                    return 1;
                }
                break;
                case FS_ARG_DIR:
                {
                    myfs_read_dir (curr_part, n); // this is your new fs function too
                    /* same as in file operation */
                    return 1;
                }
                break;
            }

            return 0;
        }
        break;
        case FS_ACT_WRITE:
        {
            /* Yeah, you want to probably create FS with write support, you can do it here */
            return 1;
        }
    }

    return 0;
}