Código da máquina Z80, 8 6 bytes *
<8ww8>
* Assume certas condições ao entrar no 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
é inicialmente 0 quando inserido no BASIC. Incrementa A
n vezes e depois escreve n vezes no mesmo local de memória (que é definido como BASIC em um local ligeiramente aleatório)! A JR
operação Jump Relative nunca faz nada, já que o C
sinalizador está sempre desmarcado; portanto, é usado para "comentar" o seguinte byte! Esta versão é um pouco trapaceira, assumindo-se certas condições de entrada, como a entrada de garantias BASIC que A
são sempre 0. A localização de (HL)
não é garantida como segura e, de fato, é provavelmente uma localização perigosa. O código abaixo é muito mais robusto e é por isso que é muito mais longo.
Código da máquina Z80, 30 bytes
Como ASCII:
o!.ww.!>A=o>{))((}<o=A<!.ww.!o
Basicamente, a primeira metade garante a criação de um valor zero e a segunda metade o incrementa e grava na memória. Na versão expandida abaixo##
denota código que não serve para nada na metade do espelho.
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
Repartição das instruções permitidas:
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
Das 39 instruções permitidas, 28 são operações de carregamento (o bloco de 0x40 a 0x7F são LD
instruções de byte único ), a maioria das quais não ajuda aqui! A única instrução de carregamento na memória ainda permitida é o LD (HL), A
que significa que tenho que armazenar o valor A
. Como A
é o único registro que resta com uma INC
instrução permitida, isso é realmente bastante útil!
Não consigo carregar A
com 0x00 porque o ASCII 0x00 não é um caractere permitido! Todos os valores disponíveis estão longe de 0 e todas as instruções matemáticas e lógicas foram proibidas! Exceto ... eu ainda posso fazer ADD HL, HL
, adicione 16 bits HL
a si mesmo! Além de carregar diretamente os valores (sem uso aqui!), INCrementing A
e DECrementingA
, L
ou HL
é a única maneira que tenho de alterar o valor de um registro! Na verdade, existe uma instrução especializada que pode ser útil no primeiro semestre, mas é difícil trabalhar no segundo semestre, e uma instrução complementar que é quase inútil aqui e ocuparia apenas espaço.
Então, eu achei o valor mais próximo de 0 que eu pude: 0x41. Como isso é perto de 0? Em binário, é 0x01000001. Então eu diminuo, carrego L
e faço ADD HL, HL
duas vezes! L
agora é zero, no qual carrego de volta A
! Infelizmente, o código ASCII para ADD HL, HL
é )
agora preciso usar (
duas vezes. Felizmente, (
é JR Z, e
, onde e
é o próximo byte. Portanto, ele devora o segundo byte e eu só preciso garantir que ele não faça nada, tomando cuidado com a Z
bandeira! A última instrução para afetar a Z
flag foi DEC A
(contra-intuitivamente, ADD HL, HL
não a altera) e, como eu sei que A
era 0x40 naquele momento, é garantido que Z
não está definido.
A primeira instrução na segunda metade JR Z, #28
não fará nada nas primeiras 255 vezes, porque o sinalizador Z só pode ser definido se A tiver excedido de 255 para 0. Depois disso, a saída estará errada, no entanto, pois ele está salvando valores de 8 bits de qualquer maneira que não deveria importar. O código não deve ser expandido mais de 255 vezes.
O código deve ser executado como um trecho, pois todas as formas disponíveis de retorno limpo foram desabilitadas. Todas as instruções RETurn estão acima de 0x80 e as poucas operações de salto permitidas só podem pular para um deslocamento positivo, porque todos os valores negativos de 8 bits também foram proibidos!
#
é a sua própria relação também, mas, você está certo, não em consolas.