I wanted something a little more elaborate that can be defined within the output string for special formatting in the way of colours and tabulation. Essentially this is similar to function 0x13 of int 0x10, with a few perks
Here is an example of the string would be defined. This displays a double lined box on top quarter of screen in bright white with the text "STORK-OS" inside it
022104 SignOn db 2, 33, 4 ; Set intial position
030F db 3, 15
C9 db 0xc9 ; Topleft double line
010ACD db 1, 10, 0xcd ; 11 double horizontal lines
BB db 0xbb
0ABA20 db 10, 0xba, ' '
038653544F524B2D4F- db 3, 0x86, 'STORK-OS', 3, 15
53030F
20BA0A db ' ', 0xba, 10
C8 db 0xc8
010ACD db 1, 10, 0xcd
BC db 0xbc
0307 db 3, 7 ; Change back to white on black
00 db 0 ; SignOn terminus
02 21 04 03 0F C9 01 0A CD BB 0A BA 20 03 86 53
54 4F 52 4B 2D 4F 53 03 0F 20 BA 0A C8 01 0A CD
BC 03 07 00
; --------------------------------------------------------------------------------------------
; Display NULL termianted ASCII string on console, evaluating special characters less than
; space.
; ENTRY: SI = Pointer to ASCII string
; LEAVE: SI = Pointer to next avaliable string if applicable.
; CONTROL CHARACTERS:
; (1) db 1, 24, 48 Will repeat 48 '0' 24 times
; (2) db 2, 33, 8 Position cursor to Column 33 / Line 8
; or
; db 2
; dw 0x821
; (3) db 3, 7 Change color to white on black
; (4) db 10 Line feed and carriage return only to DL
; (5) db 13 Line feed and carriage return to leftmost position
; ____________________________________________________________________________________________
VIDEO equ 16 ; Video services interrupt
SET_CURSOR_POS equ 2 ; BIOS Set cursor position
GET_CURSOR_POS equ 3
WRITE_CATTR equ 9 ; Write character and attribute
READ_CATTR equ 8 ; Read character and attribute
ShowS push cx
push dx ; Preserve registers used by procedure
; Parameters that are to be different than default need be specified in output string.
mov ah, GET_CURSOR_POS ; Get current position of cursor
int VIDEO
push dx ; Save local variable
mov cx, 1 ; Default number of characters to write
mov ah, READ_CATTR
int VIDEO
mov bl, ah ; Consider this to be default
; Cycle through each character until terminator and do special for characters less
; than space.
.Next lodsb
cmp al, ' '
jb .Fnc1 ; Anything less than space is a function char.
; BIOS serviced to write character and attribute at position advancing cursor to
; next position
mov ah, WRITE_CATTR
int VIDEO
add dl, cl ; Bump in case repeat count
mov cl, 1 ; Re-set to default
mov ah, SET_CURSOR_POS
int VIDEO
jmp .Next
; Characters 1 - 31 are treated as special case and unconventional interpretation
; of carrige returns (0AH) and line feeds (0DH).
; (1): Repeat character to specified number of times.
.Fnc1 cmp al, 1 ; Are we repeating a character
jnz .Fnc2
lodsb ; Get repeat count
mov cl, al ; store in CL
jmp .Next
; (2) New horizontal/vertical position of cursor. DL will be consider the new default
; whenever line feed is encountered
.Fnc2 cmp al, 2
jnz .Fnc3
pop ax ; Waste old position
lodsw ; Read next two bytes
mov dx, ax ; Move where required for BIOS call
push dx ; Save this new position
jmp .Fnc5 - 6 ; Position cursor
; (3) Change color. Next byte denotes new color for susequent characters
.Fnc3 cmp al, 3
jnz .Fnc4
lodsb ; Get color
mov bl, al ; Move into BL
jmp .Next
; (4) Line Feed positions cursor to last know coordintes in DX
.Fnc4 cmp al, 10
jnz .Fnc5
pop dx
inc dh ; Force line feed
push dx
mov ah, SET_CURSOR_POS
int VIDEO
jmp .Next
; Carriage return moves cursor to left most position on next line. This does not
; change margin. Subsequent line-feeds will use DL as desired position
.Fnc5 cmp al, 13 ; Carriage return
jnz .FncX
inc dh
mov dl, 0
jmp .Fnc5 - 6
.FncX cmp al, 0 ; We are done, last character of string
jz .Done ; Exit if terminator
jmp .Next ; All other chars 1 - 31 ignored.
; Epiloge
.Done add sp, 2 ; Waste local
pop dx
pop cx
ret ; ESI points to next string if applicable.
This is done in 16 bit as it is part of my MBR and second stage loader