Diky za clanek.
Pokusil jsem se prepsat program do "Forthu" a zkompilovat.
ZX_CONSTANT
ORG 0x8000
INIT(60000)
PRINT_Z({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"})
STOP
Prvni slovo "aktivuje" konstanty typu ZX_...
INIT a STOP obaluji program a nastavuji zasobnik navratovych adres a vraci registry pro basic.
Program musi uchovavat HL protoze je v nem TOS (top of stack).
DE, protoze je v nem NOS (next of stack).
Dalsi cell je v (SP) atd.
HL' protoze obsahuje index RAS (return adres stack).
Ostatni se da pouzit volne.
PRINT_Z je psane trosku jinak, protoze je delane jako funkce, za to o trosicku rychleji, protoze v kazdem cyklu neresi ret z a neztraci 5 taktu.
Mimochodem, retezce ukoncene nulou jsou podle nekterych programatoru ve Forthu spatne reseni. To je trochu flamewar tema. Ja si myslim, ze pokud se nesnazime s nema nejak pracovat a jen je tiskneme tak jsou v pohode.
dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'ZX_CONSTANT ORG 0x8000 INIT(60000) PRINT_Z({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"}) STOP'
ZX_EOL EQU 0x0D ; zx_constant end of line
ZX_INK EQU 0x10 ; zx_constant colour
ZX_PAPER EQU 0x11 ; zx_constant colour
ZX_FLASH EQU 0x12 ; zx_constant 0 or 1
ZX_BRIGHT EQU 0x13 ; zx_constant 0 or 1
ZX_INVERSE EQU 0x14 ; zx_constant 0 or 1
ZX_OVER EQU 0x15 ; zx_constant 0 or 1
ZX_AT EQU 0x16 ; zx_constant Y,X
ZX_TAB EQU 0x17 ; zx_constant # spaces
ZX_BLACK EQU %000 ; zx_constant
ZX_BLUE EQU %001 ; zx_constant
ZX_RED EQU %010 ; zx_constant
ZX_MAGENTA EQU %011 ; zx_constant
ZX_GREEN EQU %100 ; zx_constant
ZX_CYAN EQU %101 ; zx_constant
ZX_YELLOW EQU %110 ; zx_constant
ZX_WHITE EQU %111 ; zx_constant
ORG 0x8000
; === b e g i n ===
ld (Stop+1), SP ; 4:20 init storing the original SP value when the "bye" word is used
ld L, 0x1A ; 2:7 init Upper screen
call 0x1605 ; 3:17 init Open channel
ld HL, 0xEA60 ; 3:10 init Return address stack = 60000
exx ; 1:4 init
ld BC, string101 ; 3:10 print_z Address of null-terminated string101
call PRINT_STRING_Z ; 3:17 print_z
Stop: ; stop
ld SP, 0x0000 ; 3:10 stop restoring the original SP value when the "bye" word is used
ld HL, 0x2758 ; 3:10 stop
exx ; 1:4 stop
ret ; 1:10 stop
; ===== e n d =====
;------------------------------------------------------------------------------
; Print C-style stringZ
; In: BC = addr
; Out: BC = addr zero + 1
rst 0x10 ; 1:11 print_string_z putchar with ZX 48K ROM in, this will print char in A
PRINT_STRING_Z: ; print_string_z
ld A,(BC) ; 1:7 print_string_z
inc BC ; 1:6 print_string_z
or A ; 1:4 print_string_z
jp nz, $-4 ; 3:10 print_string_z
ret ; 1:10 print_string_z
STRING_SECTION:
string101:
db ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!", 0x00
size101 EQU $ - string101
; seconds: 0 ;[35:167]
Dalsi varianta je pouzit retezec, ktery bude ukoncen tak ze posledni bajt bude mit 7. bit nastaveny na 1, takze se usetri bajt na retezec. Pouzije se slovo PRINT_I.
dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'ZX_CONSTANT ORG 0x8000 INIT(60000) PRINT_I({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"}) STOP'
ZX_EOL EQU 0x0D ; zx_constant end of line
ZX_INK EQU 0x10 ; zx_constant colour
ZX_PAPER EQU 0x11 ; zx_constant colour
ZX_FLASH EQU 0x12 ; zx_constant 0 or 1
ZX_BRIGHT EQU 0x13 ; zx_constant 0 or 1
ZX_INVERSE EQU 0x14 ; zx_constant 0 or 1
ZX_OVER EQU 0x15 ; zx_constant 0 or 1
ZX_AT EQU 0x16 ; zx_constant Y,X
ZX_TAB EQU 0x17 ; zx_constant # spaces
ZX_BLACK EQU %000 ; zx_constant
ZX_BLUE EQU %001 ; zx_constant
ZX_RED EQU %010 ; zx_constant
ZX_MAGENTA EQU %011 ; zx_constant
ZX_GREEN EQU %100 ; zx_constant
ZX_CYAN EQU %101 ; zx_constant
ZX_YELLOW EQU %110 ; zx_constant
ZX_WHITE EQU %111 ; zx_constant
ORG 0x8000
; === b e g i n ===
ld (Stop+1), SP ; 4:20 init storing the original SP value when the "bye" word is used
ld L, 0x1A ; 2:7 init Upper screen
call 0x1605 ; 3:17 init Open channel
ld HL, 0xEA60 ; 3:10 init Return address stack = 60000
exx ; 1:4 init
ld BC, string101 ; 3:10 print_i Address of string101 ending with inverted most significant bit
call PRINT_STRING_I ; 3:17 print_i
Stop: ; stop
ld SP, 0x0000 ; 3:10 stop restoring the original SP value when the "bye" word is used
ld HL, 0x2758 ; 3:10 stop
exx ; 1:4 stop
ret ; 1:10 stop
; ===== e n d =====
;------------------------------------------------------------------------------
; Print string ending with inverted most significant bit
; In: BC = addr string_imsb
; Out: BC = addr last_char + 1
rst 0x10 ; 1:11 print_string_i putchar with ZX 48K ROM in, this will print char in A
PRINT_STRING_I: ; print_string_i
ld A,(BC) ; 1:7 print_string_i
inc BC ; 1:6 print_string_i
or A ; 1:4 print_string_i
jp p, $-4 ; 3:10 print_string_i
and 0x7f ; 2:7 print_string_i
rst 0x10 ; 1:11 print_string_i putchar with ZX 48K ROM in, this will print char in A
ret ; 1:10 print_string_i
STRING_SECTION:
string101:
db ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!" + 0x80
size101 EQU $ - string101
; seconds: 0 ;[38:185]
Posledni varianta je zakladni PRINT, ktere vola ROM rutinu pro tisk retezce, ktera vyzaduje pokazde nastavit delku tisknuteho retezce, takze opakovane volani zabira nejvic mista.
dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ls -l root_str*.bin -rw-rw-r-- 1 dworkin dworkin 50 Feb 21 02:59 root_str.bin -rw-rw-r-- 1 dworkin dworkin 56 Feb 21 02:58 root_stri.bin -rw-rw-r-- 1 dworkin dworkin 54 Feb 21 02:58 root_strz.bin dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$
PS: Preklad je napsan v pouhem makru (M4) a vsechny PRINT se snazi najit shodne retezce pokud se pouziji, aby se ulozil jen jeden. Proto ty slova vypadaji "trosku" jinak nez ve Forthu.
PRINT({"Retezec"}) misto ." Retezec"
PUSH(10) misto 10
ADD misto +