Nedílnou součástí prakticky všech moderních mikroprocesorů i některých mikrořadičů je modul určený pro provádění operací s hodnotami s plovoucí řádovou čárkou. S některými možnostmi nabízenými tímto modulem, který se v minulosti označoval termínem „matematický koprocesor“, se ve stručnosti seznámíme v dnešním článku.

Obsah

1. Použití assembleru v Linuxu: práce s matematickým koprocesorem

2. Rozdíl mezi celočíselnými operacemi a operacemi s hodnotami s plovoucí řádovou čárkou

3. Norma IEEE 754 a její varianty

4. Způsob interní reprezentace hodnot s plovoucí řádovou čárkou

5. Formát single – hodnoty s jednoduchou přesností

6. Uložení znaménka, mantisy a exponentu ve formátu single

7. Speciální hodnoty s exponenty 0 a 255

8. Denormalizovaná čísla, hodnoty typu NaN a nekonečna

9. Formát double – hodnoty s dvojnásobnou přesností

10. Rozšířený formát extended/temporary

11. Pracovní registry matematického koprocesoru

12. Řídicí registr

13. Stavový registr

14. Základní instrukce – načítání dat do registrů

15. Aritmetické operace

16. Odkazy na Internetu

1. Použití assembleru v Linuxu: práce s matematickým koprocesorem

Na všech mikroprocesorech s architekturou i386 i x86-64 a taktéž u většiny mikroprocesorů s architekturou ARM (s výjimkou některých menších mikrořadičů řady Cortex-M či starších čipů předchozí generace) nalezneme modul, který je určený pro provádění operací s hodnotami reprezentovanými v takzvaném systému plovoucí řádové čárky. V angličtině se používá označení floating point, protože při zápisu desetinných čísel se zde používá tečka a nikoli čárka. Tento modul se z historických důvodů nazývá „matematický koprocesor“, a to proto, že v minulosti se skutečně jednalo o samostatný čip, který bylo možné na základní desku počítače nainstalovat až ve chvíli, kdy to bylo vzhledem k provozovaným úlohám nezbytné (typicky se jednalo o osobní mikropočítače, na nichž se provozoval CAD popř. se na něm v tabulkovém procesoru zpracovávaly rozsáhlejší tabulky s mnoha výpočty). Později se matematický koprocesor stal nedílnou součástí mikroprocesoru, což znamená, že dnes již není nutné testovat jeho přítomnost, provádění všech operací s plovoucí řádovou čárkou je rychlejší (sdílí se společná interní sběrnice) a taktéž není nutné explicitně čekat na dokončení výpočtů.

V dnešním článku se seznámíme především s instrukcemi i s principem práce s hodnotami s plovoucí řádovou čárkou, který je použit na mikroprocesorech s architekturou i386 a x86-64. Až příště si řekneme, jakým způsobem lze podobné výpočty provádět na čipech s architekturou ARM (tam je totiž situace poněkud složitější vzhledem k mnoha různým variantám, s nimiž se můžeme setkat).

2. Rozdíl mezi celočíselnými operacemi a operacemi s hodnotami s plovoucí řádovou čárkou

Již v úvodu je nutné upozornit na fakt, že zpracování hodnot s plovoucí řádovou čárkou se v mnoha ohledech odlišuje od zpracování celočíselných hodnot. Je tomu tak hned z několika důvodů. U celočíselných hodnot je u všech současných mikroprocesorových architektur totiž předem zřejmé, jaké hodnoty lze uložit do zvoleného n-bitového slova. Například u osmibitových slov je při použití čísel bez znaménka možné reprezentovat hodnoty od 0 do 255 (včetně), zatímco u čísel se znaménkem (konkrétně s dvojkovým doplňkem) jsou to hodnoty od -128 do 127. Navíc je při provádění základních aritmetických operací nutné sledovat pouze několik výjimečných stavů:

  1. Přenos u čísel bez znaménka (carry)
  2. Přetečení u čísel se znaménkem (overflow)
  3. Dělení nulou

