FORTH
Úvod Výukové lekce  01 02 03 


   Lekce 2 - Aritmetické operace


   Mezi základní aritmetické operace patří sčítání, odčítání, násobení, dělení. Operandy jsou 16-bitová nebo 32-bitová čísla, se znaménkem nebo bez.
16-bitové číslo bez znaménka má rozsah 0 až 65535 (0 až FFFFh). Se znaménkem 0 až 32767 (0 až 7FFFh), záporné -32768 až -1 (ukládá se do paměti jako 8000h až FFFFh).  Záporné číslo se vytvoří dvojkovým doplňkem - znegují se bity a přičte se 1. Např. -3 je FFFCh+1=FFFDh.
32-bitové číslo bez znaménka má rozsah 0 až 4 294 967 295 (0 až FFFF FFFFh). Se znaménkem 0 až 2 147 483 647 (0 až 7FFF FFFFh), záporné
-2 147 483 648 až -1 (ukládá se do paměti jako 8000 0000h až FFFF FFFFh).
  Při násobení a dělení je třeba odlišovat, jestli počítáme se znaménkem nebo bez. Absolutní hodnoty se zpracují zvlášť a znaménka také zvlášť.

Příklad 3: Na následujícím Obr. 3 jsou prakticky vyzkoušeny některé aritmetické operace v F-PC .
 
