Saturday, May 7, 2011

Useless OS 1.2 - x86 assembly

This is a bit of a technical entry, which by the way has nothing to do with LFScript at all...

For one of my projects, I'm learning a bit of x86 assembly.

Some initial goals were:
- Print a string of text on the screen
- Be able to use all 16 colours
- Position the text cursor
- Do NOT use BIOS interrupts (because it may eventually have to run in protected mode)

I came up with this:

%define  CODE_BASE  0x07C0

;; 'UselessOS 1.2' a.k.a. 'Print some coloured text, position a cursor and quit'
;; Created: 2011-05-06/2011-05-07
;; By: Marcel van den Boer
;;
;; Released in the PUBLIC DOMAIN
;;
;; Build and run with:
;;   $ nasm -f bin -o colortext.bin colortext.asm
;;   $ dd if=/dev/zero of=colortext.img bs=2880 count=512
;;   $ dd status=noxfer conv=notrunc if=colortext.bin of=colortext.img
;;   $ qemu -fda colortext.img
;;
;; Resources:
;; - http://mikeos.berlios.de/write-your-own-os.html
;; - http://www.jamesmolloy.co.uk/tutorial_html/
;; - http://wiki.osdev.org/Memory_Map_%28x86%29
;; - http://www.tarleton.edu/computerscience/documents/CS%20380/ ...
;;          ... Labs/Lab%203%20-%20Kernel.pdf

; Color definitions
%define  BLACK    0x0
%define  BLUE     0x1
%define  GREEN    0x2
%define  CYAN     0x3
%define  RED      0x4
%define  MAGENTA  0x5
%define  YELLOW   0x6
%define  WHITE    0x7

; Color brightness
%define  NORMAL   0x0
%define  BRIGHT   0x8

; Video memory facts
%define  COLOR       (BACKGROUND << 4 | FOREGROUND)
%define  CURSOR      ((CURSOR_Y * COLUMNS) + CURSOR_X)
%define  VIDEO_BASE  0xB800
%define  COLUMNS     80
%define  ROWS        25

; Text to print
%define  MESSAGE  'Useless OS 1.2 loaded... Goodbye!'
%define  FOREGROUND  (YELLOW | BRIGHT)
%define  BACKGROUND  (BLUE   | BRIGHT)

; Where to place the cursor
%define  CURSOR_X  79
%define  CURSOR_Y  24

init:
    ; Note: This section marked 'init' is not required for the remaining code
    ;       It's just here for my own reference
    cli

    ; Set up stack
    mov ax, 0x07E0
    mov ss, ax
    mov esp, (0x0007FFFF - 0x00007E00)

cursor:
    ; Lower byte
    mov byte al, 0x0F
    mov word dx, 0x03D4
    out dx, al

    mov byte al, CURSOR
    mov word dx, 0x03D5
    out dx, al

    ; Upper byte
    mov byte al, 0x0E
    mov word dx, 0x03D4
    out dx, al

    mov byte al, CURSOR >> 8
    mov word dx, 0x03D5
    out dx, al

start:
    ; Initialize registers which will be modified later (pointers)
    mov word si, 0
    mov word di, MSG_BASE

    ; Initialze registers with non-changing data
    mov word ax, CODE_BASE
    mov word bx, VIDEO_BASE

    ; Set character color
    mov byte ch, COLOR

fetch:
    ; Fetches the next character
    mov word ds, ax     ; Align with code
    mov byte cl, [di]   ; Fetch character
    inc di              ; Increment character index

print:
    ; Prints the most recently loaded character
    mov word ds, bx     ; Align with video memory
    mov word [si], cx   ; Print character
    add si, 2           ; Increment video index

branch:
    ; Fetch the next character if the end of the string has not been reached
    cmp cl, 0
    jne fetch

    ; Otherwise fill the screen with the last (null) character
    cmp si, (COLUMNS * ROWS * 2)
    jl print

end:
    ; Finally, wait forever
    jmp $

data:
    MSG_BASE db MESSAGE, 0

padding:
    ; Required to be recognized as a boot sector
    times 510-($-$$) db 0
    dw 0xAA55


(It is has version number 1.2 because: "1.0" printed the string and cleared the screen, "1.1" added colour and "1.2" added cursor management. Though every version was made in the last two days.)

Enjoy.

No comments:

Post a Comment