Povšimněte si, že není nutné řešit například práci s nekonečnými hodnotami (kladné a záporné nekonečno), protože takové hodnoty stejně nelze nijak reprezentovat, čímž se detekce potenciálně neplatných výpočtů zjednodušuje. Není například nutné řešit, co se stane v případě pokusu o výpočet ∞-∞ nebo 0×∞, vlastně jedinou potenciálně problematickou operací je výpočet x/0 a speciálně též 0/0 (setkáme se dokonce s ALU, kde je výsledek tohoto výpočtu jednička).

Naproti tomu u hodnot reprezentovaných v systému plovoucí řádové čárky může výjimečných stavů nastat mnohem více, a to i ve chvíli, kdy uvažujeme pouze čtyři základní aritmetické operace a ne speciality typu druhá odmocnina ze záporného čísla atd.:

  1. Přetečení
  2. Podtečení
  3. Práce s tzv. denormalizovanými čísly
  4. Operace s nekonečny (kladné, záporné)
  5. Neplatné operace typu 0/0, ∞-∞ nebo 0×∞
  6. Operace s hodnotami, které nejsou skutečná čísla (NaN)

Navíc se zde objevuje další problém, který u celých čísel nebylo nutné řešit – jakým způsobem se má provádět zaokrouhlení výsledků tak, aby je bylo možné uložit zpět do pracovních registrů.

3. Norma IEEE 754 a její varianty

Před popisem jednotlivých instrukcí určených pro provádění operací s hodnotami s plovoucí řádovou čárkou je nutné se seznámit s tím, jak jsou vlastně taková čísla interně reprezentována (tj. uložena v pracovních registrech či v operační paměti), protože způsob jejich reprezentace do značné míry určuje i přesnost, rozsah podporovaných hodnot, některá specifika (způsob porovnávání) apod. U naprosté většiny polovodičových čipů vyrobených v posledním čtvrtstoletí se pro reprezentaci numerických hodnot s plovoucí řádovou čárkou dodržují vybrané formáty (někdy i všechny formáty!) specifikované v normě IEEE 754, která sama je postupně rozšiřována a upřesňována. V normě IEEE 754, jejíž první verze je mimochodem v platnosti již od roku 1985, jsou specifikovány nejenom vlastní formáty uložení numerických hodnot v systému pohyblivé řádové čárky (FP formátu), ale i pravidla implementace základních aritmetických operací s těmito hodnotami, aplikace zaokrouhlovacích režimů, způsoby některých konverzí apod. Konkrétně je v této normě popsáno:

  1. Základní (basic) a rozšířený (extended) formát uložení numerických hodnot.
  2. Způsob provádění základních matematických operací:
    • součet
    • rozdíl
    • součin
    • podíl
    • zbytek po dělení
    • druhá odmocnina
    • porovnání
  3. Režimy zaokrouhlování.
  4. Způsob práce s denormalizovanými hodnotami.
  5. Pravidla konverze mezi celočíselnými formáty (integer bez a se znaménkem) a formáty s plovoucí řádovou čárkou.
  6. Způsob konverze mezi různými formáty s plovoucí řádovou čárkou (singledouble atd.).
  7. Způsob konverze základního formátu s plovoucí řádovou čárkou na řetězec číslic (včetně nekonečen a nečíselných hodnot).
  8. Práce s hodnotami NaN (not a number) a výjimkami, které mohou při výpočtech za určitých předpokladů vzniknout.

4. Způsob interní reprezentace hodnot s plovoucí řádovou čárkou

Vybraná podmnožina racionálních čísel může být vyjádřena vztahem:

XFP=(-1)s × 2exp-bias × m

