V kapitole 13. se popisuje samomodifikujici se kod (mimochodem, odkaz vede na jeste nenahrany soubor) a me v hlave hned vyskakuji vykricniky, ze zapominame vratit rutinu do puvodni hodnoty. Ted to funguje jen proto, ze hlavni smycka je nekonecna. Jinak pri opakovanem volani si to bude drzet ten nop...
Osobne bych to napsal tak, ze tu prepisovaci cast bych dal pred tu rutinu a rutina by se pak dala volat na puvodni odkaz, s tim ze je uz "zadratovana" na nejakou hodnotu (vyhoda oproti "rom" variante s parametrem navic je, ze neztracime rychlost a uvolnime si jeden registr, za cenu toho ze to predratovani je drazsi) a nebo tesne pred ni s dalsim parametrem, ktery by ji prvne nastavil.
Pokud menime jen jeden bajt tak bych volil instrukci "ld (adresa),A ; 3:13"
A nacteni "kodu instukce" do A je u nop snadne pres xor A a u zbyvajicich staci zjistit jak vypada prvni bajt instrukce "ld A,n".
Kod bude pak o jeden bajt delsi, a pokud nam to vadi tak to muzeme jeste zkratit tak ze to opakovane volani dame primo do te rutiny. Tim usetrime 3 bajty.
fill_in_screen:
; Vyplnění obrazovky snadno rozpoznatelným vzorkem - ASCII tabulkami
;
; vstupy:
; žádné
ld de, SCREEN_ADR ; 3:10 adresa pro vykreslení prvního bloku znaků
db 0x3E ; 2:7 ld A, n
cpl ; ld A, cpl
call draw_ascii_table_init; 3:17 vykreslení 96 znaků
xor A ; 1:4 ld A, nop
call draw_ascii_table_init; 3:17 vykreslení 96 znaků
ret ; 1:10 návrat z podprogramu
draw_ascii_table_init:
ld (inv_instruction_adr),A; 3:13 adresa bajtu v paměti, který budeme modifikovat
draw_ascii_table_2x:
call draw_ascii_table ; 3:17 vykreslení 2*96 znaků
draw_ascii_table:
...
Jeste lepsi by asi bylo:
fill_in_screen:
; Vyplnění obrazovky snadno rozpoznatelným vzorkem - ASCII tabulkami
;
; vstupy:
; žádné
ld de, SCREEN_ADR ; 3:10 adresa pro vykreslení prvního bloku znaků
call draw_ascii_table_inv ; 3:17 vykreslení 2*96 znaků
xor A ; 1:4 ld A, nop
call draw_ascii_table_init; 3:17 vykreslení 2*96 znaků
ret ; 1:10 návrat z podprogramu
draw_ascii_table_inv:
db 0x3E ; 2:7 ld A, n
cpl ; ld A, cpl
draw_ascii_table_init:
ld (inv_instruction_adr),A; 3:13 adresa bajtu v paměti, který budeme modifikovat
call draw_ascii_table ; 3:17 vykreslení 96 znaků
draw_ascii_table:
Pro zmenu 1 bajtu mas pro zapis jen 3 moznosti:
db 0x3E, 0x2F ; 2:7 ld A,cpl
db 0x3E ; 2:7 ld A,cpl cpl
ld A, 0x2F ; 2:7 ld A,cpl
a "cpl" je tady promenna, takze jsem zvolil tu, kde se to tabulky kodu nemusis divat pokud si jednou zapamatujes to "ld A,n".
Pro 2 bajty je nejlepsi pouzit HL, jen si dat pozor ze Z80 ma "ld (adr),HL" 2x. Jednu tribajtovou za 16 taktu a druhou, jakou maji ostatni registrove pary DE a BC, ctyrbajtovou za 20 taktu.