FPC03
Obr. 3
+
(x1 x2 -- x3)
stav zásobníku
před a po operaci,
x1 - libovolné 16b číslo
plus x1+x2=x3  sečte dvě 16-bitová čísla, se znaménkem nebo bez, výsledek je 16-bitové číslo.
x1 a x2 se vyčtou ze zásobníku, na TOS se uloží x3.
Např. -1  3  +  .  provede -1+3, zobrazí 2. Záporné číslo -1 je vytvořeno dvojkovým doplňkem (znegovat bity čísla 1 a přičíst 1), tedy FFFEh+1=FFFFh. Přičtením 3 dostáváme výsledek 2, přetečení se ignoruje.
Např. 10000  30000  +  .  zobrazí -25536. Výsledek je větší než 32767, takže je číslo zobrazeno jako záporné. Pokud místo tečky použijeme U. , pak se výsledek zobrazí bez znaménka, tedy 40000. U čísel bez znaménka je maximální hodnota 65535.
plus
M+ (d1 n -- d2)
(x1 x2 x3 -- x4 x5)
d1-dvojnásobný rozsah, 32b
m-plus d1+n=d2  přičte 16-bitové číslo k 32-bitovému, výsledek je 32-bitové číslo.
x1 až x3 se vyčtou ze zásobníku, na TOS je vyšších 16b, na NOS nižších 16b.
Např. 2  1  30000  M+  D.  provede (2+1*65536) + 30000, zobrazí 95538. Na TOS je 1, na NOS je 30002. Když místo D. napíšeme U. U. zobrazí se 1  30002 .
mplus
D+ (d1 d2 -- d3)
(x1 x2 x3 x4 -- x5 x6)
d1 - dvojnásobný rozsah, 32b
d-plus d1+d2=d3  sečte dvě 32-bitová čísla, se znaménkem nebo bez, výsledek je 32-bitové číslo.
x1 až x4 se vyčtou ze zásobníku, na TOS je vyšších 16b, na NOS nižších 16b.
Např. -5  -1  3  0  D+  D.  provede -5+3, zobrazí -2. Nuly doplňují vyšších 16 bitů. Záporné číslo -5 je vytvořeno dvojkovým doplňkem (znegovat 5 a přičíst 1), tedy FFFF FFFAh+1=FFFF FFFBh. Přičtením 3 dostáváme výsledek -2 (FFFF FFFEh).
Např. 2  1  30000  0  D+  D.  provede (2+1*65536) + (30000+0*65536), zobrazí 95538. Na TOS je 1, na NOS je 30002. Když místo D. napíšeme U. U. zobrazí se 1  30002 .
dplus
1+ (x1 -- x2) one-plus x1+1=x2  přičte k 16-bitovému číslu na TOS číslo jedna, výsledek je 16-bitové číslo.
Na TOS je číslo zvětšené o 1.
Např. -3  1+  .  zobrazí -2 . Na TOS přečte -3, přičte 1 a uloží výsledek -2 na TOS.
oneplus
+! (x1 a-addr -- ) plus-store (a-addr)+1=>a-addr  přičte k obsahu adresy číslo x1.
Na TOS je adresa a-addr, přečte se její obsah, přičte se x1 a výsledek se uloží zpět na adresu a-addr. Slouží k přičtení čísla k proměnné (ta dává na TOS adresu, ne svoji hodnotu).
x1 a-adr jsme vyčetli ze zásobníku.
Např.
6 BASE +!  zvýší obsah proměnné BASE o 6 (z původních 10 na 16). Tímto se přepnete do šestnáctkové soustavy (příkazem DECIMAL zpátky do desítkové), viz. níže.
plusstore
- (x1 x2 -- x3) minus x1-x2=x3  odečte dvě 16-bitová čísla, se znaménkem nebo bez, výsledek je 16-bitové číslo.
x1 a x2 se vyčtou ze zásobníku, provede se NOS-TOS, na TOS se uloží x3.
Např. -1  3  -  .  provede -1-3, zobrazí se výsledek -4
minus
D- (d1 d2 -- d3)
(x1 x2 x3 x4 -- x5 x6)
d-minus d1-d2=d3  odečte dvě 32-bitová čísla, se znaménkem nebo bez, výsledek je 32-bitové číslo.
x1 až x4 se vyčtou ze zásobníku, na TOS je vyšších 16b, na NOS nižších 16b.
Např. 2  1  30000  0  D-  D. od čísla (2+1*65536) odečte (30000+0*65536), výsledek je 35538.
dminus
1- (x1 -- x2) one-minus x1-1=x2  odečte od 16-bitového čísla na TOS číslo jedna, výsledek je 16-bitové číslo.
Na TOS je číslo zmenšené o 1.
Např. -3  1-  .  zobrazí -4 . Na TOS vezme -3, odečte 1 a uloží výsledek -4 na TOS.
oneminus
* (n1 n2 -- n3)
n1-16b se znaménkem
star n1*n2=n3  vynásobí dvě 16-bitová čísla se znaménkem, výsledek je 16-bitové číslo.
n1 a n2 se vyčtou ze zásobníku, na TOS se uloží n3.
Např. 2 -3 * .  provede 2*(-3), zobrazí výsledek  -6 .
Např. 200  -300  *  .  provede 200*(-300), zobrazí 5536. Výsledkem násobení 200*300 je 60000, čemuž odpovídá číslo -5536, pro 200*(-300) tedy 5536.
STAR
M* (n1 n2 -- d1) m-star n1*n2=d1  vynásobí dvě 16-bitová čísla se znaménkem, výsledek je 32-bitové číslo.
n1 a n2 se vyčtou ze zásobníku, na TOS se uloží vyšších 16b d1,  na NOS nižžších 16b.
Např. 200  -3000  M*  D.  provede 200*(-3000), zobrazí výsledek -600000.
mstar
UM* (u1 u2 -- ud1)
u1-16b bez znaménka
ud1-32b bez znaménka
u-m-star u1*u2=ud1  vynásobí dvě 16-bitová čísla bez znaménka, výsledek je 32-bitové číslo.
u1 a u2 se vyčtou ze zásobníku, na TOS se uloží vyšších 16b ud1, na NOS nižžších 16b.
Např. 200  3000  UM*  D.  provede 200*3000, zobrazí výsledek 600000.
Např. 200  -3000  UM*  D.  provede 200*62536, zobrazí výsledek 12507200 (-3000 bere jako 62536, ne 3000 a minus).
umstar
/ (n1 n2 -- n3)