přičemž význam jednotlivých symbolů ve vztahu je následující:

  • XFP značí reprezentovanou numerickou hodnotu z podmnožiny racionálních čísel (ta je zase podmnožinou čísel reálných). Díky vyhrazeným (speciálním) hodnotám je možné rozlišit kladnou a zápornou nulu i kladné a záporné nekonečno, což je jeden z důležitých rozdílů oproti způsobu reprezentace celých čísel. Také se může uložit nečíselná hodnota: NaN – (Not a Number), která je výsledkem některých matematicky nedefinovaných operací, například 0/0 nebo 00.
  • 2 je báze, někdy také nazývaná radix, u normy IEEE 754 je to vždy dvojka, protože výpočty s bází dvě jsou pro číslicové obvody nejjednodušší. V minulosti se používaly i jiné báze, například 8, 16 nebo i 10, s nimi se však již dnes prakticky nesetkáme.
  • exp je vždy kladná hodnota exponentu posunutého o hodnotu bias
  • bias je hodnota, díky které je uložený exponent vždy kladný. Tato hodnota se většinou volí dle vztahu: bias=2eb-1-1, kde eb je počet bitů vyhrazených pro exponent. Pro specifické účely je však možné zvolit i jinou hodnotu.
  • m je mantisa, která je u formátů dle normy IEEE 754 vždy kladná
  • s je znaménkový bit nabývající hodnoty 0 nebo 1. Pokud je tento bit nulový, je reprezentovaná hodnota XFP kladná, v opačném případě se jedná o zápornou hodnotu. Vzhledem k tomu, že je jeden bit vyhrazen na uložení znaménka, je možné rozlišit kladnou a zápornou nulu.

5. Formát single – hodnoty s jednoduchou přesností

Podle bitové šířky čísel exp, bias a m se rozlišují základní (basic) a rozšířené (extended) formáty FP čísel; norma IEEE 754 přitom explicitně zmiňuje dva základní formáty: jednoduchá přesnost (single) a dvojitá přesnost (double).

Tento formát, který je v programovacích jazycích označován buď jako single či float, je charakteristický tím, že se pro uložení numerické hodnoty používá třiceti dvou bitů (4 byty), což pro mnoho aplikací představuje velmi dobrý poměr mezi rozsahem hodnot, přesností a nároky na úložný prostor, nehledě na to, že mnoho architektur stále používá 32 bitové sběrnice. Oněch 32 bitů je rozděleno do třech částí. V první části (představované nejvyšším bitem) je uloženo znaménko, následuje osm bitů pro uložení posunutého exponentu a za nimi je zbývajících 23 bitů, které slouží pro uložení mantisy. Celé třiceti dvoubitové slovo s FP hodnotou tedy vypadá následovně:

bit 31 30   29 … 24   23 22   21 … 3   2   1   0
význam s exponent (8 bitů) mantisa (23 bitů)

Exponent je přitom posunutý o hodnotu bias, která je nastavena na 127, protože je použit výše uvedený vztah:

bias=2eb-1-1

a po dosazení eb=8 (bitů) dostaneme:

bias=28-1-1=27-1=128-1=127

Vzorec pro vyjádření reálné hodnoty vypadá následovně:

Xsingle=(-1)s × 2exp-127 × m

6. Uložení znaménka, mantisy a exponentu ve formátu single

Uložení znaménka číselné hodnoty je jednoduché: pokud je znaménkový bit nastavený na jedničku, jedná se o zápornou hodnotu, v opačném případě jde o hodnotu kladnou. Exponent je uložený v takzvané posunuté formě, tj. jako binárně zakódované celé číslo v rozsahu 0..255. Po vyjádření neposunutého exponentu dostáváme rozsah -127..128, obě krajní hodnoty jsou však použity pro speciální účely, proto dostáváme rozsah exponentů -126..127 pro normalizovaná čísla (krajními hodnotami jsou takové exponenty, které mají všechny bity buď jedničkové nebo naopak nulové). Ještě si však musíme říci, jakým způsobem je uložena mantisa. Ta je totiž většinou (až na velmi malá čísla) normalizovaná, což znamená, že se do mantisy ukládají pouze hodnoty v rozsahu <1,0;2,0-ε>. Vzhledem k tomu, že první bit umístěný před binární tečkou je u tohoto rozsahu vždy nastavený na jedničku, není ho zapotřebí ukládat, což znamená, že ušetříme jeden bit z třiceti dvoubitového slova. Pro normalizované hodnoty platí následující vztah:

Xsingle=(-1)s × 2exp-127(1.M)2

kde M je hodnota bitového vektoru mantisy, tj.:

M=m22-1+m21-2+m20-3+…+m1-22+m0-23

Rozsah hodnot, jež je možné reprezentovat pomocí jednoduché přesnosti v normalizovaném tvaru je -3,4×1038 až 3,4×1038. Nejnižší reprezentovatelná (normalizovaná) hodnota je rovna 1,17549×10-38, denormalizovaná pak 1,40129×10-45. Jak jsme k těmto hodnotám došli? Zkuste se podívat na následující vztahy:

hexadecimální hodnota výpočet FP dekadický výsledek normalizováno
0x00000001 2-126×2-23 1,40129×10-45 ne
0x00800000 2-126 1,17549×10-38 ano
0x7F7FFFFF (2-2-23)×2127 3,4×1038 ano

7. Speciální hodnoty s exponenty 0 a 255

Ještě si musíme vysvětlit význam těch exponentů, které mají minimální a maximální hodnotu, tj. jsou buď nulové, nebo mají hodnotu 255 (obě samozřejmě před posunem). Vše je přehledně uvedeno v následující tabulce:

s-bit exponent mantisa význam šestnáctkově
0 0<e<255 >0 normalizované kladné číslo
1 0<e<255 >0 normalizované záporné číslo
0 0 >0 denormalizované kladné číslo
1 0 >0 denormalizované záporné číslo
0 0 0 kladná nula 0x00000000
1 0 0 záporná nula 0x80000000
0 255 0 kladné nekonečno 0x7F800000
1 255 0 záporné nekonečno 0xFF800000
0 255 >0 NaN – not a number
1 255 >0 NaN – not a number

8. Denormalizovaná čísla, hodnoty typu NaN a nekonečna

Pojmem denormalizovaná čísla označujeme takové hodnoty, u kterých není první (explicitně nevyjádřený) bit mantisy roven jedničce, ale naopak nule. Výpočty s těmito velmi malými hodnotami nejsou přesné, zejména při násobení a dělení (a samozřejmě i všech odvozených operacích). Při ukládání denormalizovaných čísel je exponent vždy nastaven na nejnižší hodnotu, tj. na -126 a nejvyšší (explicitně neukládaný) bit mantisy je vždy nulový, nikoli jedničkový, jak je tomu u normalizovaných hodnot. Hodnota typu NaN vznikne v případě, že je použita operace s nejasným výsledkem, například 0/0, 00 nebo, a to v praxi snad nejčastěji, při odmocňování záporných čísel. Nekonečná hodnota vzniká typicky při dělení nulou (zde je možné zjistit znaménko), nebo při vyjádření funkcí typu log(0) atd.

9. Formát double – hodnoty s dvojnásobnou přesností

Formát s dvojitou přesností (double), který je definovaný taktéž normou IEEE 754, se v mnoha ohledech podobá formátu s jednoduchou přesností (single), pouze se zdvojnásobil celkový počet bitů, ve kterých je hodnota uložena, tj. místo 32 bitů se používá 64 bitů. Právě to je hlavní příčinou toho, proč se tento formát nazývá double, ve skutečnosti je totiž přesnost více než dvojnásobná. 64 bitů alokovaných pro FP hodnotu je v tomto případě rozděleno následujícím způsobem:

  1. 1 bit pro znaménko
  2. 11 bitů pro exponent
  3. 52 bitů pro mantisu

