<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ca">
	<id>http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Home-Built_Z-80_Computer</id>
	<title>Home-Built Z-80 Computer - Historial de revisió</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Home-Built_Z-80_Computer"/>
	<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Home-Built_Z-80_Computer&amp;action=history"/>
	<updated>2026-08-30T10:17:25Z</updated>
	<subtitle>Historial de revisió per a aquesta pàgina del wiki</subtitle>
	<generator>MediaWiki 1.34.2</generator>
	<entry>
		<id>http://wiki.joanillo.org/index.php?title=Home-Built_Z-80_Computer&amp;diff=256484&amp;oldid=prev</id>
		<title>Joan: /* Versió Z80 */</title>
		<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Home-Built_Z-80_Computer&amp;diff=256484&amp;oldid=prev"/>
		<updated>2017-07-13T23:28:19Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Versió Z80&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Pàgina nova&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Introducció=&lt;br /&gt;
'''NOTA''': segueixo el projecte:&lt;br /&gt;
&lt;br /&gt;
'''Simplest possible homebrew Z80 8-bit computer''':&lt;br /&gt;
*https://www.youtube.com/watch?v=CS44XJt_gYc&amp;amp;t=68s (amb botó que dispara els pulsos del rellotge)&lt;br /&gt;
*https://www.youtube.com/watch?v=kSRZ2_V9SgM (amb rellotge)&lt;br /&gt;
*http://nuclear.mutantstargoat.com/hw/z80micro/&lt;br /&gt;
&lt;br /&gt;
Però es comenten altres projectes&lt;br /&gt;
*http://cpuville.com/Z80.htm&lt;br /&gt;
*https://www.allthingsmicro.com/index.php/projects/build-a-z80-based-computer&lt;br /&gt;
*http://zx80.netai.net/grant/z80/SimpleZ80.html&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Components=&lt;br /&gt;
*Z84C0006 -&amp;gt; és el Z80 que pot funcionar a 6MHz (IC 6MHZ Z80 CMOS CPU 40-DIP)&lt;br /&gt;
*74HC14 -&amp;gt; Circuito Integrado Hex Schmitt Trigger Inverter DIP14&lt;br /&gt;
*74HC574N -&amp;gt; TIPO D FLIP-FLOP, 74HC574, DIP20 TEXAS INSTRUMENTS SN74HC574N&lt;br /&gt;
*28C16 -&amp;gt; Memoria Eeprom 16K -&amp;gt; 24LC16 o 24LC64&lt;br /&gt;
*NE555&lt;br /&gt;
&lt;br /&gt;
Jo tenia experiència amb la memòria 24LC256 (que té 8 pins). És una memòria de 256Kb = 32KBx8bits, amb 3 pins (A0 A1 A2) per llegir o escriure les dades, però es direcciona amb el protocol I2C ( 2-wire serial interface bus), els pins SCL i SDA. Però això no és el que jo vull. El que jo vull és un xip on pugui direccionar els 10 bits del bus de direccions, i els 8 bits del bus de dades del 80, i aquest és el 28C16, que té 24 pins (DIP24).&lt;br /&gt;
===Compres===&lt;br /&gt;
*http://www.ebay.es/itm/Z84C0006PEC-Z80-B-CPU-CMOS-6-MHz-DIP40-/361046393388?hash=item54100ac22c:g:4tkAAOSwEK9UD2G1&lt;br /&gt;
11,53e (1 unitat)&lt;br /&gt;
*http://www.ebay.es/itm/10pcsx-74HC14AP-IC-DIP14-/322202332948?hash=item4b04c16f14:g:CTIAAOSw-YVXk6LA&lt;br /&gt;
7e (10 unitats)&lt;br /&gt;
*http://www.ebay.es/itm/D-TYPE-FLIP-FLOP-74HC574-DIP20-Part-TEXAS-INSTRUMENTS-SN74HC574N-/351041614108?hash=item51bbb5f11c:g:uy8AAOxyBvZTPxet&lt;br /&gt;
7e (2 unitats)&lt;br /&gt;
*http://www.ebay.es/itm/AT28C16-25-Integrated-Circuit-CASE-DIP24-/401092271449?hash=item5d62f65d59:g:qIgAAOSwHxVW8AAm&lt;br /&gt;
12e (1 unitat)&lt;br /&gt;
&lt;br /&gt;
Necessito sockets per la memòria.1 per al programador, i una altra per la placa. 10 x 24-pin Dip / Dil Pcb Ic Socket: 7e (2 unitats)&lt;br /&gt;
*http://www.ebay.es/itm/261998168513&lt;br /&gt;
&lt;br /&gt;
===74HC14: Hex Schmitt Trigger Inverter===&lt;br /&gt;
[[Fitxer:870047-DI1.gif | thumbnail]]&lt;br /&gt;
Circuito Integrado Hex Schmitt Trigger Inverter DIP14&lt;br /&gt;
*https://es.wikipedia.org/wiki/Disparador_Schmitt&lt;br /&gt;
&lt;br /&gt;
El Schmitt Trigger usa la histéresis para prevenir el ruido que podría tapar a la señal original y que causaría falsos cambios de estado si los niveles de referencia y entrada son parecidos.&lt;br /&gt;
&lt;br /&gt;
El schmitt trigger hace uso de la histéresis, que es la tendencia a conservar el nivel lógico hasta que no se produzca un cambio brusco. De esta manera se previene el ruido que podría tapar a la señal original y que causaría falsos cambios de estado si los niveles de referencia y entrada son parecidos.&lt;br /&gt;
===74HC574N: Octal D-type flip-flop, positive edge-trigger, 3-state===&lt;br /&gt;
[[Fitxer:Flip-flop-tipo-d-74hc574.jpg | thumbnail]]&lt;br /&gt;
Són Flip-Flops tipus D. N'hi ha 8. La transició es fa quan el clock passa de low a high. Hi ha un pin per ficar la sortida a alta impedància (Z) i deshabilitar.&lt;br /&gt;
&lt;br /&gt;
The typical use for such a chip is in a microprocessor system to gate the system databus into an I/O device only when the specific I/O address is decoded.&lt;br /&gt;
&lt;br /&gt;
The 74HC574; 74HCT574 is an 8-bit positive-edge triggered D-type flip-flop with 3-state outputs. The device features a clock (CP) and output enable (OE) inputs. The flip-flops will store the state of their individual D-inputs that meet the set-up and hold time requirements on the LOW-to-HIGH clock (CP) transition. A HIGH on OE causes the outputs to assume a high-impedance OFF-state. Operation of the OE input does not affect the state of the flip-flops. Inputs include clamp diodes. This enables the use of current limiting resistors to interface inputs to voltages in excess of VCC.&lt;br /&gt;
*https://en.wikipedia.org/wiki/Flip-flop_(electronics)&lt;br /&gt;
The D flip-flop is widely used. It is also known as a &amp;quot;data&amp;quot; or &amp;quot;delay&amp;quot; flip-flop. The D flip-flop captures the value of the D-input at a definite portion of the clock cycle (such as the rising edge of the clock). That captured value becomes the Q output. At other times, the output Q does not change.[22][23] The D flip-flop can be viewed as a memory cell, a zero-order hold, or a delay line.&lt;br /&gt;
&lt;br /&gt;
Truth table:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Clock 	        D 	Qnext&lt;br /&gt;
Rising edge 	0 	0&lt;br /&gt;
Rising edge 	1 	1&lt;br /&gt;
Non-Rising 	X 	Q&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Memòria 28C16 EEPROM 2KBx8 = 16Kb (CMOS)===&lt;br /&gt;
[[Fitxer:28c16.gif | thumbnail]]&lt;br /&gt;
*At28c16-15pc -&amp;gt; seria 150ns d'accés&lt;br /&gt;
*At28c16-25pc -&amp;gt; seria 250ns d'accés&lt;br /&gt;
&lt;br /&gt;
'''NOTA'''. Les memòries de 64K (28C64) són més fàcils de trobar en el eBay, i més barates. 28C32 no existeix. La compatibilitat de pins entre 28C16 i 28C64 és quasi!&lt;br /&gt;
&lt;br /&gt;
Fer el programador per gravar la informació en aquesta EPROM està discutit aquí: [[Programador_EEPROM_amb_Arduino]]&lt;br /&gt;
&lt;br /&gt;
=Construcció. PCB amb CNC, doble capa=&lt;br /&gt;
[[Fitxer:Z80 mini.png | thumbnail | v2, hi ha un error]]&lt;br /&gt;
Parteixo del projecte original (carpeta ''z80micro1-rev1/''), i retoco la pcb (''_v2'') per tal de fer més gruixudes les pistes, fins allà on pugui. A més, faré tres ponts, i així elimino pistes que eren molt llargues  i primes. És una PCB de doble capa, i els forats coincideixen perfectament, fent 4 forats de referència amb la broca de 1mm (i filferro de 1mm).&lt;br /&gt;
&lt;br /&gt;
En el '''v2''' he fet un error, i és que partint del projecte original em vaig carregar les línies de contorn, i que en realitat és un poligon. Això vol dir que en el resultat final no m'ha sortit el ''auto ratsnest'', és a dir que tots els grounds estan desconnectats entre sí. Malament. Jo he d'obtenir unes plaques amb unes superfícies de ground ben grosses, tant en el top com en el bottom. No cal que tots els ''plates'' del ground estiguin connectats entre si (en el top i en el bottom), sinó que han d'estar connectats entre el top i el bottom. En qualsevol cas, és fàcil veure la continuïtat de tot el GND.&lt;br /&gt;
&lt;br /&gt;
Per fer el ratsnest i els GND està explicat a [[Eagle_CadSoft#Ratsnest.2C_fer_el_GND_ben_gros]]&lt;br /&gt;
&lt;br /&gt;
'''v3'''. He fet el ratsnest. He fresat 3 plaques. En la primera em vaig equivocar al fer la volta, els drills no coincidien. Això ja ho tinc solucionat. Però aquesta és la que he aconseguit una més bona definició de les pistes primes (pistes de 16, tot i que en la v4 les he fet de 24). He tingut problemes amb les broques V-shape de 10º, que tenen tendència a trencar-se. Aquestes proves les he fet amb la pcb2gcode amb una profunditat de 0,3mm (el valor per defecte és de 0,2mm), i això fa que es mengi una mica més de coure. La última prova és la vàlida, tot i que m'ha quedat unes pistes massa primes (les de 16), i puc tenir problemes al soldar.&lt;br /&gt;
&lt;br /&gt;
'''v4''' (TBD). He implementat vàries millores. He eliminat les pistes de 16mils i les he ficat a 24mils (les pistes que passen entre els pins del xip, 24mils és suficient). He comprat unes broques de 20º, que espero que no es trenqui com les de 10º, i tindran més precisió que les de 30º. En el pcb2gcode he ficat depth=0,2mm (valor per defecte) en comptes de 0,3mm. Es menjarà menys coure i les pistes hauran de quedar més bé, tot i que hauré de repassar detingudament el resultat.&lt;br /&gt;
&lt;br /&gt;
'''v5a'''. He fet servir mètode de la planxa i àcid. Ha anat força, el mètoe de la planxa eś eficient, tot i que he malmès la placa. He fet servir una combinació de CNC i planxa que s'ha demostrat bastant efectiva. Primer faig els drills de la placa (amb els 4 forats de referència, també a 0,65-0,7mm). Aleshores amb el mètode de la planxa faig les dues cares. Trec el paper (difícil saber quan has de parar), i ataco amb àcid i aigua oxigenada (correcta, però difícil saber quan has de parar. Si et passes, poden quedar les pistes massa primes). De totes maneres, encara que he malmès la placa, és una bona opció.&lt;br /&gt;
&lt;br /&gt;
'''v5b'''. És la primera versió que he construït i ha funcionat (fent servir CNC). He tingut problemes amb les soldadures fredes. D'una banda, tinc un soldador de punta fina de 11 W que va bé, però les soldadures són massa fredes. D'altra banda, tinc soldadors de 26W i 60W però les puntes són massa gruixudes (tot i que en algunes pistes ja és suficient). He corregit un parell d'errors. Hi havia una soldadura freda en la senyal D3, en una soldadura que quedava molt amagada.&lt;br /&gt;
&lt;br /&gt;
He demanat un soldador de punta fina de 26W.&lt;br /&gt;
&lt;br /&gt;
No oblidar-se de soldar les pistes del top que estan unides als xips. He tingut problemes per soldar les pistes del TOP amb els sòcals dels xips (si no faig servir sòcal sinó el xip directament, aleshores no ha de representar cap problemsa). Hi ha dues solucions.&lt;br /&gt;
*1. La que he implementat és fer ponts de manera que uneixo les pistes de dalt i de baix, amb soldadures fàcils. El sòcal el soldo només per baix, i ja està. El milllor és que els ponts tinguin pads el més ample possibles i separats dels pins, per facilitar la soldadura.&lt;br /&gt;
2. L'altra solució és fer servir sòcals tornejats, un soldador de punta ben fina i fil prim. Ens hem d'assegurar que la connexió sigui bona i segura. Amb sòcals tornejats podem accedir al sòcal per fer la soldadura. Si no tenim sòcals tornejats també es pot fer, s'ha d'entrar només la meitat del sòcal per tal de fer una mica d'espai per fer la soldadura, però és més difícil.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la v5 (he fet vàries proves) finalment he aconseguit una bona placa amb broca V-shape de 20 graus, i el gruix de les pistes òptim està explicat a:&lt;br /&gt;
[[Fer_plaques_PCB_amb_màquina_CNC#Gruixos_de_les_pistes_per_a_CNC]]&lt;br /&gt;
&lt;br /&gt;
'''v6''' (TODO). Treure els ponts i les vies. Això vol dir soldar amb més precisió amb un bon soldador de punta fina. sòcals tornejats.&lt;br /&gt;
&lt;br /&gt;
==RESET==&lt;br /&gt;
RESET must be active for a minimum of three full clock cycles before a reset operation is complete. Al principi semblava que no funcionava el RESET amb el manual clock, però llegint la documentació està clar. Amb el RESET apretat, clicar tres vegades el botó de clock.&lt;br /&gt;
&lt;br /&gt;
=Ensamblador Z80. Z80 Assembler=&lt;br /&gt;
(carpeta ''projectes/Z80'')&lt;br /&gt;
*http://www.nongnu.org/z80asm/&lt;br /&gt;
*http://savannah.nongnu.org/projects/z80asm&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z80asm-1.8.tar.gz&lt;br /&gt;
&lt;br /&gt;
$ ./z80asm --help&lt;br /&gt;
Usage: ./z80asm [options] [input files]&lt;br /&gt;
&lt;br /&gt;
Possible options are:&lt;br /&gt;
-h	--help		Display this help text and exit.&lt;br /&gt;
-V	--version	Display version information and exit.&lt;br /&gt;
-v	--verbose	Be verbose.  Specify again to be more verbose.&lt;br /&gt;
-l	--list		Write a list file.&lt;br /&gt;
-L	--label		Write a label file.&lt;br /&gt;
-p	--label-prefix	prefix all labels with this prefix.&lt;br /&gt;
-i	--input		Specify an input file (-i may be omitted).&lt;br /&gt;
-o	--output	Specify the output file.&lt;br /&gt;
-I	--includepath	Add a directory to the include path.&lt;br /&gt;
Please send bug reports and feature requests to &amp;lt;shevek@fmf.nl&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Els primers codis que vull compilar i gravar en la EEPROM són els que es mostren en el projecte del mini-ordinador Z80:&lt;br /&gt;
*http://nuclear.mutantstargoat.com/hw/z80micro/&lt;br /&gt;
&lt;br /&gt;
'''exemple1.asm''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
org $0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
loop:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        jr loop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per obtenir el binari:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./z80asm -I /headers/ -o examples/exemple1.bin -i examples/exemple1.asm&lt;br /&gt;
$ od -Ax -t x1 exemple1.bin&lt;br /&gt;
000000 3e 01 d3 ff 07 18 fb&lt;br /&gt;
000007&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Aquests valors també els puc veure amb la utilitat gràfica '''ghex'''&lt;br /&gt;
==Z80Pack: ensamblador i simulador==&lt;br /&gt;
És un altre ensamblador, que a més té simulador:&lt;br /&gt;
*http://www.autometer.de/unix4fun/z80pack/ftp/&lt;br /&gt;
Descarrego la versió 1.34. Les carpetes ''z80asm/'' i ''z80sim/'' es compilen amb ''make'' sense problemes.&lt;br /&gt;
&lt;br /&gt;
Per otenir el binari dels meus dos exemples he de tabular el ORG (o senzillament no posar-lo), i sense el símbol del dòllar:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ORG 0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
loop:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        jr loop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
i obtinc el mateix binari&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./z80asm -fb exemple1.asm&lt;br /&gt;
$ od -Ax -t x1 exemple1.bin&lt;br /&gt;
000000 3e 01 d3 ff 07 18 fb&lt;br /&gt;
000007&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si compilo sense l'opció ''-fb'' obtenim:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./z80asm exemple1b.asm&lt;br /&gt;
Z80 - Assembler Release 1.7, Copyright (C) 1987-2016 by Udo Munk&lt;br /&gt;
Pass 1&lt;br /&gt;
   Read    exemple1b.asm&lt;br /&gt;
Pass 2&lt;br /&gt;
   Read    exemple1b.asm&lt;br /&gt;
0 error(s)&lt;br /&gt;
$ od -Ax -t x1 exemple1b.bin&lt;br /&gt;
000000 ff 00 00 3e 01 d3 ff 07 18 fb&lt;br /&gt;
00000a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I això té la seva importància perquè és aquest fitxer el que va bé per al simulador.&lt;br /&gt;
&lt;br /&gt;
===Simulador Z80===&lt;br /&gt;
*http://www.autometer.de/unix4fun/z80pack/doc_sim_install.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd ~/z80pack-1.34/z80sim/srcsim&lt;br /&gt;
$ make&lt;br /&gt;
$ ./z80sim -z&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Aleshores ja podem carregar el programa amb l'opció '''r''', i és important veure com '''START:0000''' (això ho hem aconseguit compilant sense l'opció -fb):&lt;br /&gt;
&lt;br /&gt;
Un cop estem en el prompt del simulador ('''&amp;gt;&amp;gt;&amp;gt;'''), l'opció ''g'' és per arrencar el programa, i amb el ''ENTER'' (single step program) vaig avançant pel programa. Amb l'opció ''t, trace'' puc veure vàries instruccions a l'hora.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./z80sim -z&lt;br /&gt;
&lt;br /&gt;
#######  #####    ###            #####    ###   #     #&lt;br /&gt;
     #  #     #  #   #          #     #    #    ##   ##&lt;br /&gt;
    #   #     # #     #         #          #    # # # #&lt;br /&gt;
   #     #####  #     #  #####   #####     #    #  #  #&lt;br /&gt;
  #     #     # #     #               #    #    #     #&lt;br /&gt;
 #      #     #  #   #          #     #    #    #     #&lt;br /&gt;
#######  #####    ###            #####    ###   #     #&lt;br /&gt;
&lt;br /&gt;
Release 1.34, Copyright (C) 1987-2017 by Udo Munk&lt;br /&gt;
&lt;br /&gt;
CPU speed is unlimited&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; r exemple1b.bin&lt;br /&gt;
Loader statistics for file exemple1b.bin:&lt;br /&gt;
START : 0000&lt;br /&gt;
END   : 0006&lt;br /&gt;
LOADED: 0007&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;
&lt;br /&gt;
PC   A  SZHPNC I  IFF BC   DE   HL   A'F' B'C' D'E' H'L' IX   IY   SP&lt;br /&gt;
0002 01 000000 00 00  0000 0000 0000 0000 0000 0000 0000 0000 0000 ffff&lt;br /&gt;
OUT	(FF),A&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;
&lt;br /&gt;
PC   A  SZHPNC I  IFF BC   DE   HL   A'F' B'C' D'E' H'L' IX   IY   SP&lt;br /&gt;
0004 01 000000 00 00  0000 0000 0000 0000 0000 0000 0000 0000 0000 ffff&lt;br /&gt;
RLCA&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;
&lt;br /&gt;
PC   A  SZHPNC I  IFF BC   DE   HL   A'F' B'C' D'E' H'L' IX   IY   SP&lt;br /&gt;
0005 02 000000 00 00  0000 0000 0000 0000 0000 0000 0000 0000 0000 ffff&lt;br /&gt;
JR	0002&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;
&lt;br /&gt;
PC   A  SZHPNC I  IFF BC   DE   HL   A'F' B'C' D'E' H'L' IX   IY   SP&lt;br /&gt;
0002 02 000000 00 00  0000 0000 0000 0000 0000 0000 0000 0000 0000 ffff&lt;br /&gt;
OUT	(FF),A&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Fixem-nos que encara que hem afegit tres bytes al principi del fitxer (''ff 00 00''), quan fem dump de la memòria (opció -d) aquests tres bytes no apareixen, per tant ho fem bé:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; ? -&amp;gt; per veure les opcions&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; d&lt;br /&gt;
Adr    00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ASCII&lt;br /&gt;
0000 - 3e 01 d3 ff 07 18 fb ec 29 cd ba ab f2 fb e3 46 	&amp;gt;.......)......F&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Per visualitzar o canviar un registre, ho fem amb '''x''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; x a&lt;br /&gt;
A = 04 : 01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''compte''': el nom del registre en minúscules. Hem de posar el nou valor, si és el mateix, repetim el valor.&lt;br /&gt;
&lt;br /&gt;
Amb tot això, aquest simulador m'haurà d'anar bé per programar l'algorisme de les Torres de Hanoi.&lt;br /&gt;
&lt;br /&gt;
=Programes de prova. Ensamblador Z80=&lt;br /&gt;
En aquest projecte es proposen dos exercicis simples, on la sortida són 8 LEDs. En el primer exemple els LEDs es van desplaçant, quan arriba al final torna al principi. En el segon exemple, quan el led encès arriba al final, canvia de direcció-&lt;br /&gt;
&lt;br /&gt;
'''exemple 1''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
org $0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
loop:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        jr loop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*'''org $0'''&lt;br /&gt;
'''ORG''' is an abbreviation for &amp;quot;origin&amp;quot;. ORG is merely an indication on where to put the next piece of code/data, related to the current segment. '''ORG''' it's the location in memory where you want the binary program to be loaded to, if any. '''ORG''' is used to set the assembler location counter. &lt;br /&gt;
&lt;br /&gt;
*'''ld a, 1'''&lt;br /&gt;
The LD instruction is used to put the value from one place into another place.&lt;br /&gt;
Per tant, fiquem un 1 en el registre A (registre general)&lt;br /&gt;
&lt;br /&gt;
*'''loop:'''&lt;br /&gt;
És un label, al qual podem cridar dins del mateix loop. Per tant, ens servirà per fer bucles. El programa s'executarà sense fi.&lt;br /&gt;
&lt;br /&gt;
*'''out (255), a'''&lt;br /&gt;
OUT: Writes the value of the second operand into the port given by the first operand.&lt;br /&gt;
&lt;br /&gt;
En el registre A hi havíem ficat un 1. En aquest cas, què significa el port (255)? La idea que es persegueix és que el contingut de A es correspon amb l'encesa dels LEDs.&lt;br /&gt;
&lt;br /&gt;
Llegint en el '''Z80 CPU User Manual''', pàgina 306. '''OUT (n), A'''. The operand n is placed on the bottom half (A0 through A7) of the address bus to select&lt;br /&gt;
the I/O device at one of 256 possible ports. The contents of the Accumulator (Register A) also appear on the top half (A8 through A15) of the address bus at this time. Then the byte&lt;br /&gt;
contained in the Accumulator is placed on the data bus and written to the selected peripheral device.&lt;br /&gt;
&lt;br /&gt;
Per tant, en el bus de direccions (A0...A7) hem de veure FF (que és el port, però que per nosaltres no té cap sentit), i el contingut de l'acumuladror l'hem de veure en el bus de dades (que és el que interessa), i també a A8...A15 (tot i que nosaltres només tenim A8, A9 i A10. Com que fiquem el contingut de l'acumulador en el bus de dades, això és una operació d'escriptura (WR). Si ens fixem en l'esquema, el clock del LATCH està unit al WR del Z80. Per tant, cada vegada que fem una operació d'escriptura en el bus de dades es fa un latch del bus de dades. &lt;br /&gt;
&lt;br /&gt;
*'''rlca'''&lt;br /&gt;
Performs RLC A much quicker, and modifies the flags differently. S,Z, and P/V are preserved, H and N flags are reset.&lt;br /&gt;
&lt;br /&gt;
'''RLC''': 8-bit rotation to the left. The bit leaving on the left is copied into the carry, and to bit 0.&lt;br /&gt;
Per tant, amb RLCA el que fem és una rotació cap a l'esquerra de 8 bits. Originalment teníem un 1. El 1 passa cap a l'esquerra:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
00000001&lt;br /&gt;
00000010&lt;br /&gt;
00000100&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*'''jr loop'''&lt;br /&gt;
'''JR''': Relative jumps to the address. This means that it can only jump between 128 bytes ahead or behind. Can be conditional or unconditional. JR takes up one less byte than JP, but is also slower. Weigh the needs of the code at the time before choosing one over the other (speed vs. size).&lt;br /&gt;
Per tant, tornem al loop (quan té un sol argument és un jump sense condició)&lt;br /&gt;
&lt;br /&gt;
La idea doncs del codi és que anem fent una rotació cap a l'esquerra d'un bit en el registre A, i el contingut de A el bolquem al port (255), que està associat al display dels LEDs. En conclusió, hem de veure com roten els LEDs.&lt;br /&gt;
&lt;br /&gt;
'''exemple 2''': Un exercici una mica més interessant&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
org $0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
left:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        cp 128&lt;br /&gt;
        jr z, right&lt;br /&gt;
        jr left&lt;br /&gt;
right:  out (255), a&lt;br /&gt;
        rrca&lt;br /&gt;
        cp 1&lt;br /&gt;
        jr z, left&lt;br /&gt;
        jr right&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''CP''' is a subtraction from A that doesn't update A, only the flags it would have set/reset if it really was subtracted. Per tant, en fer la substracció és possible que el flag Z (el bit de Zero en el registre F) estigui a 0 o a 1.&lt;br /&gt;
jr z, right: jr és el jump, i quan té dos arguments, el primer argument és la condició. Mirem el flag Z, si és 1, anem a right.&lt;br /&gt;
&lt;br /&gt;
La idea del codi doncs és que el led que s'encén es desplaça cap a l'esquerra o cap a la dreta. Per decidir el canvi de direcció hem de fer una resta, i mirar el flag Z.&lt;br /&gt;
&lt;br /&gt;
Pas a pas el funcionament és el següent.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld a, 1 -&amp;gt; A: 00000001&lt;br /&gt;
left:   out (255), a -&amp;gt; mostrem el LED: 0000000X&lt;br /&gt;
rlca -&amp;gt; A: 00000010&lt;br /&gt;
cp 128:&lt;br /&gt;
10000000 - 00000010 = (128-2) = 126 = 0x7E = 01111110 (però és una resta sense portar-ne, no afecta al flag Z)&lt;br /&gt;
jr z, right -&amp;gt; com que Z=0, no es fa el jump de right, sinó fem el jump de left, per tant, continuem en el mateix bucle.&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
rlca -&amp;gt; A: 01000000&lt;br /&gt;
cp 128:&lt;br /&gt;
10000000 - 01000000 = (128-64) = 64 = 01000000 (però és una resta sense portar-ne, no afecta al flag Z)&lt;br /&gt;
jr z, right -&amp;gt; com que Z=0, no es fa el jump de right, sinó fem el jump de left, per tant, continuem en el mateix bucle.&lt;br /&gt;
&lt;br /&gt;
rlca -&amp;gt; A: 10000000 = (128-128) = 0 = 00000000 (però ara sí que tenim el flag Z=1)&lt;br /&gt;
jr z, right -&amp;gt; com que Z=1, ara sí que es fa el jump de right, i per tant saltem a l'altre bucle.&lt;br /&gt;
&lt;br /&gt;
right:  out (255), a -&amp;gt; mostrem el LED: X0000000&lt;br /&gt;
rrca -&amp;gt; A: 01000000&lt;br /&gt;
cp 1:&lt;br /&gt;
01000000 - 00000001 = (64-1) = 63 = 0x3F = 00111111 (però és una resta sense portar-ne, no afecta al flag Z)&lt;br /&gt;
jr z, left -&amp;gt; com que Z=0, no es fa el jump de left, sinó fem el jump de right, per tant, continuem en el mateix bucle (estem en el bucle de right).&lt;br /&gt;
...&lt;br /&gt;
rrca -&amp;gt; A: 00000010&lt;br /&gt;
cp 1:&lt;br /&gt;
00000010 - 00000001 = (2-1) = 1 = 0x01 (però és una resta sense portar-ne, no afecta al flag Z)&lt;br /&gt;
jr z, left -&amp;gt; com que Z=0, no es fa el jump de left, sinó fem el jump de right, per tant, continuem en el mateix bucle (estem en el bucle de right).&lt;br /&gt;
&lt;br /&gt;
rrca -&amp;gt; A: 00000001&lt;br /&gt;
cp 1:&lt;br /&gt;
00000001 - 00000001 = (1-1) = 0 = 0x01 (però ara sí que tenim el flag Z=1)&lt;br /&gt;
jr z, left -&amp;gt; com que Z=1, ara sí que fa el jump de left i saltem a l'altre bucle, i tornem a començar.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Codi màquina. Opcodes del Z80==&lt;br /&gt;
Tenim els dos programes en ensamblador. S'ha d'obtenir el codi màquina (els bytes que ficarem dins de la EEPROM), i veure com els bytes generats es corresponen amb els opcodes del Z80. És a dir, les instruccions estan associades a unes direccions de memòria que el Z80 entén.&lt;br /&gt;
&lt;br /&gt;
Compilem els dos programes d'exemple que tenim:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./z80asm -I ~/Z80/z80asm-1.8/headers/ -o exemple1.bin -i examples/exemple1.asm&lt;br /&gt;
$ ./z80asm -I ~/Z80/z80asm-1.8/headers/ -o exemple2.bin -i examples/exemple2.asm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I els bytes que obtenim són:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ od -Ax -t x1 exemple1.bin &lt;br /&gt;
000000 3e 01 d3 ff 07 18 fb&lt;br /&gt;
&lt;br /&gt;
$ od -Ax -t x1 exemple2.bin &lt;br /&gt;
000000 3e 01 d3 ff 07 fe 80 28 02 18 f7 d3 ff 0f fe 01&lt;br /&gt;
000010 28 f0 18 f7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Repassem els dos exemples:&lt;br /&gt;
&lt;br /&gt;
''exemple1.asm'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
org $0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
loop:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        jr loop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''exemple2.asm'':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
org $0&lt;br /&gt;
        ld a, 1&lt;br /&gt;
left:   out (255), a&lt;br /&gt;
        rlca&lt;br /&gt;
        cp 128&lt;br /&gt;
        jr z, right&lt;br /&gt;
        jr left&lt;br /&gt;
right:  out (255), a&lt;br /&gt;
        rrca&lt;br /&gt;
        cp 1&lt;br /&gt;
        jr z, left&lt;br /&gt;
        jr right&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I aquí tenim el resum dels opcodes que es fan servir:&lt;br /&gt;
*http://z80-heaven.wikidot.com/opcode-reference-chart (en aquesta taula queda més clar)&lt;br /&gt;
*http://www.z80.info/z80oplist.txt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
3E LD   A,&amp;amp;00     -              SRL  (HL)   SRL  (IY+0)  &lt;br /&gt;
D3 OUT  (&amp;amp;00),A   -              SET  2,E    set 2,(iy+0)-&amp;gt;e  -&lt;br /&gt;
07 RLCA           -              RLC  A      rlc (iy+0)-&amp;gt;a    MOS_ARGS&lt;br /&gt;
18 JR   &amp;amp;4546     -              RR   B      rr  (iy+0)-&amp;gt;b    -&lt;br /&gt;
FE CP   &amp;amp;00       -              SET  7,(HL) SET  7,(IY+0)    [z80]&lt;br /&gt;
28 JR   Z,&amp;amp;4546   -              SRA  B      sra (iy+0)-&amp;gt;b    -&lt;br /&gt;
0F RRCA           -              RRC  A      rrc (iy+0)-&amp;gt;a    MOS_FF0F&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*podem veure com en l'exemple1 la direcció de ''loop'' és ''FB''&lt;br /&gt;
*podem veure com les direccions de ''left'' i ''right'' són ''F7'' i ''02''&lt;br /&gt;
&lt;br /&gt;
És a dir, cada instrucció té un codi (per ex, ''LD'' és ''3E''), i d'aquesta manera el Z80 sap quina instrucció ha d'executar. A més, donada una instrucció sap si li segueix cap argument, 1 ó 2 arguments.&lt;br /&gt;
=Torres de Hanoi en Z80 assembler=&lt;br /&gt;
[[Fitxer:Hanoi.jpg | thumbnail]]&lt;br /&gt;
==Algorisme==&lt;br /&gt;
L'algorisme de les Torres de Hanoi és un exemple típic de recursivitat:&lt;br /&gt;
*https://www.tutorialspoint.com/data_structures_algorithms/tower_of_hanoi.htm&lt;br /&gt;
I en aquest enllaç tenim l'algorisme recursiu en molts llenguatges (sortida orientada a text), entre ells ''360 Assembly'', però no Z80 assembly:&lt;br /&gt;
*https://rosettacode.org/wiki/Towers_of_Hanoi#360_Assembly&lt;br /&gt;
&lt;br /&gt;
'''Algorisme''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Els passos a seguir són:&lt;br /&gt;
Step 1 − Move n-1 disks from source to aux&lt;br /&gt;
Step 2 − Move nth disk from source to dest&lt;br /&gt;
Step 3 − Move n-1 disks from aux to dest&lt;br /&gt;
&lt;br /&gt;
A recursive algorithm for Tower of Hanoi can be driven as follows −&lt;br /&gt;
&lt;br /&gt;
START&lt;br /&gt;
Procedure Hanoi(disk, source, dest, aux)&lt;br /&gt;
&lt;br /&gt;
   IF disk == 1, THEN&lt;br /&gt;
      move disk from source to dest             &lt;br /&gt;
   ELSE&lt;br /&gt;
      Hanoi(disk - 1, source, aux, dest)     // Step 1&lt;br /&gt;
      move disk from source to dest          // Step 2&lt;br /&gt;
      Hanoi(disk - 1, aux, dest, source)     // Step 3&lt;br /&gt;
   END IF&lt;br /&gt;
   &lt;br /&gt;
END Procedure&lt;br /&gt;
STOP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I aquí tenim la versió ''X86 assembly'' en dues versions, amb push/pop a una pila i, millor', sense push/pop:&lt;br /&gt;
*http://www.mastropaolo.com/2005/06/01/hanoi-towers-as-a-pure-recursion-benchmark-part-2-algorithm-optimizations/&lt;br /&gt;
Es compara la velocitat amb C++, i resulta ser el doble de ràpid.&lt;br /&gt;
==Versió x86 Assembly==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mov ebx, from&lt;br /&gt;
mov ecx, to&lt;br /&gt;
mov edx, use&lt;br /&gt;
mov eax, howmany&lt;br /&gt;
xor esi, esi&lt;br /&gt;
&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
mov retcode, esi&lt;br /&gt;
jmp EndHanoiAsm&lt;br /&gt;
HanoiAsm:&lt;br /&gt;
dec eax&lt;br /&gt;
jz NextLoop&lt;br /&gt;
push eax&lt;br /&gt;
xchg ecx, edx&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
xchg ecx, edx&lt;br /&gt;
xchg edx, ebx&lt;br /&gt;
pop eax&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
xchg edx, ebx&lt;br /&gt;
NextLoop:&lt;br /&gt;
inc esi&lt;br /&gt;
ret&lt;br /&gt;
EndHanoiAsm:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Assembly, no push/pop''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
push ebp&lt;br /&gt;
mov ebx, from&lt;br /&gt;
mov ecx, to&lt;br /&gt;
mov edx, use&lt;br /&gt;
xor esi, esi&lt;br /&gt;
&lt;br /&gt;
mov eax, howmany&lt;br /&gt;
mov ebp, esp&lt;br /&gt;
shl eax, 2&lt;br /&gt;
sub ebp, eax&lt;br /&gt;
sar eax, 2&lt;br /&gt;
&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
pop ebp&lt;br /&gt;
mov retcode, esi&lt;br /&gt;
jmp EndHanoiAsm&lt;br /&gt;
HanoiAsm:&lt;br /&gt;
dec eax&lt;br /&gt;
jz NextLoop&lt;br /&gt;
xchg ecx, edx&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
mov eax, esp&lt;br /&gt;
xchg ecx, edx&lt;br /&gt;
sub eax, ebp&lt;br /&gt;
xchg edx, ebx&lt;br /&gt;
sar eax, 2&lt;br /&gt;
call HanoiAsm&lt;br /&gt;
xchg edx, ebx&lt;br /&gt;
NextLoop:&lt;br /&gt;
inc esi&lt;br /&gt;
ret&lt;br /&gt;
EndHanoiAsm:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Explicació:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mov ebx, from&lt;br /&gt;
mov ecx, to&lt;br /&gt;
mov edx, use&lt;br /&gt;
mov eax, howmany -&amp;gt; eax serà la variable temporal per guardar els discos que falten&lt;br /&gt;
xor esi, esi&lt;br /&gt;
&lt;br /&gt;
call HanoiAsm -&amp;gt; fem la primera crida&lt;br /&gt;
mov retcode, esi -&amp;gt; movem el contingut de esi a retcode. Què és retcode?&lt;br /&gt;
jmp EndHanoiAsm -&amp;gt; sortim del programa&lt;br /&gt;
&lt;br /&gt;
HanoiAsm:&lt;br /&gt;
dec eax -&amp;gt; decrementa el contingut de eax en 1 unitat. eax és el howmany&lt;br /&gt;
jz NextLoop -&amp;gt; j&amp;lt;condition&amp;gt;. jz &amp;lt;label&amp;gt; (jump when last result was zero). Aquesta és la condició de què quan disk=1 sortim&lt;br /&gt;
push eax -&amp;gt; guarda a la pila el valor de eax, que és el valor actual de num de discs per col.locar&lt;br /&gt;
xchg ecx, edx -&amp;gt; Exchanges the contents of the destination (first) and source (second) operands&lt;br /&gt;
call HanoiAsm -&amp;gt; tornem a cridar: recursivitat&lt;br /&gt;
xchg ecx, edx -&amp;gt; tornem a intercanviar&lt;br /&gt;
xchg edx, ebx&lt;br /&gt;
pop eax -&amp;gt; recuperem de la pila el valor de eax&lt;br /&gt;
call HanoiAsm -&amp;gt; tornem a cridar: recursivitat&lt;br /&gt;
xchg edx, ebx  -&amp;gt; tornem a intercanviar&lt;br /&gt;
&lt;br /&gt;
NextLoop:&lt;br /&gt;
inc esi -&amp;gt; incrementem esi en una unitat i tornem. esi és un registre de propòsit general&lt;br /&gt;
ret -&amp;gt; retorna de la crida de HanoiAsm &lt;br /&gt;
&lt;br /&gt;
EndHanoiAsm: -&amp;gt; sortim del programa&lt;br /&gt;
&lt;br /&gt;
http://www.cs.virginia.edu/~evans/cs216/guides/x86.html&lt;br /&gt;
&lt;br /&gt;
mov ebx, from -&amp;gt; fica el contingut de from a ebx&lt;br /&gt;
xor esi, esi -&amp;gt; fica esi=0 quan esi sigui igual a ell mateix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Versió Z80==&lt;br /&gt;
Per compilar i simular:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
joan@joan-portatil:~/projectes/Z80/z80pack-1.34/z80asm$ ./z80asm hanoi_v1.asm&lt;br /&gt;
$ cp hanoi_v1.bin ../z80sim/srcsim/&lt;br /&gt;
&lt;br /&gt;
joan@joan-portatil:~/projectes/Z80/z80pack-1.34/z80sim/srcsim$ ./z80sim -z&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I la versió amb Z80, finalment! ja he trobat la solució. '''hanoi_v1.asm''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ORG 0&lt;br /&gt;
numdisks	EQU	3&lt;br /&gt;
source	EQU	4&lt;br /&gt;
aux	EQU	2&lt;br /&gt;
dest	EQU	1&lt;br /&gt;
&lt;br /&gt;
	ld a, numdisks&lt;br /&gt;
	ld b, source&lt;br /&gt;
	ld c, aux&lt;br /&gt;
	ld d, dest&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
	ld e,(255)	;mostrem&lt;br /&gt;
	jp Fi&lt;br /&gt;
&lt;br /&gt;
HanoiAsm:&lt;br /&gt;
	dec a ;decrementem, si a=0 (vol dir que a valia 1), anem a la rutina NextLoop, tornem a deixar a=1, i sortim&lt;br /&gt;
	jr z, NextLoop&lt;br /&gt;
	push af&lt;br /&gt;
&lt;br /&gt;
	ld h,c&lt;br /&gt;
	ld l,d&lt;br /&gt;
	ld d,h&lt;br /&gt;
	ld c,l&lt;br /&gt;
&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
&lt;br /&gt;
	pop af&lt;br /&gt;
	inc a&lt;br /&gt;
	ld e,a	;mostrem&lt;br /&gt;
	ld e,b	;mostrem&lt;br /&gt;
	ld e,c	;mostrem&lt;br /&gt;
	ld e,(0)	;mostrem&lt;br /&gt;
	dec a&lt;br /&gt;
&lt;br /&gt;
	ld h,b&lt;br /&gt;
	ld l,d&lt;br /&gt;
	ld d,h&lt;br /&gt;
	ld b,l&lt;br /&gt;
&lt;br /&gt;
	ld h,d&lt;br /&gt;
	ld l,c&lt;br /&gt;
	ld c,h&lt;br /&gt;
	ld d,l&lt;br /&gt;
&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
&lt;br /&gt;
	ld h,b&lt;br /&gt;
	ld l,c&lt;br /&gt;
	ld c,h&lt;br /&gt;
	ld b,l&lt;br /&gt;
&lt;br /&gt;
	ret&lt;br /&gt;
&lt;br /&gt;
NextLoop:&lt;br /&gt;
	inc a&lt;br /&gt;
	ld e,a	;mostrem&lt;br /&gt;
	ld e,b	;mostrem&lt;br /&gt;
	ld e,d	;mostrem&lt;br /&gt;
	ld e,(0);mostrem&lt;br /&gt;
	ret&lt;br /&gt;
&lt;br /&gt;
Fi:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La solució està fixant-se en el registre E. Surten valors que s'han d'interpretar. Per exemple, per a N=2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
E=1 -&amp;gt; moure el primer disc des de la posició 4 (el primer peg, source) fins la posició 2 (2n peg, aux)&lt;br /&gt;
E=4&lt;br /&gt;
E=2&lt;br /&gt;
&lt;br /&gt;
E=2 -&amp;gt; moure el segon disc des de la posició 4 (el primer peg, source) fins la posició 1 (3r peg, destí)&lt;br /&gt;
E=4&lt;br /&gt;
E=1&lt;br /&gt;
&lt;br /&gt;
E=1 -&amp;gt; moure el primer disc des de la posició 2 (el segon peg, aux) fins la posició 1 (3r peg, destí)&lt;br /&gt;
E=2&lt;br /&gt;
E=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I per què he escollit els valors de 4,2,1 en els registres b,c i d? Doncs perquè visualment podré veure la solució amb els meus 8 leds. El que he de veure en la sortida a mida que vagi fent cicles de rellotge és la solució:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
xxxxxxxx -&amp;gt; significa que ve un moviment&lt;br /&gt;
.......x&lt;br /&gt;
.....x..&lt;br /&gt;
......x.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
xxxxxxxx -&amp;gt; significa que ve un moviment&lt;br /&gt;
......x.&lt;br /&gt;
.....x..&lt;br /&gt;
.......x&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
xxxxxxxx -&amp;gt; significa que ve un moviment&lt;br /&gt;
......x.&lt;br /&gt;
......x.&lt;br /&gt;
.......x&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''hanoi_v2.asm''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ORG 0&lt;br /&gt;
numdisks	EQU	3&lt;br /&gt;
source	EQU	4&lt;br /&gt;
aux	EQU	2&lt;br /&gt;
dest	EQU	1&lt;br /&gt;
&lt;br /&gt;
	ld a, numdisks&lt;br /&gt;
	ld b, source&lt;br /&gt;
	ld c, aux&lt;br /&gt;
	ld d, dest&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
	ld e,(255)	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	jp Fi&lt;br /&gt;
&lt;br /&gt;
HanoiAsm:&lt;br /&gt;
	dec a ;decrementem, si a=0 (vol dir que a valia 1), anem a la rutina NextLoop, tornem a deixar a=1, i sortim&lt;br /&gt;
	jr z, NextLoop&lt;br /&gt;
	push af&lt;br /&gt;
&lt;br /&gt;
	ld h,c&lt;br /&gt;
	ld l,d&lt;br /&gt;
	ld d,h&lt;br /&gt;
	ld c,l&lt;br /&gt;
&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
&lt;br /&gt;
	pop af&lt;br /&gt;
	inc a&lt;br /&gt;
	ld e,a	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,b	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,c	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,(0)	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	dec a&lt;br /&gt;
&lt;br /&gt;
	ld h,b&lt;br /&gt;
	ld l,d&lt;br /&gt;
	ld d,h&lt;br /&gt;
	ld b,l&lt;br /&gt;
&lt;br /&gt;
	ld h,d&lt;br /&gt;
	ld l,c&lt;br /&gt;
	ld c,h&lt;br /&gt;
	ld d,l&lt;br /&gt;
&lt;br /&gt;
	call HanoiAsm&lt;br /&gt;
&lt;br /&gt;
	ld h,b&lt;br /&gt;
	ld l,c&lt;br /&gt;
	ld c,h&lt;br /&gt;
	ld b,l&lt;br /&gt;
&lt;br /&gt;
	ret&lt;br /&gt;
&lt;br /&gt;
NextLoop:&lt;br /&gt;
	inc a&lt;br /&gt;
	ld e,a	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,b	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,d	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ld e,(0)	;mostrem&lt;br /&gt;
	out (255), e&lt;br /&gt;
	ret&lt;br /&gt;
&lt;br /&gt;
Fi:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$  od -Ax -t x1 hanoi_v2.bin &lt;br /&gt;
000000 ff 00 00 3e 03 06 04 0e 02 16 01 cd 12 00 1e ff&lt;br /&gt;
000010 d3 ff c3 4c 00 3d 28 28 f5 61 6a 54 4d cd 12 00&lt;br /&gt;
000020 f1 3c 5f d3 ff 58 d3 ff 59 d3 ff 1e 00 d3 ff 3d&lt;br /&gt;
000030 60 6a 54 45 62 69 4c 55 cd 12 00 60 69 4c 45 c9&lt;br /&gt;
000040 3c 5f d3 ff 58 d3 ff 5a d3 ff 1e 00 d3 ff c9&lt;br /&gt;
00004f&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{Autor}}, juny 2017&lt;/div&gt;</summary>
		<author><name>Joan</name></author>
		
	</entry>
</feed>