Kod maszynowy Z80, 8 6 bajtów *
<8ww8>
* Przyjmuje określone warunki, wchodząc z Amstrad BASIC
< INC A // A=A+1
8w JR C, #77 ## C is unset unless A has overflowed, does nothing
w LD (HL), A // Saves A to memory location in HL (randomly initialised)
8> JR C, #3E ## C is still unset, does nothing
A
początkowo wynosi 0 po wprowadzeniu z BASIC. Przyrosty A
n razy, a następnie zapisuje n razy do tej samej lokalizacji w pamięci (która jest ustawiona przez BASIC na nieco losową lokalizację)! Operacja JR
Jump Relative nigdy nie robi nic, ponieważ C
flaga jest zawsze rozbrojona, dlatego służy do „komentowania” następującego bajtu! Ta wersja nieco oszukuje, zakładając pewne warunki wejścia, a mianowicie wejście z gwarancji BASIC, która A
zawsze wynosi 0. Lokalizacja (HL)
nie jest gwarantowana jako bezpieczna, aw rzeczywistości jest to prawdopodobnie niebezpieczne miejsce. Poniższy kod jest znacznie bardziej niezawodny, dlatego jest o wiele dłuższy.
Kod maszynowy Z80, 30 bajtów
Jako ASCII:
o!.ww.!>A=o>{))((}<o=A<!.ww.!o
Zasadniczo pierwsza połowa gwarantuje utworzenie wartości zerowej, a druga połowa zwiększa ją i zapisuje w pamięci. W rozszerzonej wersji poniżej ##
oznacza kod, który nie służy żadnemu celowi w jego połowie lustra.
o LD L, A ##
!.w LD HL, #772E // Load specific address to not corrupt random memory!
w LD (HL), A ## Save random contents of A to memory
.! LD L, #21 ##
>A LD A, #41 // A=#41
= DEC A // A=#40
o LD L, A // L=#40
>{ LD A, #7B ##
) ADD HL, HL // HL=#EE80
) ADD HL, HL // HL=#DD00. L=#00 at this point
(( JR Z, #28 ##
} LD A, L // A=L
< INC A // A=L+1
o LD L, A // L=L+1
= DEC A // A=L
A LD B, C ##
< INC A // A=L+1
!.w LD HL, #772E // Load address back into HL
w LD (HL), A // Save contents of A to memory
.! LD L, #21 ##
o LD L, A // L=A
Podział dozwolonych instrukcji:
n op description
-- ---- -----------
28 LD LoaD 8-bit or 16-bit register
3 DEC DECrement 8-bit or 16-bit register
1 INC INCrement 8-bit or 16-bit register
1 ADD ADD 8-bit or 16-bit register
Available but useless instructions:
3 JR Jump Relative to signed 8-bit offset
1 DAA Decimal Adjust Accumulator (treats the A register as two decimal digits
instead of two hexadecimal digits and adjusts it if necessary)
1 CPL 1s ComPLement A
1 HALT HALT the CPU until an interrupt is received
Spośród 39 dozwolonych instrukcji 28 to operacje ładowania (blok od 0x40 do 0x7F to LD
instrukcje jednobajtowe ), z których większość tutaj nie pomaga! Jedyne dozwolone ładowanie do pamięci jest nadal dozwolone, LD (HL), A
co oznacza, że muszę zapisać wartość w A
. Ponieważ A
jest to jedyny rejestr z dozwoloną INC
instrukcją, jest to całkiem przydatne!
Nie mogę załadować A
z 0x00, ponieważ ASCII 0x00 nie jest dozwolonym znakiem! Wszystkie dostępne wartości są dalekie od 0, a wszystkie instrukcje matematyczne i logiczne zostały niedozwolone! Z wyjątkiem ... Nadal mogę ADD HL, HL
, dodaj 16-bit HL
do siebie! Oprócz bezpośredniego ładowania wartości (tutaj nie ma zastosowania!), INKrementacji A
i DECrementacji A
, L
lub HL
to jest jedyny sposób na zmianę wartości rejestru! W rzeczywistości jest jedna specjalistyczna instrukcja, która może być pomocna w pierwszej połowie, ale kłopot z obejściem w drugiej połowie, i instrukcja uzupełniająca, która jest prawie bezużyteczna tutaj i zajmuje tylko miejsce.
Znalazłem więc najbliższą wartość 0, którą mogłem: 0x41. Jak to jest bliskie zeru? W systemie binarnym jest to 0x01000001. Więc zmniejszam, ładuję L
i robię ADD HL, HL
dwa razy! L
ma teraz zero, do którego ładuję ponownie A
! Niestety kod ASCII dla ADD HL, HL
jest, )
więc muszę teraz użyć (
dwa razy. Na szczęście (
jest JR Z, e
, gdzie e
jest następny bajt. Więc pożera drugi bajt i muszę tylko upewnić się, że nic nie zrobi, uważając na Z
flagę! Ostatnią instrukcją, która wpłynęła na Z
flagę, była DEC A
(sprzeczna z intuicją, ADD HL, HL
nie zmienia jej), a ponieważ wiem, że A
w tym momencie była to 0x40, jest pewna, że Z
nie jest ustawiona.
Pierwsza instrukcja w drugiej połowie JR Z, #28
nic nie zrobi przez pierwsze 255 razy, ponieważ flagę Z można ustawić tylko wtedy, gdy A przepełniło się z 255 do 0. Następnie dane wyjściowe będą błędne, jednak ponieważ i tak zapisuje tylko wartości 8-bitowe nie powinno mieć znaczenia. Kod nie powinien być rozszerzany więcej niż 255 razy.
Kod musi zostać wykonany jako fragment kodu, ponieważ wszystkie dostępne sposoby czystego powrotu zostały niedozwolone. Wszystkie instrukcje RETurn są powyżej 0x80, a kilka dozwolonych operacji Jump może przeskoczyć tylko do dodatniego przesunięcia, ponieważ wszystkie 8-bitowe wartości ujemne zostały również niedozwolone!
#
jest to również jego własna relacja, ale masz rację, nie w konsolach.