Bitově vypadá rozdělení následovně:

bit 63 62 … 52 51 … 0
význam s exponent (11 bitů) mantisa 52( bitů)

Exponent je v tomto případě posunutý o hodnotu bias=2047 a vzorec pro výpočet reálné hodnoty vypadá takto:

Xdouble=(-1)s × 2exp-2047 × m

Přičemž hodnotu mantisy je možné pro normalizované hodnoty získat pomocí vztahu:

m=1+m51-1+m50-2+m49-3+…+m0-52

(mx představuje x-tý bit mantisy)

Rozsah hodnot ukládaných ve dvojité přesnosti je -1,7×10308..1,7×10308, nejmenší možná nenulová hodnota je rovna 2,2×10-308. Minimální a maximální hodnota exponentu má opět speciální význam, který je vysvětlen (spolu s normalizovanými čísly) v následující tabulce:

s-bit exponent mantisa význam
0 0<e<2047 >0 normalizované kladné číslo
1 0<e<2047 >0 normalizované záporné číslo
0 0 >0 denormalizované kladné číslo
1 0 >0 denormalizované záporné číslo
0 0 0 kladná nula
1 0 0 záporná nula
0 2047 0 kladné nekonečno
1 2047 0 záporné nekonečno
0 2047 >0 NaN – not a number
1 2047 >0 NaN – not a number

10. Rozšířený formát extended/temporary

Kromě obou základních formátů (tj. jednoduché i dvojité přesnosti) je v normě IEEE 754 povoleno používat i rozšířené formáty. Na platformě x86 je při výpočtech prováděných v matematickém koprocesoru používán rozšířený formát nazývaný extended či temporary. Tento formát je zajímavý tím, že pro uložení FP hodnot používá 80 bitů a je do něho možné beze ztráty přesnosti uložit 64bitové hodnoty typu integer (což je v mnoha oblastech velmi důležité). Osmdesátibitový vektor je rozdělený do třech částí následujícím způsobem:

  • 1 bit pro znaménko
  • 15 bitů pro exponent (BIAS je roven 16383)
  • 64 bitů pro mantisu (maximální hodnota přesahuje 104932)

U tohoto formátu je zajímavá funkce bitu s indexem 63. Podle hodnoty tohoto bitu se rozlišují čísla normalizovaná a nenormalizovaná (tento bit ve skutečnosti nahrazuje implicitně nastavovaný nejvyšší bit mantisy, jak ho známe z předchozích formátů). Matematické koprocesory řady 80×87 sice dokážou pracovat s čísly nenormalizovanými, výsledkem jeho aritmetických operací jsou však vždy hodnoty normalizované. Všechny možnosti, které mohou při ukládání extended FP formátu nastat, jsou přehledně vypsány v následující tabulce:

s-bit exponent mantisa m63 význam
0 0<e<32767 >0 1 normalizované kladné číslo
1 0<e<32767 >0 1 normalizované záporné číslo
0 0<e<32767 >0 0 nenormalizované kladné číslo
1 0<e<32767 >0 0 nenormalizované záporné číslo
0 0 >0 0 denormalizované kladné číslo
1 0 >0 0 denormalizované záporné číslo
0 0 0 x kladná nula
1 0 0 x záporná nula
0 32767 0 x kladné nekonečno
1 32767 0 x záporné nekonečno
0 32767 >0 x NaN – not a number
1 32767 >0 x NaN – not a number

Pro normalizované i nenormalizované hodnoty je možné uloženou hodnotu vyjádřit pomocí vzorce (všimněte si, že bit 63 je umístěn před binární tečkou):

Xextended=(-1)s × 2exp-16383 × m

m=m630+m62-1+m61-2+…+m0-63

11. Pracovní registry matematického koprocesoru

