Код машини Z80, 8 6 байт *
<8ww8>
* Передбачає певні умови, ввівши з 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
початково 0, коли вводиться з BASIC. Він збільшується A
n разів, потім записує його n разів у те саме місце пам’яті (яке встановлюється злегка випадковим розташуванням BASIC)! Операція JR
Jump Relative ніколи нічого не робить, оскільки C
прапор завжди не встановлений, тому використовується для "коментування" наступного байта! Ця версія трохи обманює, якщо передбачити певні умови в'їзду, а саме вхід із гарантій BASIC, який A
завжди дорівнює 0. Місцезнаходження (HL)
не гарантується як безпечне, і насправді це, мабуть, небезпечне місце. Наведений нижче код набагато надійніший, тому він настільки довший.
Код машини Z80, 30 байт
Як ASCII:
o!.ww.!>A=o>{))((}<o=A<!.ww.!o
В основному, перша половина гарантує створення нульового значення, а друга половина збільшує його і записує його в пам'ять. У розгорнутій версії нижче ##
позначається код, який не виконує жодної мети на своїй половині дзеркала.
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
Розбивка дозволених інструкцій:
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
З 39 дозволених інструкцій, 28 - це операції з завантаження (блок від 0x40 до 0x7F - це всі однобайтові LD
інструкції), більшість з яких тут не допомагають! Єдине завантаження в пам'ять інструкції все ще дозволено, це LD (HL), A
означає, що я повинен зберігати значення в A
. Оскільки A
єдиний реєстр, що залишився з дозволеною INC
інструкцією, це насправді досить зручно!
Я не можу завантажити A
з 0x00 для початку, тому що ASCII 0x00 не є дозволеним символом! Усі доступні значення далекі від 0, а всі математичні та логічні вказівки заборонені! За винятком ... Я ще можу зробити ADD HL, HL
, додати 16-бітний HL
до себе! Крім прямого завантаження значень (тут немає ніякого використання!), Збільшення A
та декрементація A
, L
або HL
це єдиний спосіб змінити значення регістра! Насправді є одна спеціалізована інструкція, яка може бути корисною у першій половині, але болісно обійтися у другій половині, і інструкція з доповненням, яка тут майже марна і просто займе місце.
Отже, я знайшов найближче значення до 0, яке я міг: 0x41. Наскільки це близько до 0? У двійковій вона 0x01000001. Тож я його декрементую, завантажую L
і роблю ADD HL, HL
двічі! L
тепер дорівнює нулю, на який я завантажую назад A
! На жаль, код ASCII для ADD HL, HL
, )
тому мені тепер потрібно використовувати (
два рази. На щастя, (
є JR Z, e
, де e
наступний байт. Тож він піднімає другий байт, і мені просто потрібно переконатися, що він нічого не робить, обережно ставившись до Z
прапора! Остання інструкція вплинути на Z
прапор була DEC A
(протиінтуїтивно, ADD HL, HL
не змінює його), і оскільки я знаю, що A
в цей момент було 0x40, гарантовано, що Z
це не встановлено.
Перша інструкція у другій половині JR Z, #28
нічого не зробить перші 255 разів, оскільки прапор Z може бути встановлений лише у тому випадку, якщо A переповнений з 255 до 0. Після цього вихід буде помилковим, однак, так як він так само зберігає лише 8-бітові значення не має значення. Код не слід розширювати більше 255 разів.
Код повинен бути виконаний як фрагмент, оскільки всі доступні способи чистого повернення були заборонені. Всі вказівки щодо повернення вище 0x80, і кілька дозволених операцій стрибків можуть переходити лише до позитивного зміщення, тому що всі 8-бітові негативні значення також заборонені!
#
є його власне відбиття, але, ви маєте рацію, не в консолях.