Itt egy egyszerű program (SjASM PC-s Z80 assemblerrel fordítható), amely karakteres képernyőt állít be, és kiír egy üzenetet, majd a SPACE billentyűre vár, aminek a lenyomásakor kilép:
org 00f0h
defw 0500h, prg_end - 0100h, 0, 0, 0, 0, 0, 0
macro exos n
rst 30h
defb n
endm
dispw equ 40
disph equ 25
main:
di
ld sp, 0100h
ld a, 0ffh
out (0b2h), a
ld hl, reset
ld (0bff8h), hl
ei
ld bc, 1:27 ; BORD_VID
ld d, 00100000b
exos 16
halt
halt
call mem_alloc
call lpt_init
ei
ld hl, testmsg
ld de, 1:2
call printstr
.l1: ld a, 8
di
out (0b5h), a
in a, (0b5h)
ei
and 40h
jr nz, .l1
jp reset
mem_alloc:
.l1: exos 24
or a
jp nz, reset
ld a, c
cp 0fch
jr c, .l1
ld l, c
out (0b3h), a
.l2: dec l
ret z
ld c, l
exos 25
jr .l2
lpt_init:
di
ld hl, (0bff4h)
set 7, h
res 6, h
set 2, l
set 1, l
ld a, (hl)
inc l
ld h, (hl)
ld l, a
ld (lpbdata + 6), hl
ld de, lpt_begin
ld hl, disp_begin & 3fffh
in a, (0b3h)
rrca
rrca
and 0c0h
push af
or h
ld h, a
ld a, disph
.l1: ld (lpbdata + 4), hl
ld bc, dispw
add hl, bc
push hl
ld hl, lpbdata
ld c, 16
ldir
pop hl
dec a
jr nz, .l1
ld hl, lptborderblank
ld bc, lptborderblank_end - lptborderblank
ldir
ld hl, disp_begin
ld de, disp_begin + 1
ld bc, disph * dispw - 1
ld (hl), ' '
ldir
pop af
or high (lpt_begin & 3fffh)
ld l, low lpt_begin
ld h, a
setlptaddr:
ld a, 1ch
.l1: add hl, hl
rla
jr nc, .l1
ld c, 82h
out (c), h
out (83h), a
ret
printstr:
push hl
push de
ld e, d ; D = Y
ld d, 0
ld a, dispw
call multDEbyAtoHL
ld bc, disp_begin
pop de ; E = X
ld d, 0
add hl, bc
add hl, de
pop de
.l1: ld a, (de)
or a
ret z
ld (hl), a
inc de
inc hl
jr .l1
multDEbyAtoHL:
ld hl, 0
add a, a
jr nc, .l1
ld l, e
ld h, d
add hl, hl
.l1: add a, a
jr nc, .l2
add hl, de
.l2: add hl, hl
add a, a
jr nc, .l3
add hl, de
.l3: add hl, hl
add a, a
jr nc, .l4
add hl, de
.l4: add hl, hl
add a, a
jr nc, .l5
add hl, de
.l5: add hl, hl
add a, a
jr nc, .l6
add hl, de
.l6: add hl, hl
add a, a
jr nc, .l7
add hl, de
.l7: add hl, hl
ret p
add hl, de
ret
reset:
di
ld sp, 4000h
ld a, 0ffh
out (0b2h), a
ld hl, reset
ld (0bff8h), hl
ld bc, 1:27 ; BORD_VID
ld d, 00h
exos 16
ld c, 40h
exos 0
ld a, 01h
out (0b3h), a
ld a, 6
jp 0c00dh
lpt_begin equ 0f800h
disp_begin equ 0c000h
lpbdata:
defb 256 - 9, 08h, (63 - dispw) / 2, (63 + dispw) / 2
defw 0, 0
defb 00000000b, 10010010b, 00000000b, 01001001b
defb 0, 0, 0, 0
tborder equ (294 / 2) - (disph * 9 / 2)
bborder equ (294 / 2) - ((disph * 9 + 1) / 2)
lptborderblank:
defb 256 - bborder, 82h, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - 3, 00h, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - 2, 00h, 6, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - 1, 00h, 63, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - 3, 00h, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - 9, 02h, 6, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
defb 256 - tborder, 03h, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
lptborderblank_end:
testmsg:
defm "Enterprise"
defb 0
prg_end:
A program működésének a magyarázata:
- először beállítja a veremmutatót, minden EXOS 5 fejlécű programot ezzel kell kezdeni, mert egyébként a veremmutató érvénytelen, és a program az első megszakításnál lefagy
- belapozza a rendszerszegmenst (FFh) a 2. lapra, a program futása közben a 8000h-BFFFh területen mindig ez lesz látható
- ha a program hosszabb lenne egy szegmensnél, akkor a második és a harmadik szegmens száma a BFFDh és BFFEh címeken lenne található (a rendszer nem lapozza be automatikusan)
- beállítja a melegindítási címet (BFF8h), hogy a reset gomb lenyomására ne történjen hidegindítás
- EXOS változó írása (EXOS 16) hívással beállítja a keretszínt
- lefoglal egy video szegmenst az LPT-nek és a karakteres képernyőnek
- létrehozza az LPT-t, törli a képernyőt, és beállítja az LPT címét a 82h/83h I/O portokon
- kiír egy üzenetet a képernyő bal felső sarkába
- a Space billentyű lenyomására vár (B5h port figyelése), és ha ez megtörténik, akkor a melegindítási rutinra ugrik
A memóriafoglalás:
- ciklusban szegmenst foglal (EXOS 24) addig, amíg a száma FCh vagy nagyobb lesz (video szegmens); az EXOS a szegmenseket növekvő sorrendben foglalja le, tehát az esetleges video szegmensek csak minden más szegmens lefoglalása után kerülnek sorra
- ha ez nem sikerül, akkor a melegindítási rutinra ugrik
- egyébként a 3. lapra belapozza a video szegmenst, és minden más szegmenst felszabadít (EXOS 25)
A képernyő inicializálása:
- az EXOS LPT címét a rendszerszegmensről kiolvassa (BFF4h), és ehhez képest +6 byte eltolással megtalálható az LPT-be írandó karakterkészlet cím
- létrehozza az LPT-t (a karaktersoroknak megfelelő számú LPB + a keretek és a függőleges visszafutás)
- a címeket NICK címekre konvertálja a szegmensszámnak megfelelően
- feltölti a képernyőt szóköz karakterekkel
- végül a 82h és 83h I/O portokon beállítja az LPT címét
Szöveg írása a képernyőre (E = X pozíció, D = Y pozíció, HL = szöveg címe, a szöveg C formátumú, azaz 00h karakter jelzi a végét):
- kiszámítja a képernyő memória kezdőcímet, ami C000h + (D * szélesség) + E
- a szöveget 00h karakterig másolja (nem ellenőrzi, hogy nem történik-e a képernyő területén kívülre írás)
Melegindítás:
- beállítja a veremmutatót és belapozza a rendszerszegmenst a 2. lapra
- átmenetileg visszaállítja a címet, hogy a reset gomb esetleges nagyon gyors újabb lenyomása (pl. érintkezési hiba miatt) ne eredményezzen hidegindítást (ez nem biztos, hogy a gyakorlatban hasznos)
- visszaállítja a korábban EXOS változó írásával beállított keretszínt feketére
- felszabadít minden lefoglalt memóriát (EXOS 0 C=40h jelzőbitekkel)
- a 01h:C00Dh címre ugrik A=6 kóddal, ami a rendszer indításakor látható villogó Enterprise logót jeleníti meg (a RAM-ban található bővítők, RAMDISK, és EXOS változók nem vesznek el)
- az LPT visszaállításával nem foglalkozik, mert azt a rendszer egyébként is megteszi, ahogy az esetleges csatornák bezárását is; csak a Reset gomb lenyomásakor szintén automatikusan helyreállítja a rendszer a 0030h-005Fh területet is