Matematický koprocesor má k dispozici celkem osm pracovních registrů, přičemž každý registr má šířku osmdesáti bitů. To znamená, že je možné provádět operace s hodnotami s rozšířenou (extended) přesností a samozřejmě taktéž s přesností jednoduchou (single) a dvojitou (double). Zajímavé a dnes již poněkud neobvyklé je, že zmíněných osm registrů tvoří zásobník, takže instrukce pro načítání hodnot ve skutečnosti provádí uložení na vrchol zásobníku, aritmetické operace pracují se dvěma registry na vrcholu zásobníku atd. U mnoha instrukcí je však možné toto pravidlo porušit a zvolit si registry explicitně, popř. zakázat odstranění původních operandů ze zásobníku. Zápis jmen registrů vypadá takto: ST(0), ST(1) atd. (pořadí registru v zásobníku se průběžně mění). Moderní FPU již tento zásobníkový koncept, který byl výhodný pro starší a méně dobré překladače, zcela odstranily.

12. Řídicí registr

Kromě pracovních registrů obsahuje matematický koprocesor i řídicí registr (control register). Ten má šířku pouze šestnáct bitů a obsahuje masky výjimek, které mohou nastat při provádění různých operací, dále pak dva bity pro volbu zaokrouhlovacího režimu a taktéž dva bity pro volbu přesnosti jednotlivých výpočtů:

# Označení Význam
0 IM maska výjimky Invalid Operation
1 DM maska výjimky Denormalized Operand
2 ZM maska výjimky Zero Divide
3 OM maska výjimky Overflow
4 UM maska výjimky Underflow
5 PM maska výjimky Precision
6 ×
7 IE povolení přerušení (dnes nevyužito)
8 PC1 volba přesnosti výpočtů (viz tabulku níže)
9 PC2 -//-
10 RC1 volba zaokrouhlovacího režimu (viz tabulku níže)
11 RC2 -//-
12 IC dnes nepoužito, pro kompatibilitu s 80287
13 ×
14 ×
15 ×

Bity RC2 a RC1 se používají pro volbu zaokrouhlení:

RC2 RC1
0 0 zaokrouhlení na nejbližší sudé číslo (mantisa)
0 1 zaokrouhlení směrem k -∞
1 0 zaokrouhlení směrem k +∞
1 1 zaokrouhlení směrem k nule

Bity PC2 a PC1 určují, zda se mají výpočty provádět s jednoduchou přesností, dvojitou přesností či s rozšířenou přesností:

PC2 PC1
0 0 32 bitů
0 1
1 0 64 bitů
1 1 80 bitů (výchozí)

Většinou není nutné obsah tohoto registru v průběhu výpočtů měnit.

13. Stavový registr

Jednotlivé matematické operace prováděné matematickým koprocesorem nastavují bity v takzvaném stavovém registru (status register). Tento registru má taktéž šířku šestnácti bitů a jeho struktura vypadá následovně:

# Označení Význam
0 IE výjimka Invalid Operation
1 DE výjimka Denormalized Operand
2 ZO výjimka Zero Divide
3 OE výjimka Overflow
4 UE výjimka Underflow
5 PE výjimka Precision
6 SF špatná manipulace se zásobníkem operandů
7 ES Error summary
8 C0 výsledek porovnání (příznakový bit)
9 C1 výsledek porovnání (příznakový bit)
10 C2 výsledek porovnání (příznakový bit)
11 ST0 ukazatel vrcholu zásobníku
12 ST1 ukazatel vrcholu zásobníku
13 ST2 ukazatel vrcholu zásobníku
14 C3 výsledek porovnání (příznakový bit)
15 B busy bit (provádí se operace)

Nejzajímavější jsou bity C0, C1, C2 a C3, protože do těchto bitů se ukládá například výsledek porovnání dvou hodnot atd. Tyto bity jsou ve stavovém registru umístěny tak, aby přesně odpovídaly umístění standardních příznaků v registru EFLAGS:

FPU EFLAGS
C0 carry flag
C1 undefined
C2 parity flag
C3 zero flag

Způsob použití si ukážeme příště.

14. Základní instrukce – načítání dat do registrů

V této kapitole si prozatím bez demonstračního příkladu vypíšeme základní instrukce určené pro načtení dat do registrů FPU. Jedná se o následujících osm instrukcí:

# Instrukce Význam
1 FLD načtení hodnoty typu single, double či extended z paměti či jiného registru
2 FLD1 načtení konstanty +1,0
3 FLDL2T načtení konstanty log210
4 FLDL2E načtení konstanty log2e
5 FLDPI načtení konstanty π
6 FLDLG2 načtení konstanty log102
7 FLDLN2 načtení konstanty loge2
8 FLDZ načtení konstanty +0,0 (kladná nula)

Hodnoty logaritmů se využijí v mnoha instrukcích, které si popíšeme příště.

15. Aritmetické operace

Mezi základní aritmetické operace patří především:

# Instrukce Význam
1 FADD součet
2 FSUB rozdíl
3 FSUBR rozdíl, ale operandy jsou prohozeny
4 FMUL součin
5 FDIV podíl
6 FDIVR podíl, ale operandy jsou prohozeny
7 FCHS změna znaménka
8 FABS výpočet absolutní hodnoty
9 FSQRT výpočet druhé odmocniny

