Mathpack info v2 MCCM/WR/JvdM, 00-00-94 ############################################################################# ## ## ## MATH-PACK info - versie #2.00 ## ## ## ############################################################################# MPNED20.TXT (c) 1994 MCCM/WR/JvdM Met deze tekst be”gen wij een zo compleet mogelijk overzicht te geven van de officiele routines van de MATH-PACK (MP) en, in een later stadium, andere bruikbare aan de MP gerelateerde BASIC-routines. De auteurs stellen op- en aanmerkingen zeer op prijs, welke kunnen dienen om deze versie 2.00 verder te vervolmaken. Dat deze file nu bestaat is voornamelijk aan Waldo Ruiterman (WR) te danken die hiervoor het nodige 'koeliewerk' heeft verricht. Ik, Jan van der Meer (JvdM), teken voorlopig voor de tekst. Deze file is overigens PD en mag dus vrij verspreid worden via BBS'en of op wat voor andere, niet winstgevende, manier dan ook. Wat niet mag is dat je er wijzigingen in aanbrengt - hoe logisch die ook mogen lijken. Zie je een fout neem dan kontact met ons op via de aan het eind van deze file vermelde adressen/telefoonnummers. Allereerst wil ik kwijt dat je voor een goed gebruik van de MP over een behoorlijke dosis machinetaal-kennis en -ervaring dient te beschikken. Ook een meer dan basale kennis van het MSX-geheugenbeheer kan geen kwaad. Aan de andere kant acht ik het niet onmogelijk dat een studie MP je deze vaardigheden vanzelf afdwingt... Verwacht geen wonderen nu je deze file eenmaal hebt. De MATH-PACK laat zich nu eenmaal moeilijk temmen en dus zul je zelf ook het nodige spitwerk moeten verrichten. De navolgende informatie moet echter voldoende zijn om zonder al te veel problemen thuis te raken in MATH-PACK. Mijn (JvdM) ervaring is dat een pakket als WBASS2 alsook MSXDEBUG zich hier bij uitstek voor leent. Deze file is gebaseerd op de over de MP bestaande originele engelstalige literatuur. Deze literatuur werd niet alleen vertaald, doch aangezien hierin vele onduidelijkheden en zelfs fouten voorkomen, werd e.e.a. bewerkt en aange- vuld met wetenswaardige details, welke inmiddels zijn verzameld. Een bron van onduidelijkheden is het verschil tussen de door een MSX-computer gebruikte wetenschappelijke notatie voor uitvoer naar het beeldscherm en de wijze waarop getalswaarden van enkele- en dubbele-precisie intern opgeslagen worden in het geheugen. De engelse documentatie gebruikt deze interne notatie, welke E R U I T Z I E T als de bekende wetenschappelijke notatie (bekend van de uitvoer naar het scherm) D O C H D I T I N F E I T E N I E T I S. Aldus ontstaat er een spraakverwarring die we allereerst uit de wereld zullen helpen door het verschil tussen de interne- en de wetenschappelijke notatie duidelijk te maken. Het wegwijs worden in de documentatie wordt dan (hopen we) een stuk minder lastig. ALGEMENE DEFINITIES: -------------------- Elk getal, dat buiten de grenzen voor een integere waarde valt, wordt intern opgeslagen als een getal met drijvende decimale punt. Daarbij onderscheiden we enkele- en dubbele-precisie, waarbij respektievelijk 6 of 14 relevante cijfers worden gebruikt. Als voor het neerschrijven van een getal meer dan de genoemde 6 of 14 cijfers nodig zouden zijn (excl. decimale punt) dan wordt door een MSX-computer in basic c.q. directmode voor de uitvoer naar het beeldscherm de wetenschappelijke notatie gebruikt. (letter "E" gevolgd door exponentwaarde) De 6 of 14 relevante cijfers worden zonder decimale punt intern opgeslagen in BCD (binairy coded decimal). Daarbij wordt voor elk cijfer van een getal slechts de binaire code gebruikt voor de cijfers 0 t/m 9. Voor 1 cijfer zijn dan maar 4 bits (1 nibble) nodig. Er passen dus 2 cijfers in 1 byte. De 2 cijfers '39' b.v. worden binair 0011 en 1001. Samengevoegd tot 1 byte wordt dat 00111001. In hex uitgedrukt is de waarde van deze byte &H39. De 6 cijfers bij een getal van enkele precisie passen dus in 3 bytes. Deze serie van 6 cijfers heet "mantisse". Bij een getal van dubbele precisie bestaat de mantisse uit 14 relevante cijfers, passend in 7 bytes. De volgorde van de BCD gecodeerde bytes van de mantisse is hetzelfde als wanneer we die zouden opschrijven. B.v. de mantisse 12345678901234 bestaat achtereenvolgend uit de 7 bytes &H12, &H34, &H56, &H78, &H90, &H12 en &H34. De mantisse kan zowel op een positief- als een negatief getal betrekking hebben. Deze z.g. polariteit wordt gecodeerd in 1 byte tezamen met de waarde van de exponent en de polariteit daarvan. Deze z.g. exponentbyte is altijd de 1e byte. Daarna komen de 3 of 7 bytes voor de mantisse. Hoe de codering van de exponentbyte in elkaar steekt volgt later. De exponent wordt uitgedrukt met de term 'E+n' of 'E-n', waarbij n staat voor de getalswaarde van de exponent. De letter 'E' staat in feite voor de formule (in basic notatie) " * 10^ ". Dit betekent, dat we om de werkelijke waarde van het getal te krijgen, hetwelk door de mantisse en de exponent wordt voorge- steld, we de decimale punt bij een positieve exponent evenveel plaatsen naar rechts zouden moeten verschuiven als het getal van de exponent. Bij een nega- tieve exponent zou de decimale punt naar links i.p.v. naar rechts geschoven moeten worden. We moeten dus weten waar in de mantisse de decimale punt wordt geacht te staan om de werkelijke waarde van de kombinatie mantisse + exponent te kunnen achterhalen. De plaats waar de decimale punt geacht wordt te staan bij de interne notatie (opslag in het geheugen), is anders dan de plaats waar de decimale punt werkelijk staat als een MSX-computer een wetenschappelijke notatie op het scherm zet. Dit verschil moeten we kennen om vlot met de Mathpack-routines om te kunnen gaan. WETENSCHAPPELIJKE NOTATIE (uitvoer naar scherm) ------------------------- De decimale punt wordt geplaatst tussen het 1e en 2e cijfer van de mantisse. De exponent geeft het aantal plaatsen aan, dat de decimale punt verplaatst moet worden om de werkelijke waarde van het getal te verkrijgen. Positieve exponent: naar rechts. Negatieve exponent: naar links. INTERNE NOTATIE (opslag in het geheugen) --------------- De decimale punt wordt geacht te staan v¢¢r het 1e cijfer van de mantisse i.p.v. erachter zoals bij de wetenschappelijke notatie (zie boven). Omdat de decimale punt nu 1 plaats verder naar links staat dan bij de wetenschappe- lijke notatie, moet de exponent ook veranderd worden om dezelfde re‰ele waarde van het getal te behouden. Het gevolg van e.e.a. is, dat bij de wetenschappe- lijke notatie, die voor schermuitvoer wordt gebruikt, de waarde van de exponent altijd 1 lager (-1) is dan bij de interne notatie, welke in het geheugen staat. Voortaan zal de wetenschappelijke notatie worden aangeduid als " w.n. " en de interne notatie als " i.n. " Het verschil tussen i.n. en w.n. wordt duidelijk als we in directmode (basic) zouden typen: A=.12345678901234E+15: B=.12345678901234E-15: PRINT A,B <return> De MSX-computer zet dan op het scherm: 1.2345678901234E+14 1.234568901234E-16 De ingetypte waarden voor A & B waren overeenkomstig de i.n. Zo staan de mantisse en de exponent in het geheugen. Bij de uitvoer naar het scherm werd de w.n. gebruikt met als gevolg, dat waarde van de exponent bij w.n. 1 lager (-1) is dan de waarde van de exponent, welke in het geheugen staat (i.n.). Bij bovenstaand voorbeeld zou voor "A" ook 12345.678091234E+10 ingetypt kunnen worden. Onze komputer zet de mantisse volgens de i.n. in het geheugen, dus de decimale punt is 5 plaatsen naar links verhuisd (v¢¢r het 1e cijfer van de mantisse). Voor het verkrijgen van de re‰ele waarde zou de punt weer 5 plaatsen naar rechts verplaatst moeten worden en nog eens 10 plaatsen naar rechts vanwege "E+10". Als exponent-waarde wordt derhalve +5 +10 = +15 opgeslagen zodat de re‰ele waarde van het getal gelijkwaardig blijft. Alles wat we in direct-mode intypen is in feite een ascii-string, waarmee de getalswaarde wordt voorgesteld. Onze computer gebruikt ‚‚n van de MP-routines om die string om te zetten naar een re‰ele getalswaarde. Die MP-routine kun je o.a. vinden in de tabellen verderop. Het verschil tussen de w.n. en de i.n. moeten we kennen om een w.n. te kunnen vertalen naar de juiste waarden voor de mantisse en de exponent. De engelse documentatie gebruikt de i.n. daarbij worden de mantisse en de exponent steeds gegeven zoals die intern opgeslagen staan. Een mantisse bestaat altijd uit 6 of 14 cijfers. De getalswaarde van b.v. 123.4E-15 heeft maar 4 relevante cijfers. Bij de opslag hiervan wordt de mantisse aangevuld met nullen erachter tot 6 of 14 cijfers. De engelse documentatie geeft in zo'n geval ook alle erachter geplaatste nullen weer, welke in het geheugen zijn opgeslagen. Bij de w.n. op het scherm worden deze afsluitende nullen altijd weggelaten. De engelse notatie gebruikt gemakshalve de i.n. omdat daarbij de waarde van de exponent identiek is aan waarde van de exponent, die in de exponentbyte gecodeerd zit. Helaas werd verzuimd om te vermelden, dat dit niet de w.n. is, hoewel die daar wel erg op lijkt. Dit kan bij het gebruik van de MP-routines zeer verwarrend werken. In de diverse nog volgende voorbeelden, overzichten en tabellen zal naast de i.n. uit de engelse documentatie tevens de w.n. worden vermeld, zodat het verschil steeds duidelijk is. Onjuiste interpretatie hopen we daardoor te voorkomen. CODERING VAN EXPONENTBYTE ------------------------- In de exponentbyte staan 3 gegevens gecodeerd, te weten: Polariteit (teken) van het getal, polariteit van de exponent en waarde van de exponent. Alle bits = '0': De waarde van het getal (mantisse) is exakt nul. Bit 7 = '0': Mantisse positief (positief getal) Bit 7 = '1': Mantisse negatief (negatief getal) Bit 6 = '0': Exponent negatief (in bereik -1 t/m -63) Bits 0-5 vormen het 2-komplement van de absolute binaire waarde van de exponent Bit 6 = '1': Exponent positief (in bereik +0 t/m +63) Bits 0-5 vormen de binaire waarde van de exponent Opmerking: Voor het bepalen van de waarde van de exponent wordt de decimale punt geacht te staan v¢¢r het 1e cijfer van de mantisse. Het exponentbyte wordt als 1e byte in het geheugen opgeslagen. De 3 of 7 bytes van de mantisse volgen direkt daarna. Opslagplaats is: 'DAC' of 'ARG', zie verderop voor details & adressen. Aanwijzing voor minder gevorderden: 2-Komplement = Komplement +1 Voorbeeld vertaling naar 2 komplement: te vertalen waarde: -63 Absolute waarde = 63, binair: 111111 komplement: 000000 +1: 1 + ------ 2-komplement: 000001 = -63 Voorbeeld terugvertalen van 2-komplement naar absolute waarde: negatieve waarde uitgedrukt als 2-komplement: 000001 (-63) komplement: 111110 +1: 1 + ------ (nieuw 2-komplement) absolute waarde was: 111111 = 63 ============================================================================= De MATH-PACK (MP) is de kern voor de rekenkundige routines van MSX-BASIC. De MP bestaat uit een breed scala aan reken- en wiskundige routines welke, mits aan bepaalde voorwaarden is voldaan, ook vanuit een 'gewoon' ml-programma zijn aan te roepen c.q. te gebruiken. In wezen is de MP dan ook niet meer dan een verzameling van niet officiele BIOS-routines. Wel is het zo dat niet zelden zowel page 0 (#0000-#3FFF) alswel page 1 (#4000-#7FFF) gelijktijdig op de ROM geschakeld dienen te staan tijdens het gebruik van MP-routines. Bij de overgang van MSX1 naar MSX2 stonden de programmeurs van dit systeem voor het probleem dat, ook al waren de MP-routines niet officieel, er toch in zowel hun eigen code alswel in zeer veel MSX1 programma's er al een dusdanig veelvuldig en rechtstreeks gebruik van de MP-routines was gemaakt, dat ze eigenlijk geen keus meer hadden. Het feit dat ze het voor elkaar hebben gekre- gen deze routines op hetzelfde adres te houden verdient bewondering. Zo zijn er ook nog diverse BASIC-routines die hun plaats hebben behouden. Een programma dat hier listig gebruik van maakt is MSXCALC.TSR welke bij Jos de Boer (MS-actie) is te bestellen. In de MATH-PACK zijn een drietal adressen van groot belang. Dit zijn VALTYP (#F663), DAC (#F7F6...) en ARG (#F847...). VALTYP is een acroniem voor 'VALue TYPe' (waardetype). DAC en ARG staan respectievelijk voor 'Decimal ACumulator (decimale opslagplaats) en ARGument' (berekeningswaarde). Neem de voornoemde uitleg van DAC en ARG niet al te letterlijk op; want er is op allerlei manieren mee te goochelen. Het MATH-PACK werkgebied. ------------------------- --------------------------------------------------------------------------- | Label | Adres | Lengte | Betekenis | |--------|--------|--------|----------------------------------------------| | DAC | &HF7F6 | 16 | Decimal accumulator voor invoer en uitvoer *)| | ARG | &HF847 | 16 | Argument (2e getal voor berekeningen) | | VALTYP | &HF663 | 1 | Getalstypering of stringtypering | --------------------------------------------------------------------------- *) Getallen met drijvende decimale punt (floating point): Exponentbyte + mantisse in BCD notatie Enkele precisie in DAC+0 t/m DAC+3. Dubbele precisie in DAC+0 t/m DAC+7 Integer getal: Binair in DAC+2 (lowbyte) en DAC+3 (highbyte). (Negatieve waarde als 2-komplement) Voor zowel DAC als ARG zijn alleen de 1e 8 bytes van belang voor de program- meur. De 2e 8 bytes worden gebruikt door diverse basic en MP-routines. De 1-byte-waarde in (VALTYP) is 2, 3, 4 of 8 volgens onderstaand lijstje: 2 voor een 2-byte-integer Opslag in DAC+2 (lowbyte) en DAC+3 (highbyte) 3 voor een stringdescriptor 4 voor een enkel precisie getal Opslag in DAC+0 t/m DAC+3 8 voor een dubbel precisie getal Opslag in DAC+0 t/m DAC+7 De waarde 3 is thans onbelangrijk. We willen immers rekenen ! De waarde in VALTYP geeft niet alleen de getalstypering aan, doch geeft tevens het aantal van belang zijnde (significante) bytes in (DAC...) en/of (ARG...) Omdat de MATH-PACK eigenlijk een verzameling van BASIC-routines is zal er bij het optreden/konstateren van een fout (bijv. delen door nul of een "overflow") gepoogd worden naar BASIC terug te keren. Om dit te voorkomen zou de hook H.ERRO (&HFFB1) omgebogen moeten worden. Hier hopen we een andere keer op terug te komen. In feite dient elk machinetaalprogramma "eigen foutaf- handelingsroutines" te hebben als er kans is, dat er een foutmelding via de biosrom of de diskrom wordt geaktiveerd. TABEL 1: Formaat van getallen met drijvende decimale punt. (floating point) ----------------------------------------------------------- ----------------------------------------- Bitnummer | 7 | 6 5 4 3 2 1 0 | ------------|---|-----------------------| 1e byte ^ ^ |+/-| exponentcodering | | | -------|---------------------------| | | ^ | 1e cijfer | 2e cijfer | 2e byte enkele | | |-------------|-------------| precisie | | | 3e cijfer | 4e cijfer | 3e byte | | | |-------------|-------------| | | mantisse | 5e cijfer | 6e cijfer | 4e byte v | in |-------------|-------------|---------------- | BCD-formaat | 7e cijfer | 8e cijfer | 5e byte dubbele | |-------------|-------------| precisie | | 9e cijfer | 10e cijfer | 6e byte | | |-------------|-------------| | | | 11e cijfer | 12e cijfer | 7e byte | | |-------------|-------------| | v | 13e cijfer | 14e cijfer | 8e byte v ------------------------------------------------------------ Noot: De exponentcodering werd reeds eerder besproken, zie aldaar. Tabel 2: Voorbeelden van getalsuitdrukkingen. --------------------------------------------- Voorbeeld van een enkele precisie getal: 123456 ---> .123456E+6 (i.n.) ---> 1.23456E+5 (w.n.) DAC+0 +1 +2 +3 --------------------- Interne opslag (hex) in DAC: | 46 | 12 | 34 | 56 | --------------------- Voorbeeld van een dubbele precisie getal: 123456.78901234 ---> .12345678901234E+6 (i.n.) ---> 1.2345678901234E+5 (w.n.) DAC+0 +1 +2 +3 +4 +5 +6 +7 ----------------------------------------- Interne opslag (hex) in DAC: | 46 | 12 | 34 | 56 | 78 | 90 | 12 | 34 | ----------------------------------------- Noot: Bij MSX geldt, dat de wetenschappelijke notatie niet wordt gebruikt als de exponent ( bij i.n.) in het bereik -1 t/m +14 ligt. De schermuitvoer bij dit voorbeeld zal daarom identiek zijn aan de 1e notatie met de decimale punt achter het 6e cijfer. Een getalswaarde, door MSX op het scherm gezet, zal dus nooit eindigen op E-2 t/m E+13. MSX zet dan de decimale punt op de juiste plaats i.p.v. de w.n. te gebruiken. Tabel 3: Exponent formaat en grenzen. ------------------------------------- |+/- teken|<--exponent-codering-->| Betekenis: |---------|-----------------------|--------------------------------------- | 0 | 0 0 0 0 0 0 0 | Het getal c.q. de mantisse is exact nul |---------|-----------------------| | 1 | 0 0 0 0 0 0 0 | Niet toegestaan (* 10^-0 ???) |---------|-----------------------| | x | 0 0 0 0 0 0 1 | * 10^-63 (E-63) kleinste exponent |---------|-----------------------| | x | 1 0 0 0 0 0 0 | * 10^0 = * 1 (E+0) |---------|-----------------------| | x | 1 1 1 1 1 1 1 | * 10^63 (E+63) grootste exponent ----------------------------------- Noot: x = '0' Getal (mantisse) is positief x = '1' Getal (mantisse) is negatief De exponent-codering werd reeds eerder besproken, zie aldaar. Tabel 4: Geldige reeks dubbele precisie getallen. ------------------------------------------------- Byte| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Waarde van getal ----|----|----|----|----|----|----|----|----|------------------------------ DAC:| FF | 99 | 99 | 99 | 99 | 99 | 99 | 99 | -0.99999999999999E+63 (i.n.) | | | | | | | | | -9.9999999999999E+62 (w.n.) |----|----|----|----|----|----|----|----|------------------------------ DAC:| 81 | 10 | 00 | 00 | 00 | 00 | 00 | 00 | -0.10000000000000E-63 (i.n.) | | | | | | | | | -1E-64 (w.n.) |----|----|----|----|----|----|----|----|------------------------------ DAC:| 00 | x | x | x | x | x | x | x | 0 |----|----|----|----|----|----|----|----|------------------------------ DAC:| 01 | 10 | 00 | 00 | 00 | 00 | 00 | 00 | +0.10000000000000E-63 (i.n.) | | | | | | | | | +1E-64 (w.n.) |----|----|----|----|----|----|----|----|------------------------------ DAC:| 7F | 99 | 99 | 99 | 99 | 99 | 99 | 99 | +0.99999999999999E+63 (i.n.) | | | | | | | | | +9.9999999999999E+62 (w.n.) ----------------------------------------------------------------------- ============================================================================== =============== MATH-PACK ROUTINES EN HUN ENTRY-ADRESSEN =============== ============================================================================== PRIMAIRE REKENFUNKTIES: --------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|-------------------------------------------------------| | DECSUB | &H268C | DAC <--- DAC - ARG | | DECADD | &H269A | DAC <--- DAC + ARG | | DECNRM | &H26FA | normaliseert DAC: eventuele voorloopnullen worden | | | | uit de mantisse verwijderd. Exponent wordt aangepast | | | | op dec. punt voor 1e cijfer. Bijvoorbeeld: 0.001234 | | | | wordt: .12340000000000E-2 (i.n.) ---> 1.234E-3 (w.n.)| | DECROU | &H273C | rondt DAC af tot mantisse van 14 relevante cijfers. | | DECMUL | &H27E6 | DAC <--- DAC * ARG | | DECDIV | &H289F | DAC <--- DAC / ARG | --------------------------------------------------------------------------- Noot: Deze routines behandelen de getallen in DAC en ARG als dubbele precisie. De registers worden niet bewaard !!! GONIOMETRISCHE FUNCTIES, WORTELTREKKEN, KWADRATEREN & AFRONDEN: --------------------------------------------------------------------------- | Label | Adres | Funktie | Wijzigt registers | |--------|--------|-------------------------------|-----------------------| | COS | &H2993 | DAC <--- COS(DAC) | A,B,C,D,E,H en L | | SIN | &H29AC | DAC <--- SIN(DAC) | A,B,C,D,E,H en L | | TAN | &H29FB | DAC <--- TAN(DAC) | A,B,C,D,E,H en L | | ATN | &H2A14 | DAC <--- ATN(DAC) | A,B,C,D,E,H en L | | LOG | &H2A72 | DAC <--- LOG(DAC) | A,B,C,D,E,H en L | | SQR | &H2AFF | DAC <--- SQR(DAC) | A,B,C,D,E,H en L | | EXP | &H2B4A | DAC <--- EXP(DAC) | A,B,C,D,E,H en L | | RND | &H2BDF | DAC <--- RND(DAC) | A,B,C,D,E,H en L | --------------------------------------------------------------------------- Noot: Deze functies hebben dezelfde naam en functie als in BASIC. TEKEN-MANIPULATIES: ----------------------------------------------------------------------------- | Label | Adres | Funktie | Wijzigt register(s) | |--------|--------|-----------------------------------|---------------------| | SIGN | &H2E71 | AF <--- teken van DAC | A | | | | NC, Z (A = &H00) <--- DAC = 0| | | | | NC, NZ (A = &H01) <--- DAC > 0| | | | | C,S-vlag (A = &HFF) <--- DAC < 0| | | ABSFN | &H2E82 | DAC <--- ABS(DAC) | A,B,C,D,E,H,L | | | | Resultaat: Mantisse positief | | | NEG | &H2E8D | DAC <--- NEG(DAC) | A,H,L | | | | Teken mantisse + <---- - | | | | | of - <---- + | | | SGN | &H2E97 | DAC <--- SGN(DAC) | A,H,L | | | | Resultaat is 2 bytes integer | | | | | DAC+2 = &H00 <----- DAC = 0 | | | | | DAC+3 = &H00 <----- | | | | | | | | | | DAC+2 = &H01 <----- DAC > 0 | | | | | DAC+3 = &H00 <----- | | | | | | | | | | DAC+2 = &HFF <----- DAC < 0 | | | | | DAC+3 = &HFF <----- | | | | | (&HF663) <----- &H02 | | ----------------------------------------------------------------------------- Noot: De funktie SGN is identiek aan de BASIC-funktie SNG( < N > ) De funktie ABSFN is identiek aan de BASIC-funktie ABS( < N > ) (Overige funkties hebben geen equivalent in BASIC.) De funktie SIGN is soortgelijk als SGN. SIGN geeft echter het resultaat in het 'A' register en de vlaggen in het 'F' register zijn reeds gezet (voor gebruik in machinetaal). DAC en VALTYP (&HF663) blijven ongewijzigd bij SIGN !! DATA VERPLAATSINGEN: --------------------------------------------------------------------------- | Label | Adres | Funktie | Type variabele | wijzigt registers | |--------|--------|------------------|----------------|-------------------| | MAF | &H2C4D | ARG <--- DAC | dubb. precisie | A,B,D,E,H,L | | MAM | &H2C50 | ARG <--- (HL) | dubb. precisie | A,B,D,E,H,L | | MOV8DH | &H2C53 | (DE) <--- (HL) | dubb. precisie | A,B,D,E,H,L | | MFA | &H2C59 | DAC <--- ARG | dubb. precisie | A,B,D,E,H,L | | MFM | &H2C5C | DAC <--- (HL) | dubb. precisie | A,B,D,E,H,L | | MMF | &H2C67 | (HL) <--- DAC | dubb. precisie | A,B,D,E,H,L | | MOV8HD | &H2C6A | (HL) <--- (DE) | dubb. precisie | A,B,D,E,H,L | | XTF | &H2C6F | (SP) <--> DAC | dubb. precisie | A,B,D,E,H,L | | PHA | &H2CC7 | ARG <--- (SP) | dubb. precisie | A,B,D,E,H,L | | PHF | &H2CCC | DAC <--- (SP) | dubb. precisie | A,B,D,E,H,L | | PPA | &H2CDC | (SP) <--- ARG | dubb. precisie | A,B,D,E,H,L | | PPF | &H2CE1 | (SP) <--- DAC | dubb. precisie | A,B,D,E,H,L | | PUSHF | &H2EB1 | DAC <--- (SP) | enk. precisie | D,E | | MOVFM | &H2EBE | DAC <--- (HL) | enk. precisie | B,C,D,E,H,L | | MOVFR | &H2EC1 | DAC <--- (CBED) | enk. precisie | D,E | | MOVRF | &H2ECC | (CBED) <--- DAC | enk. precisie | B,C,D,E,H,L | | MOVRMI | &H2ED6 | (CBED) <--- (HL) | enk. precisie | B,C,D,E,H,L | | MOVRM | &H2EDF | (BCDE) <--- (HL) | enk. precisie | B,C,D,E,H,L | | MOVMF | &H2EE8 | (HL) <--- DAC | enk. precisie | A,B,D,E,H,L | | MOVE | &H2EEB | (HL) <--- (DE) | enk. precisie | B,C,D,E,H,L | | VMOVAM | &H2EEF | ARG <--- (HL) | VALTYP | B,C,D,E,H,L | | MOVVFM | &H2EF2 | (DE) <--- (HL) | VALTYP | B,C,D,E,H,L | | VMOVE | &H2EF3 | (HL) <--- (DE) | VALTYP | B,C,D,E,H,L | | VMOVFA | &H2F05 | DAC <--- ARG | VALTYP | B,C,D,E,H,L | | VMOVFM | &H2F08 | DAC <--- (HL) | VALTYP | B,C,D,E,H,L | | VMOVAF | &H2F0D | ARG <--- DAC | VALTYP | B,C,D,E,H,L | | VMOVMF | &H2F10 | (HL) <--- DAC | VALTYP | B,C,D,E,H,L | --------------------------------------------------------------------------- Noot: Een registernaam tussen haakjes (DE), (HL), (SP) betekent, dat het betreffende register de pointer bevat naar het geheugenadres waar de 1e byte van de te verplaatsen 2, 4 of 8 databytes is (of moet worden-) opgeslagen. 4 Registernamen tussen haakjes zoals (CBED) bevatten een getal in enkele precisie: Van links naar rechts bevatten de 4 registers het exponentbyte (in C), mantissa 1e & 2e cijfer (in B), idem 3e & 4e cijfer (in E) en idem 5e & 6e cijfer (in D). "VALTYP" betekent dat het aantal te verplaatsen bytes (2, 4 of 8) en de juiste plaatsing in DAC of ARG bepaald wordt door de code voor het type variabele in geheugenplaats 'VALTYP' (&HF663). VERGELIJKINGEN: --------------------------------------------------------------------------- | Label | Adres | Type variabele | Links | Rechts | Wijzigt registers | |--------|--------|-----------------|--------|--------|-------------------| | FCOMP | &H2F21 | enk. precisie | CBED *)| DAC | H,L | | ICOMP | &H2F4D | 2-byte integer | DE | HL | H,L | | XDCOMP | &H2F5C | dubb. precisie | ARG | DAC | A,B,C,D,E,H,en L | --------------------------------------------------------------------------- *) In C: Teken & exponentcodering in B: 1e & 2e cijfer mantissa in E: 3e & 4e cijfer mantissa, in D: 5e & 6e cijfer mantissa Noot: Het resultaat komt in het A-register, de betekenis is: A=1 ----------> links < rechts A=0 ----------> links = rechts A=-1 (&HFF) ----> links > rechts INVOER ascii string, UITVOER (naar DAC) integer of getal met drijvende punt --------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|-------------------------------------------------------| | FIN | &H3299 | AsciiZ-string, welke een pos./neg. getal (met/zonder | | | | dec. punt) voorstelt wordt geconverteerd naar of een | | | | integer of een getal met drijvende punt (volgens in- | | | | terne notatie) en opgeslagen in DAC. & VALTYP | |-------------------------------------------------------------------------| | Invoer: HL <---- Pointer naar in geheugen opgeslagen ascii string. | | A <---- Eerste teken van de opgeslagen string. *) | | Uitvoer: DAC <---- Integer of getal van enkele- of dubbele-precisie. | | C <---- &HFF: Ascii string bevatte geen decimale punt. **) | | of &H00: Ascii string bevatte wel decimale punt. | | B <---- aantal bytes mantissa ***) | | D <---- Aantal numerieke karakters in de ascii string | | (&HF663) <---- VALTYP (&H02, &H04 of &H08) ****) | | Alle registers worden gewijzigd !! | --------------------------------------------------------------------------- Noot: De basic-rom moet reeds in page 1 aangeschakeld zijn. *) Data-invoer in het 'A' register is niet nodig bij Turbo-R. (genegeerd) **) Bij een integere waarde betekent "&HFF" dat het getal negatief is. ***) Alleen geldig bij getal in dubbele precisie. ****) De variabele codering die in VALTYP wordt gezet hangt af van de getalswaarde, welke de ascii-string blijkt voor te stellen. Als niet zeker is, dat de string een getal met dubbele precisie voorstelt, dan dienen v¢¢r het gebruik van deze routine de 8 geheugen- plaatsen DAC+0 t/m DAC+7 gewist te worden door ze te vullen met &H00. Een ascii-string, welke een getal voorstelt met decimale punt erin, wordt altijd geconverteerd naar een getal met drijvende decimale punt. (enkele of dubbele precisie) Voor een integere waarde mag de ascii-string bestaan uit: Alleen cijfers met teken erv¢¢r. (+ teken niet verplicht) of: &H.... 1 - 4 hex karakters of: &O.... 1 - 6 octal karakters (binnen range &O0 - &O177777) of: &B.... 1 - 16 binaire karakters "0" of "1" Voor een waarde in enkele- of dubbele precisie mag de string bestaan uit: Alleen cijfers met teken erv¢¢r (+teken niet verplicht) met- of zonder decimale punt. of: Een wetenschappelijke notatie. Notatie als macht (...^..) is niet toegestaan. CONVERSIE WAARDE IN DAC naar afdrukbare ascii-string --------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|-------------------------------------------------------| | FOUT | &H3425 | Conversie van (DAC) naar dubbele precisie en daarna | | | | conversie naar ascii-string. (&HF663) <---- &H08 | |-------------------------------------------------------------------------| | Waarde in DAC positief: 1e karakter van de string is een spatie. | | Waarde in DAC negatief: 1e karakter is minteken. DAC neg. ----> DAC pos.| | | | Indien de waarde van de exponent (i.n.) buiten het bereik -1 t/m +14 | | ligt, dan wordt de wetenschappelijke notatie gebruikt. (Decimale punt | | na 1e cijfer van de mantissa) | | uitvoer: HL <---- pointer naar startadres van de string. | --------------------------------------------------------------------------- Noot: De basic-rom moet reeds in page 1 aangeschakeld zijn. CONVERSIE WAARDE IN DAC naar afdrukbare geformatteerde ascii-string (Vergelijkbaar met basicfunktie "PRINT USING") --------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|-------------------------------------------------------| | PUFOUT | &H3426 | Als funktie FOUT (zie boven) doch geformateerd | |-------------------------------------------------------------------------| | invoer: A <---- formaat codering | | bit 7: 0 = ongeformateerd 1 = geformateerd | | bit 6: 0 = zonder komma's 1 = met komma's om de | | drie cijfers. | | bit 5: 0 = geen betekenis 1 = voorafgaande spaties | | worden opgevuld met | | punten. | | bit 4: 0 = geen betekenis 1 = een "$" wordt voor de| | waarde geplakt. | | bit 3: 0 = geen betekenis 1 = een "+" wordt voor | | een positieve waarde | | gezet. | | bit 2: 0 = geen betekenis 1 = het +/-teken komt na | | de waarde. | | bit 1: niet gebruikt | | bit 0: 0 = fixed point 1 = floating point | | B <---- aantal cijfers voor (excl.) de decimale punt. | | C <---- aantal cijfers na (incl.) de decimale punt. | | | | uitvoer: HL <---- pointer naar startadres van de string. | --------------------------------------------------------------------------- Noot: Indien het A register = &H00 dan wordt de inhoud van de overige registers genegeerd en de funktie FOUT (Label &H3425) uitgevoerd. De basic-rom moet reeds in page 1 aangeschakeld zijn !!! CONVERSIE INTEGER (in DAC) naar binaire/octal/hexadecimale ascii-string. --------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|-------------------------------------------------------| | FOUTB | &H371A | Maakt van de 2-byte integer in DAC+2, +3 een binair | | | | uitgedrukte ascii-string. | | FOUTO | &H371E | Maakt van de 2-byte integer in DAC+2, +3 een octaal | | | | uitgedrukte ascii-string. | | FOUTH | &H3722 | Maakt van de 2-byte integer in DAC+2, +3 een hexade- | | | | cimaal uitgedrukte ascii-string. | |-------------------------------------------------------------------------| | invoer: DAC+2 (lowbyte), DAC+3 (highbyte) <----- 2-byte integer | | VALTYP <--- 2 | | uitvoer: HL <--- Pointer naar beginadres van de string. | --------------------------------------------------------------------------- Noot: Er zijn geen strings gereserveerd. Het startadres van de string van de uitvoerroutine is normaal FBUFFR (vanaf &HF7C5). In sommige gevallen kan het enigzins verschillen. Dit geldt ook voor de routines "FOUT" en "PUFOUT" voor conversie naar een string. TYPE CONVERSIE: -------------------------------------------------------------------------- | label | adres | functie | |------------------------------------------------------------------------| | FRCINT | &H2F8A | Converteert (DAC) naar een 2-byte integer (DAC+2, 3).| | FRCSNG | &H2FB2 | Converteert (DAC) naar een enkele precisie waarde. | | FRCDBL | &H303A | Converteert (DAC) naar een dubbele precisie waarde. | | FIXER | &H30BE | (DAC) <--- SGN(DAC) * INT(ABS(DAC)) | | Alle registers kunnen gewijzigd worden | -------------------------------------------------------------------------- Noot: Na het aanroepen van een van deze routines, bevat VALTYP (&HF663) de code (2, 4 of 8) van het gewijzigde getalstype in DAC. De basic-rom moet reeds in page 1 aangeschakeld zijn !! Alle registers worden veranderd. REKENFUNKTIES MET 2 INTEGERE GETALLEN: (Positief +1 t/m +32767 of negatief -1 t/m -32768) -------------------------------------------------------------------------- | Label | Adres | Funktie | Wijzigt registers | |--------|--------|-------------------|----------------------------------| | UMULT | &H314A | DE <--- BC * DE | A,B,C,D,E | | ISUB | &H3167 | HL <--- DE - HL | Alle | | IADD | &H3172 | HL <--- DE + HL | Alle | | IMULT | &H3193 | HL <--- DE * HL | Alle | | IDIV | &H31E6 | HL <--- DE \ HL | Alle | | IMOD | &H323A | HL <--- DE mod HL | Alle | | | | DE <--- (2 * resultaat indien getallen positief) | -------------------------------------------------------------------------- Noot: De routine IDIV geeft, indien DE en HL beiden met een POSITIEF integer getal geladen waren, de rest * 2 terug in register DE. De rest verkrijgt men door (DE)/2. De routine IMOD heeft men dan niet nodig. Bij de routines IDIV en IMOD moeten BEIDE getallen positief of negatief zijn om een geldige uitkomst te verkrijgen. Negatieve getallen als twee complement! en #02 in VALTYP zetten. MACHTSVERHEFFEN: ----------------------------------------------------------------------------- | Label | Adres | Funktie | Grondtal | Macht | Resultaat | |--------|--------|--------------------------|----------|-------|-----------| | SGNEXP | &H37C8 | macht van enk. precisie | DAC | ARG | DAC | | DBLEXP | &H37D7 | macht van dubb. precisie | DAC | ARG | DAC | | INTEXP | &H383F | macht van 2-byte integer | DE | HL | DAC | ----------------------------------------------------------------------------- Noot: Alle registers worden gewijzigd. @@@ EXTRA: @@@ -------------------------------------------------------------------------- | Label | Adres | Funktie | |--------|--------|------------------------------------------------------| | PRTHL | &H3412 | Zet HL decimaal op het scherm. | -------------------------------------------------------------------------- Noot: Deze, wellicht meest gebruikte, MP-routine is niet officieel! Page 1 hoeft hierbij niet op de ROM te staan. Op en aanmerkingen over deze file graag sturen naar: Jan van der Meer Rensumaheerd 16 9736 AA Groningen ^/*\^ 050-417266 ;------------------------------------------------------------------ ;ML-PROGRAMMA VOOR UITVOERING VAN EEN MATHPACK ROUTINE WELKE OOK DE ;BASIC-ROM (in page 1) GEBRUIKT. B.v. mathpack-routine "FIN" ;Onderstaand programma werkt op elke MSX computer (in COM-files, geen basic) ;------------------------------------------------------------------- ;Opmerking: De inputbuffer (#F55E t/m #F65F = 258 bytes) wordt alleen gebruikt ; voor input via het toetsenbord en is dus vrij voor gebruik als ; geheugen in pagina 3. Omdat pagina 3 nooit weggeschakeld wordt kan ; dit geheugengebied gebruikt worden voor 'lastige' klussen, welke ; anders in conflict komen met benodigde slotomschakelingen. ; Gebruik van dit geheugengebied heeft als bijkomend voordeel, dat ; er geen geheugen behoeft te worden gereserveerd elders in pag. 3 LD HL,COPY_ML ;Beginadres te kopie‰ren ML-code LD DE,#F55E ;Input-buffer, te gebruiken als tijdelijke ; opslagplaats voor ML-routine LD BC,#004D ;Aantal bytes van ML-routine LDIR ;Kopi‰er ML-code naar input-buffer LD HL,GETAL ;Ascii-Z string (getalswaarde in ascii) LD DE,#F600 ;Opslagadres (in input-buffer) LD BC,#0016 ;Maximum mogelijke aantal bytes (21 + eindnul = 22) LDIR ;Ascii-Z string kopi‰ren naar input-buffer CALL #F55E ;ML-routine (in buffer) uitvoeren JR VERVOLG ;======================= ;--> Instellingen betreffende RAM in pag.1 opvragen en opslaan COPY_ML IN A,(#A8) ;Lees slotregister LD (#F65E),A ;Opslaan in input-buffer LD A,(#FFFF) ;Lees komplement van subslotregister CPL ;Converteer naar werkelijke inhoud van subslotregister LD (#F65F),A ;Opslaan in input-buffer ;--> Basic-ROM aanschakelen LD A,(#FCC1) ;Slotadres basic-ROM LD HL,#4000 ;Pagina identificatie CALL #0024 ;Schakel basic-ROM in pagina 1 ;--> Mathpack routine uitvoeren LD HL,#F600 ;Input benodigd voor MATHPACK routine "FIN" LD A,(HL) ;Idem PUSH IX ;Save PUSH IY ;Save ENTRY_M LD IX,#3299 ;Entry adres MATHPACK routine "FIN" ;Conversie ascii-Z naar notatie in 'DAC' & 'VALTYP' ;Het adres komt na kopi‰ren in #F57D te staan. Als ;er een andere routine nodig is kan het adres van die ;routine in #F5D7 worden ingevuld voordat de routine ;met "CALL #F55E" wirdt aangeroepen. LD IY,(#FCC0) ;Slot ID basic-ROM CALL #001C ;Call mathpack-routine ;--> RAM terugschakelen in pagina 1 LD A,(#F65E) ;Haal oude instelling slotregister OUT (#A8),A ;Herstel instelling slotregister LD A,(#F65F) ;Haal oude instelling subslotregister LD (#FFFF),A ;Herstel instelling subslotregister POP IY ;Herstel IY POP IX ;Herstel IX RET ;Terug naar normale ML-routine ;--------------- GETAL DEFB "12345.6789" ;(11 BYTES) voorbeeld van mogelijke ascii-Z string DEFS 11 ;+ 11 NUL-bytes = totaal 22 bytes ;======================== VERVOLG NOP ;Hier komt het vervolg van het ML-programma |