Vermenigvuldigen in ML Genic Clubguide, 00-00-00 VERMENIGVULDIGEN IN MACHINETAAL Onlangs kregen wij van een inventieve lezer een routine toegestuurd om te vermenigvuldigen in machinetaal. Niets bijzonders zult U zeggen. Dat is het ook niet echt, maar omdat er in machinetaal geen instrukties voor zijn is het toch wel handig. Bovendien schept het de mogelijkheid om eens iets meer over machinetaal uit de doeken te doen. Bij de Z80 werken we met binaire getallen, uitsluitend met nullen en enen dus. Laten we eerst eens kijken hoe we binair kunnen vermenigvuldigen: Vb. 15 * 3 = ? => 00000011 (3) 00001111 (15) * ---------------- 00000011 (3) 3 * 2 tot de 0e 00000110 (6) 3 * 2 tot de 1e 00001100 (12) 3 * 2 tot de 2e 00011000 (24) 3 * 2 tot de 3e ---------------- 101101 (45) We laten dit binair zien omdat zo in de Z80 wordt vermenigvuldigd. Allereerst zetten we een programma op. Wat moet er allemaal gebeuren in het programma, hieronder een eerste opzet: - De getallen waarmee gerekend gaat worden, moeten worden ingelezen. - Er moet gekeken worden of het getal waar we mee gaan vermenigvuldigen een 0 of een 1 is. - Is het een 0 dan kunnen we het geheel opschuiven. - Is het een 1 dan moeten we vermenigvuldigen. - We moeten zorgen dat het programma 8 keer vermenigvuldigd en dan terug keert naar BASIC. Lijkt simpel, het valt ook best wel mee. Wat we niet moeten vergeten is dat er elke keer als we het volgende getal nemen het 10 * zoveel is en er dus een 0 achter het antwoord moet komen. Vb. 4 1 22 * 11 * -- -- 8 1 80 ( Met een 0 erachter ) 10 ( Met een 0 erachter ) -- + -- + 88 11 Dus we zullen elke keer als we het volgende getal nemen om mee te vermenigvuldigen een extra nul moeten toevoegen. Nu we ongeveer het programma in het hoofd hebben, moet het natuurlijk nog wel in machinetaal komen te staan. Alvorens dat te doen kiezen we voor een tweede tussenfase. We proberen de routine nu voor zover mogelijk in BASIC te plaatsen. We gaan uit van A*B=O waarbij A op adres &HA000 staat, B op adres &HA001 staat en O op &Ha002 en &Ha003 komt te staan. 10 B=PEEK (&HA000) 20 AFTEL=8 30 A=PEEK (&HA001) 40 D=0 50 O=0 60 REM Routine A ************** 70 C$=MID$(BIN$(B),AFTEL,1):C=VAL(C$) 80 IF C=0 THEN GOTO 100 90 O=O+A 100 REM Routine B ************** 110 A$=BIN$(A)+"0":A=VAL(A$) 120 AFTEL=AFTEL-1 130 IF AFTEL<>0 THEN 60 140 ' In machinetaal wordt nu d.m.v. een soort poke de oplossing (O) op &HA002 en &HA003 gezet. 150 end In regel 70 wordt gekeken of het eerst volgende getal waarmee we gaan vermenigvuldigen 0 of 1 is. In regel 110 wordt er een 0 achter getal A geplaatst. In machinetaal is dit echter zo eenvoudig niet. Hier werkt men in getallen-paren van 8 bits. Dus daar moet het getal naar links worden opgeschoven, de overgeblevene bewaardt, en er een 0 achter geplaatst. Vb.00000000 10111011 => Naar links schuiven 00000000 0111011 => 0 erbij 00000000 01110110 => Overgeblevene bit in volgend byte. 00000001 01110110 => Voor het maken van het machinetaal programma moeten we alleen nog de juiste instrukties weten. Laten we er een paar bespreken: SRL < variabele > ( In machinetaal:register ) Stel we geven de opdracht SRL D, dan gebeurt er het volgende. Net als hierboven beschreven wordt het getal verschoven, alleen nu naar rechts , het overgeblevene getal komt in de Carry-flag te staan (Ook een soort variabele) Vb. D=10111011 => SRL D => D=01011101 Carry=0 => => Carry=1 SLA < variabele > ( In machinetaal:register ) Zelfde als de vorige instruktie alleen dan naar links. Vb. D=10111011 => SLA D => D=01110110 Carry=0 => => Carry=1 RL < variabele > ( In machinetaal:register ) Zelfde als SLA, alleen komt nu de inhoud van de carry flag er vooraan bij. Vb. D=10111011 => RL D => D=01110110 Carry=0 => => Carry=1 Vb. D=00111011 => RL D => D=01110111 Carry=1 => => Carry=0 Verder is ADD optellen in machinetaal, DEC is aftrekken en ld is poke. Bij dit laatste moeten we nog wat opmerken: Vb. ld BC,(0A000H) - H=Hexadecimaal B=0 en C=PEEK(A000) Dan volgt nu het machinetaal programma in de assembler listing : 1 ld BC,(0A00H) 'Zet getal B in register C 2 ld B,08H 'Zet 8 in register B 3 ld DE,(0A001H) 'Zet getal A in register E 4 ld D,00H 'Zet 0 in register D 5 ld HL,00H 'Maak Carry-flag 0 6 label A:srl C 'Schuif bit in carry 7 jr NC,label B 'If not carry then label B 8 add hl,de 'HL=HL+A 9 label B:sla E 'Schuif A naar links 10 rl D 'Bewaar uitgeschoven bit in D 11 dec B 'Aftel=Aftel-1 12 jr nz,label A 'If aftel<>0 then label A 13 ld (0A002H),HL 'Zet antwoord in &HA002 en &HA003 14 ret 'Terug naar BASIC 15 end Dit programma kan alleen getallen tot 256 (8 bits) optellen. Het staat op diskette als VERMENIG.MSX (Te laden vanuit het softwaremenu of via FILER.SYS). Experimenteer er nog maar eens wat mee, dit programma is niet echt voor beginners. Ik zal misschien volgende keer, als er behoefte aan is, de cursus wat meer op echte beginners richten. Vragen en/of opmerkingen, Ronald Egas De Blauwe Wereld 53 1398 EP Muiden Tel.02942-3813 (s'avonds + weekends) |