V již dvacáté první části seriálu o použití assembleru v Linuxu dokončíme téma, kterému jsme se začali věnovat minule. Jedná se o způsob použití podmínek (resp. přesněji řečeno instrukcí s podmínkami) při zpracování dat na moderní 64bitové mikroprocesorové architektuře AArch64. Procesory s touto architekturou totiž kromě podmíněných skoků podporují i některé další instrukce s podmínkou, které byly navrženy a implementovány na základě výsledků studie reálných aplikací.
Obsah
1. Použití assembleru v Linuxu: podmínky při zpracování dat na architektuře AArch64
2. Již známé instrukce: podmíněné skoky
4. Instrukce CSET – Conditional Set
5. Instrukce CSETM – Conditional Set Mask
6. Instrukce CSEL – Conditional Select
7. Instrukce CSINV – Conditional Select Invert
8. Instrukce CSINC – Conditional Select Increment
9. Instrukce CSNEG – Conditional Select Negate
10. Instrukce CINC – Conditional Increment
11. Instrukce CINV – Conditional Invert
12. Instrukce CNEG – Conditional Negate
13. Instrukce TBZ a TBNZ (Test and Branch...)
1. Použití assembleru v Linuxu: podmínky při zpracování dat na architektuře AArch64
V dnešní části seriálu o použití assembleru v Linuxu se zaměříme na poměrně zajímavou a prozatím relativně novou oblast. Jedná se o speciální instrukce implementované na moderní mikroprocesorové architektuře AArch64, které prování specifikovanou činnost pouze za předpokladu, že je splněna nějaká zadaná podmínka (kód podmínky je přitom součástí instrukčního slova). Připomeňme si, že na rozdíl od původní 32bitové architektury ARM (dnes označované ARM32) nemají všechny instrukce na AArch64 rezervovány čtyři nejvyšší bity pro specifikaci podmínky. Tato vlastnost byla na základě analýzy existujících programových strojových kódů zrušena a podmínky je tak možné použít jen u vybrané množiny instrukcí. Do této množiny byly zahrnuty i zcela nové instrukce, které na ARM32 nenalezneme, což je opět důsledek analýzy stávajících strojových kódů, ale i studia funkce překladačů.
Poznámka: podle některých vývojářů může mít extenzivní použití příznakových bitů negativní vliv na výkonnost procesoru, což je však téma, které je řešeno nejenom na AArch64, ale i na x86-64.
Připomeňme si, že na procesorové architektuře AArch64 je použito celkem čtrnáct různých podmínek, k nimž se někdy přidává i pseudopodmínka AL neboli Any/Always. V tomto případě se samozřejmě o žádnou skutečnou podmínku nejedná, neboť je instrukce provedena v každém případě.
Prvních šest podmínek testuje hodnotu pouze jediného bitového příznaku, a to N (negative), Z (zero) či V (overflow):
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
0000 | EQ | Z = 1 | rovnost po porovnání (či nulový výsledek) |
0001 | NE | Z = 0 | nerovnost po porovnání (či nenulový výsledek) |
0100 | MI | N = 1 | výsledek je záporný |
0101 | PL | N = 0 | výsledek je kladný či nulový |
0110 | VS | V = 1 | nastalo přetečení (overflow) |
0111 | VC | V = 0 | nenastalo přetečení (overflow) |
1110 | AL | Any/Always | většinou se nezapisuje, implicitní podmínka |
Další čtyři podmínkové kódy se většinou používají při porovnávání dvou hodnot bez znaménka (unsigned). V těchto případech se testují stavy příznakových bitů C (carry) a Z (zero), přesněji řečeno kombinace těchto bitů:
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
0010 | CS/HS | C = 1 | ≥ |
0011 | CC/LO | C = 0 | < |
1000 | HI | C = 1 & Z = 0 | > |
1001 | LS | C = 0 | Z = 1 | ≤ |
Poslední čtyři podmínkové kódy se používají pro porovnávání hodnot se znaménkem (signed). V těchto případech se namísto příznakových bitů (C) carry a (Z) zero testují kombinace bitů (N) negative, (V) overflow a (Z) zero:
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
1010 | GE | N == V | ≥ |
1011 | LT | N ≠ V | < |
1100 | GT | Z = 0, N = V | > |
1101 | LE | Z = 1, N ≠ V | ≤ |
Důležité je, že všechny dále popsané instrukce podporují všechny podmínky. Výjimku tvoří minule popsané instrukce CBZ a CBNZ, které pouze testovaly nulovost či naopak nenulovost vybraného pracovního registru.
2. Již známé instrukce: podmíněné skoky
Již minule jsme se zmínili o některých instrukcích provedených či naopak neprovedených na základě nějaké podmínky. Jednalo se o tyto instrukce:
Instrukce | Stručný popis |
---|---|
B.podmínka návěští | podmíněný skok po splnění podmínky na zadané návěští (kódy podmínek byly uvedeny výše) |
CBZ Wn, návěští | pokud platí Wn=0, skok na zadané návěští |
CBZ Xn, návěští | pokud platí Xn=0, skok na zadané návěští |
CBNZ Wn, návěští | pokud platí Wn≠0, skok na zadané návěští |
CBNZ Xn, návěští | pokud platí Xn≠0, skok na zadané návěští |
Tyto instrukce jsou (ve své variantě s 32bitovými registry) zpětně kompatibilní s instrukcemi známými z 32bitové architektury ARM32.
3. Nové instrukce
Mezi nové instrukce s podmínkou, které lze použít na architektuře AArch64, patří především:
Instrukce | Význam mnemotechnického kódu | Kapitola |
---|---|---|
CSET | Conditional Set | 4 |
CSETM | Conditional Set Mask | 5 |
CSEL | Conditional Select | 6 |
CSINV | Conditional Select Invert | 7 |
CSINC | Conditional Select Increment | 8 |
CSNEG | Conditional Select Negate | 9 |
CINC | Conditional Increment | 10 |
CINV | Conditional Invert | 11 |
CNEG | Conditional Negate | 12 |
TBZ | Test and Branch if Zero | 13 |
TBNZ | Test and Branch if not zero | 13 |
4. Instrukce CSET – Conditional Set
První novou instrukcí, s níž se dnes seznámíme, je instrukce nazvaná CSET neboli Conditional Set. Tato instrukce vlastně přímo odpovídá požadavkům kladeným na datový typ boolean v mnoha programovacích jazycích, v nichž je hodnota true interně reprezentována jedničkou a hodnota false nulou. Tato instrukce existuje ve dvou variantách, přičemž první varianta pracuje s 32bitovým a druhá varianta s 64bitovým operandem):
CSET Wd, condition
CSET Xd, condition
Například:
CSET W3, EQ
CSET W4, MI
CSET X5, HI
Tato instrukce pracuje následujícím způsobem – v případě, že je podmínka zapsaná ve druhém operandu cond splněna, uloží se do cílového registru Wd či do registru Xd hodnota 1. Pokud podmínka naopak splněna není, uloží se do registru Wd či Xd hodnota 0:
cíl = condition ? 1 : 0;
Ve skutečnosti se v případě CSET jedná o alias pro instrukci CSINC popsanou dále (podmínka ovšem musí být v tomto případě negována):
CSINC Wd, WZR, WZR, invert(condition)
CSINC Xd, XZR, XZR, invert(condition)
neboli:
cíl = invert(condition) ? 0 : 0+1;
5. Instrukce CSETM – Conditional Set Mask
V některých případech je nutné ukládat pravdivostní hodnoty odlišným způsobem – true bude reprezentováno hodnotou, v níž jsou všechny bity nastaveny na jedničku (v případě celých čísel se znaménkem to odpovídá hodnotě -1), false naopak hodnotou, v níž jsou všechny bity nulové. V tomto případě lze pro nastavení použít instrukci CSETM:
CSETM Wd, condition
CSETM Xd, condition
Ve vyšším programovacím jazyce by bylo možné napsat:
cíl = condition ? -1 : 0;
Poznámka: u 32bitového registru odpovídá -1 hodnotě 0xffff ffff, u 64bitového registru pak hodnotě 0xffff ffff ffff ffff.
Opět se jedná o aliasy, tentokrát ovšem na instrukci CSINV:
CSINV Wd, WZR, WZR, invert(condition)
CSINV Xd, XZR, XZR, invert(condition)
Poznámka: slovo „mask“ v názvu instrukce skutečně poměrně přesně odpovídá jednomu způsobu použití, protože pokud platí true=-1 a false=0, lze s těmito hodnotami provádět logický součin a součet bit po bitu, a to i v případě, kdy je druhým operandem odlišná hodnota.
6. Instrukce CSEL – Conditional Select
Další užitečnou instrukcí s podmínkou je instrukce zapisovaná mnemotechnickým kódem CSEL neboli Conditional Select. I tato instrukce existuje ve dvou variantách – 32bitové a 64bitové:
CSEL Wd, Wn, Wm, condition
CSEL Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena hodnota z druhého zdrojového registru Wm/Xm.
Instrukce CSEL tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : zdroj2;
7. Instrukce CSINV – Conditional Select Invert
Alternativní formou instrukce CSEL je instrukce CSINV neboli Conditional Select Invert:
CSINV Wd, Wn, Wm, condition
CSINV Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena negovaná hodnota přečtená z druhého zdrojového registru Wm/Xm.
Instrukce CSINV tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : ~zdroj2;
Poznámka: znak ~ je používán v programovacím jazyku C a od něj odvozených jazycích pro zápis unárního operátoru negace všech bitů (jedničkový doplněk).
8. Instrukce CSINC – Conditional Select Increment
Zajímavá je instrukce CSINC, která kombinuje možnosti instrukce CINC a CSEL:
CSINC Wd, Wn, Wm, condition
CSINC Xd, Xn, Xm, condition
Tato instrukce provádí následující činnost:
Wd = condition ? Wn : Wm+1;
Xd = condition ? Xn : Xm+1;
Jak jsme si již řekli ve čtvrté kapitole, je touto instrukcí realizována i pseudoinstrukce CSET, a to tehdy, pokud jsou oba zdrojové registry nulové (WZR a XZR). V tomto případě se do cílového registru dosadí 0 či 0+1=1:
CSINC Wd, WZR, WZR, invert(condition)
CSINC Xd, XZR, XZR, invert(condition)
9. Instrukce CSNEG – Conditional Select Negate
Instrukce nazvaná CSNEG se do jisté míry podobá instrukci CSINV, ovšem s tím rozdílem, že se namísto jedničkového doplňku (negace) používá při nesplnění podmínky dvojkový doplněk:
CSNEG Wd, Wn, Wm, condition
CSNEG Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena hodnota přečtená z druhého zdrojového registru Wm/Xm, u které se nejdříve změní znaménko (onen zmíněný dvojkový doplněk).
Tato instrukce tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : -zdroj2;
10. Instrukce CINC – Conditional Increment
Instrukce CINC je aliasem pro instrukci CSINC, ovšem s převrácenou podmínkou a shodnými zdrojovými registry:
CINC Wd, Wn, condition
CINC Xd, Xn, condition
Tato instrukce provádí následující činnost (je zde jen jediný zdrojový registr):
Wd = condition ? Wn+1 : Wn;
Xd = condition ? Xn+1 : Xn;
Použití této instrukce je různé, může se například použít pro realizaci příkazu continue v programovacím jazyku C.
11. Instrukce CINV – Conditional Invert
Podobná instrukce taktéž s jedním zdrojovým registrem se jmenuje CINV:
CINV Wd, Wn, condition
CINV Xd, Xn, condition
Prováděná činnost je následující (tilda znamená negaci bit po bitu):
Wd = condition ? ~Wn : Wn;
Xd = condition ? ~Xn : Xn;
Ve skutečnosti se opět jedná o instrukční alias rozpoznávaný assemblery. V tomto případě lze CINV nahradit instrukcí CSINV s oběma zdrojovými registry totožnými:
CSINV Wd, Wn, Wn, invert(condition)
CSINV Xd, Xn, Xn, invert(condition)
12. Instrukce CNEG – Conditional Negate
Poslední instrukce, přesněji řečeno (opět) instrukční alias se jmenuje CNEG:
CNEG Wd, Wn, condition
CNEG Xd, Xn, condition
Prováděná činnost:
Wd = condition ? -Wn : Wn;
Xd = condition ? -Xn : Xn;
Tento alias lze nahradit za CSNEG s totožnými zdrojovými registry a opačně zapsanou podmínkou:
CSNEG Wd, Wn, Wn, invert(condition)
CSNEG Xd, Xn, Xn, invert(condition)
13. Instrukce TBZ a TBNZ (Test and Branch...)
Poslední dvě instrukce, které si dnes popíšeme, spadají do kategorie podmíněných skoků. Tyto instrukce se jmenují TBZ (Test and Branch if Zero) a TBNZ (Test and Branch if Not Zero). Způsob zápisu těchto instrukcí je následující:
TBZ Xn, #konstanta, návěští
TBZ Wn, #konstanta, návěští
TBNZ Xn, #konstanta, návěští
TBNZ Wn, #konstanta, návěští
Konstanta má šířku pouze šest bitů, protože je v ní uložen index bitu pracovního registru, který se testuje na nulu či jedničku (u registrů Wn by stačilo jen pět bitů). V případě instrukce TBZ – pokud je n-tý bit registru Xn/Wn nastavený na nulu, provede se skok, v opačném případě se řízení přenese na další instrukci. V případě instrukce TBNZ je bit testován na nulu. Vzhledem k tomu, že v instrukčním slovu je nutné kromě adresy cíle (návěští) specifikovat i číslo pracovního registru a index bitu, je tento typ skoku omezen na rozsah ±32kB, což by ovšem v praxi mělo být více než dostačující (v opačném případě lze TBZ/TBNZ zkombinovat s absolutním skokem B).
14. Odkazy na Internetu
- Cortex-A35
https://www.arm.com/products/processors/cortex-a/cortex-a35-processor.php - Cortex-A53
https://www.arm.com/products/processors/cortex-a/cortex-a53-processor.php - Cortex-A57
https://www.arm.com/products/processors/cortex-a/cortex-a57-processor.php - Cortex-A72
https://www.arm.com/products/processors/cortex-a/cortex-a72-processor.php - Cortex-A73
https://www.arm.com/products/processors/cortex-a/cortex-a73-processor.php - System cally pro AArch64 na Linuxu
https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/unistd.h - Architectures/AArch64 (FedoraProject.org)
https://fedoraproject.org/wiki/Architectures/AArch64 - SIG pro AArch64 (CentOS)
https://wiki.centos.org/SpecialInterestGroup/AltArch/AArch64 - The ARMv8 instruction sets
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - A64 Instruction Set
https://developer.arm.com/products/architecture/instruction-sets/a64-instruction-set - Switching between the instruction sets
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - The A64 instruction set
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - Introduction to ARMv8 64-bit Architecture
https://quequero.org/2014/04/introduction-to-arm-architecture/ - MCU market turns to 32-bits and ARM
http://www.eetimes.com/document.asp?doc_id=1280803 - Cortex-M0 Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0.php - Cortex-M0+ Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0plus.php - ARM Processors in a Mixed Signal World
http://www.eeweb.com/blog/arm/arm-processors-in-a-mixed-signal-world - ARM Architecture (Wikipedia)
https://en.wikipedia.org/wiki/ARM_architecture - ARM Documentation: B, BL, BX, BLX, and BXJ
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/Cihfddaf.html - Branch and Call Sequences Explained
https://community.arm.com/groups/processors/blog/2013/09/25/branch-and-call-sequences-explained - Improving ARM Code Density and Performance
New Thumb Extensions to the ARM Architecture Richard Phelan - Aarch64 Register and Instruction Quick Start
https://wiki.cdot.senecacollege.ca/wiki/Aarch64_Register_and_Instruction_Quick_Start - Exploring AArch64 assembler – Chapter 1
http://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter1/ - Exploring AArch64 assembler – Chapter 2
http://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter-2/ - The ARM Processor Architecture
http://www.arm.com/products/processors/technologies/instruction-set-architectures.php - Thumb-2 instruction set
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344c/Beiiegaf.html - Introduction to ARM thumb
http://www.eetimes.com/discussion/other/4024632/Introduction-to-ARM-thumb - ARM, Thumb, and ThumbEE instruction sets
http://www.keil.com/support/man/docs/armasm/armasm_CEGBEIJB.htm - An Introduction to ARM Assembly Language
http://dev.emcelettronica.com/introduction-to-arm-assembly-language - Processors - ARM
http://www.arm.com/products/processors/index.php - The ARM Instruction Set
http://simplemachines.it/doc/arm_inst.pdf - ARM Architecture (Wikipedia)
http://en.wikipedia.org/wiki/ARM_architecture - C Functions Without Arguments
https://eklitzke.org/c-functions-without-arguments - GNU Assembler Examples
http://cs.lmu.edu/~ray/notes/gasexamples/ - Simply FPU
http://www.website.masmforum.com/tutorials/fptute/ - Art of Assembly language programming: The 80x87 Floating Point Coprocessors
https://courses.engr.illinois.edu/ece390/books/artofasm/CH14/CH14-3.html - Art of Assembly language programming: The FPU Instruction Set
https://courses.engr.illinois.edu/ece390/books/artofasm/CH14/CH14-4.html - INTEL 80387 PROGRAMMER'S REFERENCE MANUAL
http://www.ragestorm.net/downloads/387intel.txt - x86 Instruction Set Reference: FLD
http://x86.renejeschke.de/html/file_module_x86_id_100.html - x86 Instruction Set Reference: FLD1/FLDL2T/FLDL2E/FLDPI/FLDLG2/FLDLN2/FLDZ
http://x86.renejeschke.de/html/file_module_x86_id_101.html - x86 Instruction Set Reference: FLD
http://x86.renejeschke.de/html/file_module_x86_id_100.html - x86 Instruction Set Reference: FST/FSTP
http://x86.renejeschke.de/html/file_module_x86_id_117.html - x86 Instruction Set Reference: BTC
http://x86.renejeschke.de/html/file_module_x86_id_23.html - x86 Instruction Set Reference: BTR
http://x86.renejeschke.de/html/file_module_x86_id_24.html - x86 Instruction Set Reference: BTS
http://x86.renejeschke.de/html/file_module_x86_id_25.html - x86 Instruction Set Reference: BSF
http://x86.renejeschke.de/html/file_module_x86_id_19.html - x86 Instruction Set Reference: BSR
http://x86.renejeschke.de/html/file_module_x86_id_20.html - x86 Instruction Set Reference: BSWAP
http://x86.renejeschke.de/html/file_module_x86_id_21.html - x86 Instruction Set Reference: XCHG
http://x86.renejeschke.de/html/file_module_x86_id_328.html - x86 Instruction Set Reference: SETcc
http://x86.renejeschke.de/html/file_module_x86_id_288.html - X86 Assembly/Arithmetic
https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic - Art of Assembly - Arithmetic Instructions
http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_6/CH06-2.html - The GNU Assembler Tutorial
http://tigcc.ticalc.org/doc/gnuasm.html - The GNU Assembler - macros
http://tigcc.ticalc.org/doc/gnuasm.html#SEC109 - ARM subroutines & program stack
http://www.toves.org/books/armsub/ - Generating Mixed Source and Assembly List using GCC
http://www.systutorials.com/240/generate-a-mixed-source-and-assembly-listing-using-gcc/ - Calling subroutines
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0100a/armasm_cihcfigg.htm - ARM Assembly Language Programming
http://peter-cockerell.net/aalp/html/frames.html - ASM Flags
http://www.cavestory.org/guides/csasm/guide/asm_flags.html - Status Register
https://en.wikipedia.org/wiki/Status_register - Intel x86 JUMP quick reference
http://unixwiz.net/techtips/x86-jumps.html - Linux assemblers: A comparison of GAS and NASM
http://www.ibm.com/developerworks/library/l-gas-nasm/index.html - Programovani v assembleru na OS Linux
http://www.cs.vsb.cz/grygarek/asm/asmlinux.html - Is it worthwhile to learn x86 assembly language today?
https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1 - Why Learn Assembly Language?
http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language - Is Assembly still relevant?
http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant - Why Learning Assembly Language Is Still a Good Idea
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html - Assembly language today
http://beust.com/weblog/2004/06/23/assembly-language-today/ - Assembler: Význam assembleru dnes
http://www.builder.cz/rubriky/assembler/vyznam-assembleru-dnes-155960cz - Assembler pod Linuxem
http://phoenix.inf.upol.cz/linux/prog/asm.html - AT&T Syntax versus Intel Syntax
https://www.sourceware.org/binutils/docs-2.12/as.info/i386-Syntax.html - Linux Assembly website
http://asm.sourceforge.net/ - Using Assembly Language in Linux
http://asm.sourceforge.net/articles/linasm.html - vasm
http://sun.hasenbraten.de/vasm/ - vasm – dokumentace
http://sun.hasenbraten.de/vasm/release/vasm.html - The Yasm Modular Assembler Project
http://yasm.tortall.net/ - 680x0:AsmOne
http://www.amigacoding.com/index.php/680x0:AsmOne - ASM-One Macro Assembler
http://en.wikipedia.org/wiki/ASM-One_Macro_Assembler - ASM-One pages
http://www.theflamearrows.info/documents/asmone.html - Základní informace o ASM-One
http://www.theflamearrows.info/documents/asminfo.html - Linux Syscall Reference
http://syscalls.kernelgrok.com/ - Programming from the Ground Up Book - Summary
http://savannah.nongnu.org/projects/pgubook/ - IBM System 360/370 Compiler and Historical Documentation
http://www.edelweb.fr/Simula/ - IBM 700/7000 series
http://en.wikipedia.org/wiki/IBM_700/7000_series - IBM System/360
http://en.wikipedia.org/wiki/IBM_System/360 - IBM System/370
http://en.wikipedia.org/wiki/IBM_System/370 - Mainframe family tree and chronology
http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_FT1.html - 704 Data Processing System
http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_PP704.html - 705 Data Processing System
http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_PP705.html - The IBM 704
http://www.columbia.edu/acis/history/704.html - IBM Mainframe album
http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_album.html - Osmibitové muzeum
http://osmi.tarbik.com/ - Tesla PMI-80
http://osmi.tarbik.com/cssr/pmi80.html - PMI-80
http://en.wikipedia.org/wiki/PMI-80 - PMI-80
http://www.old-computers.com/museum/computer.asp?st=1&c=1016 - The 6502 overflow flag explained mathematically
http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html - X86 Opcode and Instruction Reference
http://ref.x86asm.net/coder32.html