16. Odkazy na Internetu

  1. Art of Assembly language programming: The 80×87 Floating Point Coprocessors
    https://courses.engr.illinois.edu/ece390/books/artofasm/CH14/CH14-3.html
  2. Art of Assembly language programming: The FPU Instruction Set
    https://courses.engr.illinois.edu/ece390/books/artofasm/CH14/CH14-4.html
  3. INTEL 80387 PROGRAMMER’S REFERENCE MANUAL
    http://www.ragestorm.net/downloads/387intel.txt
  4. x86 Instruction Set Reference: FLD
    http://x86.renejeschke.de/html/file_module_x86_id_100.html
  5. x86 Instruction Set Reference: FLD1/FLDL2T/FLDL2E/FLDPI/FLDLG2/FLDLN2/FLDZ
    http://x86.renejeschke.de/html/file_module_x86_id_101.html
  6. x86 Instruction Set Reference: BT
    http://x86.renejeschke.de/html/file_module_x86_id_22.html
  7. x86 Instruction Set Reference: BTC
    http://x86.renejeschke.de/html/file_module_x86_id_23.html
  8. x86 Instruction Set Reference: BTR
    http://x86.renejeschke.de/html/file_module_x86_id_24.html
  9. x86 Instruction Set Reference: BTS
    http://x86.renejeschke.de/html/file_module_x86_id_25.html
  10. x86 Instruction Set Reference: BSF
    http://x86.renejeschke.de/html/file_module_x86_id_19.html
  11. x86 Instruction Set Reference: BSR
    http://x86.renejeschke.de/html/file_module_x86_id_20.html
  12. x86 Instruction Set Reference: BSWAP
    http://x86.renejeschke.de/html/file_module_x86_id_21.html
  13. x86 Instruction Set Reference: XCHG
    http://x86.renejeschke.de/html/file_module_x86_id_328.html
  14. x86 Instruction Set Reference: SETcc
    http://x86.renejeschke.de/html/file_module_x86_id_288.html
  15. X86 Assembly/Arithmetic
    https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic
  16. Art of Assembly – Arithmetic Instructions
    http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_6/CH06-2.html
  17. The GNU Assembler Tutorial
    http://tigcc.ticalc.org/doc/gnuasm.html
  18. The GNU Assembler – macros
    http://tigcc.ticalc.org/doc/gnuasm.html#SEC109
  19. ARM subroutines & program stack
    http://www.toves.org/books/armsub/
  20. Generating Mixed Source and Assembly List using GCC
    http://www.systutorials.com/240/generate-a-mixed-source-and-assembly-listing-using-gcc/
  21. Calling subroutines
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0100a/armasm_cihcfigg.htm
  22. ARM Assembly Language Programming
    http://peter-cockerell.net/aalp/html/frames.html
  23. ASM Flags
    http://www.cavestory.org/guides/csasm/guide/asm_flags.html
  24. Status Register
    https://en.wikipedia.org/wiki/Status_register
  25. Intel x86 JUMP quick reference
    http://unixwiz.net/techtips/x86-jumps.html
  26. Linux assemblers: A comparison of GAS and NASM
    http://www.ibm.com/developerworks/library/l-gas-nasm/index.html
  27. Programovani v assembleru na OS Linux
    http://www.cs.vsb.cz/grygarek/asm/asmlinux.html
  28. Is it worthwhile to learn x86 assembly language today?
    https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1
  29. Why Learn Assembly Language?
    http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language
  30. Is Assembly still relevant?
    http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant
  31. Why Learning Assembly Language Is Still a Good Idea
    http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html
  32. Assembly language today
    http://beust.com/weblog/2004/06/23/assembly-language-today/
  33. Assembler: Význam assembleru dnes
    http://www.builder.cz/rubriky/assembler/vyznam-assembleru-dnes-155960cz
  34. Assembler pod Linuxem
    http://phoenix.inf.upol.cz/linux/prog/asm.html
  35. AT&T Syntax versus Intel Syntax
    https://www.sourceware.org/binutils/docs-2.12/as.info/i386-Syntax.html
  36. Linux Assembly website
    http://asm.sourceforge.net/
  37. Using Assembly Language in Linux
    http://asm.sourceforge.net/articles/linasm.html
  38. vasm
    http://sun.hasenbraten.de/vasm/
  39. vasm – dokumentace
    http://sun.hasenbraten.de/vasm/release/vasm.html
  40. The Yasm Modular Assembler Project
    http://yasm.tortall.net/
  41. 680×0:AsmOne
    http://www.amigacoding.com/index.php/680×0:AsmOne
  42. ASM-One Macro Assembler
    http://en.wikipedia.org/wiki/ASM-One_Macro_Assembler
  43. ASM-One pages
    http://www.theflamearrows.info/documents/asmone.html
  44. Základní informace o ASM-One
    http://www.theflamearrows.info/documents/asminfo.html
  45. Linux Syscall Reference
    http://syscalls.kernelgrok.com/
  46. Programming from the Ground Up Book – Summary
    http://savannah.nongnu.org/projects/pgubook/
  47. IBM System 360/370 Compiler and Historical Documentation
    http://www.edelweb.fr/Simula/
  48. IBM 700/7000 series
    http://en.wikipedia.org/wiki/IBM_700/7000_series
  49. IBM System/360
    http://en.wikipedia.org/wiki/IBM_System/360
  50. IBM System/370
    http://en.wikipedia.org/wiki/IBM_System/370
  51. Mainframe family tree and chronology
    http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_FT1.html
  52. 704 Data Processing System
    http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_PP704.html
  53. 705 Data Processing System
    http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_PP705.html
  54. The IBM 704
    http://www.columbia.edu/acis/history/704.html
  55. IBM Mainframe album
    http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_album.html
  56. Osmibitové muzeum
    http://osmi.tarbik.com/
  57. Tesla PMI-80
    http://osmi.tarbik.com/cssr/pmi80.html
  58. PMI-80
    http://en.wikipedia.org/wiki/PMI-80
  59. PMI-80
    http://www.old-computers.com/museum/computer.asp?st=1&c=1016
  60. The 6502 overflow flag explained mathematically
    http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html
  61. X86 Opcode and Instruction Reference
    http://ref.x86asm.net/coder32.html