slash n1/n2=n3  vydělí dvě 16-bitová čísla se znaménkem, výsledek je 16-bitové číslo.
n1 a n2 se vyčtou ze zásobníku, provede se NOS/TOS, na TOS se uloží n3, zbytek není.
Např. 100  3 /  .  provede 100/3, zobrazí výsledek 33. Zbytek se do zásobníku neukládá.
Např. 100  -3 /  . provede 100/(-3), zobrazí výsledek -33 (-34 F-PC, Win32Forth).
slash
MOD (n1 n2 -- n3) mod n1 mod n2=n3  zbytek po dělení dvou 16b čísel se znaménkem, výsledek je 16-bitové číslo.
n1 a n2 se vyčtou ze zásobníku, provede se NOS mod TOS, na TOS se uloží zbytek n3.
Např. 100  3  MOD  .  provede 100/3, zobrazí výsledek 1 (100/3=33+1)
Např. 100  -3  MOD  .  provede 100/(-3), zobrazí výsledek 1 (-2 F-PC, Win32Forth).
mod
/MOD (n1 n2 -- n3 n4) slash-mod n1/n2=n3 + n4  vydělí dvě 16-bitová čísla se znaménkem, výsledek je 2x 16-bitové číslo.
n1 a n2 se vyčtou ze zásobníku, provede se NOS/TOS, na TOS se uloží podíl n4, na NOS zbytek n3.
Např. 100  3  /MOD  . .  provede 100/3, zobrazí výsledek 33  1.
Např. 100  -3  /MOD . . provede 100/(-3), zobrazí výsledek -33  1 (-34  -2 F-PC, Win32Forth).
slashmod
UM/MOD (ud1 u1 -- u2 u3)
u1-16b bez znaménka
ud1-32b bez znaménka
u-m-slash-mod ud1/u1=u2 + u3  vydělí 32-bitové číslo 16-bitovým číslem, bez znamének, výsledek je 2x 16-bitové číslo.
ud1 a u1 se vyčtou ze zásobníku, provede se NOS/TOS, na TOS se uloží podíl u3, na NOS zbytek u2.
Např. 100  0  3  UM/MOD . .  provede 100/3, zobrazí výsledek 33  1.
Např. 100  1  3  UM/MOD . .  provede (100+1*65536)/3, zobrazí výsledek 21878  2.
ummod
*/ (n1 n2 n3 -- n4) star-slash (n1*n2)/n3  vynásobí dvě 16-bitová čísla se znaménkem, výsledek je 32-bitové číslo, to vydělí 16-bitovým číslem, výsledek je 16-bitové číslo.
n1 n2 n3 se vyčtou ze zásobníku, na TOS se uloží podíl n4.
Např. 33  200  100  */  .  provede 33*200/100, zobrazí výsledek 66, což je 33% z 200.
starslash
*/MOD (n1 n2 n3 -- n4 n5) star-slash-mod (n1*n2)/n3  vynásobí dvě 16-bitová čísla se znaménkem, výsledek je 32-bitové číslo, to vydělí 16-bitovým číslem, výsledek je 2x 16-bitové číslo.
n1 n2 n3 se vyčtou ze zásobníku, na TOS se uloží podíl n5, na NOS zbytek n4.
Např. 33  201  100  */MOD  . .  provede 33*201/100, zobrazí výsledek 66  33.
starslmod
M*/ (d1 n1 +n2 -- d2)
+n2-nenulové kladné
m-star-slash (d1*n1)/n2  vynásobí 32-bitové číslo 16-bitovým, se znaménky, výsledek je 48-bitové číslo, to vydělí 16-bitovým číslem, výsledek je 32-bitové číslo.
d1 n1 n2 se vyčtou ze zásobníku, na TOS se uloží d2.
Např. 60000  33  100  M*/  .  provede 60000*33/100, zobrazí výsledek 19600 (Win32Forth - 32-bitové výpočty).
mstarslash
2* (x1 -- x2) two-star <--0  posune 16b o jeden bit vlevo, nejnižší bit je nula, hodnota se zvětší na dvojnásobek.
Na TOS je 16-bitové číslo.
Např. -15000  2*  .  zobrazí výsledek -30000.
Např.  32767  2*  .  přesun do záporných čísel, nejnižší bit doplní nulou, zobrazí -2.
2star
D2* (d1 -- d2) d-two-star <--0  posune 32b o jeden bit vlevo, nejnižší bit je nula, hodnota je dvojnásobná.
Na TOS, NOS je 32-bitové číslo.
Např. -15000  -1  D2*  D.  (-1 je vyšších 16b) zobrazí výsledek -30000.
Např. 32767  1  D2*  D.  provede (32767+1*65536)*2, zobrazí výsledek 196606.
d2star
2/ (x1 -- x2) two-slash s-->  posune 16b o jeden bit vpravo, nejvyšší bit zůstává, hodnota je poloviční.
Na TOS je 16-bitové číslo.
Např. -15000  2/  .  zobrazí výsledek -7500.
Např. 40000  2/  U.  zkopíruje bit 15, proto zobrazí 52768 (20000+32768).
2slash
D2/ (d1 -- d2) d-two-slash s-->  posune 32b o jeden bit vpravo, nejvyšší bit zůstává, hodnota je poloviční.
Na TOS, NOS je 32-bitové číslo.
Např. -15000  -1  D2/  D.  (-1 je vyšších 16b) zobrazí výsledek -7500.
Např. 40000  0  D2/  D.  zobrazí 20000 (bit 31 je 0).
d2slash
ABS (n -- u)
n-16b se znaménkem
u-16b bez znaménka
abs | n |   absolutní hodnota z 16-bitového čísla se znaménkem (odstraní minus).
Na TOS je 16-bitové číslo, u záporného čísla provedl dvojkový doplněk.
Např. -2  ABS  .  zobrazí 2.
abs
DABS (d -- ud)
d-32b se znaménkem
ud-32b bez znaménka
d-abs | d |   absolutní hodnota z 32-bitového čísla se znaménkem (odstraní minus).
Na TOS, NOS je 32-bitové číslo.
Např. -2  -1  DABS  D.  zobrazí 2.
dabs
NEGATE (n1 -- n2) negate Negace - změna znaménka +/- , dvojkový doplněk (negace bitů a přičte 1).
Na TOS je 16-bitové číslo.
Např. -2 NEGATE . 3 NEGATE .  zobrazí 2  -3.
negate
DNEGATE (d1 -- d2) d-negate Negace - změna znaménka +/- , dvojkový doplněk.
Na TOS, NOS je 32-bitové číslo.
Např. -2  0  NEGATE  D.  3  0  NEGATE  D.  zobrazí 2  -3.
dnegate
BASE ( -- a-addr) base Základ číselné soustavy - proměnná určující, v jaké soustavě se zobrazují čísla, desítková, hexadecimální, binární, atd. Na TOS se uloží adresa proměnné.
Např. 2  BASE  !  do proměnné BASE uloží 2, nastaví binární soustavu.
Např.  1001  0011  *  .  zobrazí  11011  (9*3=27)
base
DECIMAL ( -- ) decimal Desítková soustava - čísla budou zobrazována v desítkové soustavě.
Např.  HEX  1A  1B  DECIMAL  . .  zobrazí 27  26.
HEX ( -- ) hex Hexadecimální soustava - čísla budou zobrazována v hexadecimální soustavě.
Např.  DECIMAL  26  27  HEX  . .  zobrazí 1B  1A.
____________________________________________________________________________________________________________________
22.11.2007 - Luboš Pěkný, čerpáno z  X3J14 dpANS-6.