V předchozím článku jsme si ukázali, jakým způsobem je možné zkombinovat zdrojový kód napsaný v programovacím jazyku C s kódem psaným v assembleru. Přitom jsme se zaměřili na 32bitovou architekturu x86 (i386 až i686) a 64bitovou architekturu x86-64. Dnes si ukážeme kombinaci jazyka C a assembleru na mikroprocesorech s architekturou ARM.
Obsah
1. Kombinace assembleru a programovacího jazyka C na procesorech ARM
2. Seznam obecných jmen registrů použitých pro specifikaci vstupních a výstupních operandů
3. Zápis komentářů, zpracování bloku asm překladačem céčka
4. Pořadí zápisu operandů, specifikace konstant a jmen registrů
5. Vrácení hodnoty z bloku napsaného v assembleru
6. Větší množství výstupních operandů
7. Vstupní a výstupní operandy
8. Použití symbolických jmen v assemblerovském bloku: cesta k čitelnému zdrojovému kódu
9. Makefile určený pro překlad dnešních demonstračních příkladů
10. Repositář s demonstračními příklady
1. Kombinace assembleru a programovacího jazyka C na procesorech ARM
Již z předchozího článku víme, že překladač GNU C (ale nejenom on) podporuje zápis bloků s instrukcemi assembleru přímo do zdrojových kódů psaných v céčku či C++. To může být velmi výhodné, protože nám to umožňuje nejenom psaní celých subrutin (podprogramů) v assembleru, ale i kombinaci C a assembleru v rámci jedné funkce, tj. bez nutnosti explicitního volání subrutiny, předání parametrů a návratu ze subrutiny apod. Minule jsme si taktéž ukázali způsob specifikace vstupních a výstupních operandů uvnitř bloku asm či __asm__. Dnes budeme v popisu této problematiky pokračovat, ovšem zaměříme se především na 32bitovou architekturu ARM, která se od architektury x86/x86-64 v mnoha ohledech odlišuje. Týká se to samozřejmě i způsobu zápisu assemblerovských bloků, specifikací operandů atd.
Všechny demonstrační příklady, s nimiž se dnes seznámíme, byly odzkoušeny na dnes již postarším GCC překladači verze 4.6.3, kterou naleznete v původních instalacích Raspbianu (testování probíhalo na Raspberry Pi):
<strong>gcc --version</strong>
gcc (Debian 4.6.3-14+rpi1) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Verze GNU assembleru použitá pro otestování demonstračních příkladů:
<strong>as -version</strong>
GNU assembler (GNU Binutils for Debian) 2.24.51.20140425
Copyright (C) 2014 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-linux-gnueabihf'.
Poznámka: demonstrační příklady budou samozřejmě funkční i na novějším překladači a/nebo novější verzi GNU Assembleru. Budou taktéž funkční na novějších procesorech ARM s výjimkou řady Cortex-M, která neobsahuje podporu pro původní ARMovskou instrukční sadu.
2. Seznam obecných jmen registrů použitých pro specifikaci vstupních a výstupních operandů
Minule jsme si řekli, že při specifikaci vstupních a výstupních operandů celého assemblerovského bloku je nutné specifikovat, do jakých registrů se tyto operandy budou ukládat. Všechny příklady používaly obecné označení „r“ značící libovolný pracovní registr. Na platformě x86/x86-64 je možné registr zvolit explicitně, a to náhradou znaku „r“ v řetězci "=r" za jiný znak podle následující tabulky. Povšimněte si, že (alespoň prozatím) není možné explicitně použít vyšších osm pracovních registrů, tj. registry pojmenované R8 až R15. V samotném assemblerovském kódu však tyto registry samozřejmě lze využít:
Náhrada "r" | Význam |
---|---|
a | %rax, %eax, %ax, %al |
b | %rbx, %ebx, %bx, %bl |
c | %rcx, %ecx, %cx, %cl |
d | %rdx, %edx, %dx, %dl |
S | %rsi, %esi, %si |
D | %rdi, %edi, %di |
U 32bitových mikroprocesorů a mikrořadičů ARM se kromě běžných pracovních registrů spadajících do kategorie „r“ mohou používat i následující skupiny registrů. Povšimněte si, že některé skupiny jsou platné pouze v režimu ARM (původní RISCová instrukční sada), jiné naopak pouze v režimu Thumb. Některé skupiny dále vyžadují matematický koprocesor (VFP...) či rozšíření NEON:
Skupina registrů | Omezení | Význam |
---|---|---|
r | × | libovolný pracovní registr |
l | × | pracovní registr r0-r7 v režimu Thumb |
h | × | pracovní registr r8-r15 v režimu Thumb |
b | Thumb | pracovní registr r0-r7 popř. ukazatel na vrchol zásobníku |
f | FPA | registr f0-f7 |
t | VFP | registr s0-s31 (single) |
x | VFP | registr d0-d7 (double) |
w | VFP | registr d0-d15 (double) |
w | VFPv3 | registr d0-d31 (double) |
Poznámka: přesnou specifikaci registru (například „r0“) prozatím nelze provést.
3. Zápis komentářů, zpracování bloku asm překladačem céčka
Praktickou část začneme velmi jednoduchým příkladem, na němž si ukážeme jeden z rozdílů mezi assemblerovským blokem psaným pro architektury x86 a x86-64 na jedné straně a tímtéž blokem psaným pro ARMovskou 32bitovou architekturu na straně druhé. Nejprve se podívejme, jak se zapisují komentáře při použití procesorů Intel či AMD. Každý komentář v assemblerovském bloku začíná znakem # a platí až do konce aktuálního řádku:
#include <stdio.h>
int main()
{
__asm__ __volatile__(
"nop \n\t"
" nop \n\t"
" nop \n\t"
" nop \n\t"
" nop # komentar \n\t"
: /* zadne vystupni registry */
: /* zadne vstupni operandy */
: /* zadne registry pouzivane uvnitr kodu */
);
return 0;
}
Naprosto stejný příklad, ovšem psaný pro 32bitovou architekturu ARM, používá odlišné komentáře. Ty začínají znakem @ a taktéž platí až do konce aktuálního řádku:
#include <stdio.h>
int main()
{
__asm__ __volatile__(
"nop \n\t"
" nop \n\t"
" nop \n\t"
" nop \n\t"
" nop @ komentar \n\t"
: /* zadne vystupni registry */
: /* zadne vstupni operandy */
: /* zadne registry pouzivane uvnitr kodu */
);
return 0;
}
Pokud se chcete podívat na způsob zpracování takového bloku překladačem céčka, lze použít příkaz:
gcc -S -c test.c -o test.s
4. Pořadí zápisu operandů, specifikace konstant a jmen registrů
Jména běžných pracovních registrů odpovídají konvencím používaným společností ARM, tj. registry mají přiřazena jména r0 až r15. U některých registrů, konkrétně u posledních třech registrů, je možné použít i jmenný alias, což se týká především pc (programový čítač), lr (link register) a sp (ukazatel na vrchol zásobníku).
Vstupní operandy se zapisují způsobem "r" (proměnná_či_konstanta). Operandy se od sebe oddělují čárkou a od výstupních operandů jsou odděleny dvojtečkou:
: "r" (ix), "r" (iy) /* vstupni operandy */
Výstupní operandy se zapisují způsobem "=r" (proměnná) a pokud je jich větší množství, opět se pro jejich oddělení používá čárka:
: "=r" (ox), "=r" (oy) /* vystupni operandy */
Na konci celého bloku se uvádí nepovinný seznam registrů, které jsou modifikovány („zničeny“) uvnitř assemblerovského bloku. Překladač programovacího jazyka C tuto informaci potřebuje, aby do těchto registrů před zavoláním assemblerovského bloku neuložil důležité údaje (připomeňme si, že samotný překladač se nijak nesnaží o hlubší analýzu assemblerovského bloku):
: "r0", "r1" /* registry pouzivane uvnitr kodu */
Následující assemblerovský blok má:
- Dva vstupní operandy, které jsou naplněny z proměnných ix a iy.
- Dva výstupní operandy, které jsou naplněny z proměnných ox a oy.
- Specifikaci pracovních registrů r0 a r1 „zničených“ uvnitř bloku.
__asm__ __volatile__(
"" /* řetězec, který se po expanzi předá do assembleru */
: "=r" (ox), "=r" (oy) /* vystupni operandy */
: "r" (ix), "r" (iy) /* vstupni operandy */
: "r0", "r1" /* registry pouzivane uvnitr kodu */
);
5. Vrácení hodnoty z bloku napsaného v assembleru
Zkusme si nyní vytvořit assemblerovský blok, který nemá žádné vstupní operandy, ovšem má jeden operand výstupní. V tomto bloku se nejdříve do pracovního registru r0 vloží konstanta 42 a ta se ve druhé instrukci přenese do výstupního operandu, který je v bloku reprezentován svým pořadovým číslem %0. Výsledek je uložen do globální proměnné result, která je následně vypsána na standardní výstup běžnou céčkovskou funkcí printf():
#include <stdio.h>
unsigned long result;
int main()
{
__asm__ __volatile__(
"mov r0, #42 \n\t"
"mov %0, r0 \n\t"
: "=r" (result) /* vystupni operand */
: /* zadne vstupni operandy */
: "r0" /* registry pouzivane uvnitr kodu */
);
printf("%ld\n", result);
return 0;
}
Pokud výše uvedený zdrojový kód přeložíme s volbou -s, můžeme ve vygenerovaném souboru najít i náš blok, v němž je jasně patrné, jak došlo k náhradě operandu specifikovaného svým pořadovým číslem %0 za registr r2:
#APP
@ 7 "asm_in_c_4.c" 1
mov r0, #42
mov r2, r0
6. Větší množství výstupních operandů
Na rozdíl od běžných funkcí mohou assemblerovské bloky vytvořit větší množství výstupních hodnot, které jsou reprezentovány výstupními operandy. V předchozím příkladu jsme použili jen jeden výstupní operand, nyní si ukážeme použití dvou operandů, jejichž hodnoty mají být na konci assemblerovského bloku uloženy do globálních proměnných nazvaných x a y. Pro zajímavost je v assemblerovském bloku použita instrukce mov, která hodnotu vstupního operandu (registr r0) posune doleva o jeden bit (jedná se o logický posun), což je v instrukční sadě 32bitových mikroprocesorů ARM plně podporováno:
#include <stdio.h>
unsigned long x = 10;
unsigned long y = 20;
int main()
{
printf("%ld\t%ld\n", x, y);
__asm__ __volatile__(
"mov r0, #42 \n\t"
"mov r1, r0, lsl #1 \n\t"
"mov %0, r0 \n\t"
"mov %1, r1 \n\t"
: "=r" (x), "=r" (y) /* vystupni operandy */
: /* zadne vstupni operandy */
: "r0", "r1" /* registry pouzivane uvnitr kodu */
);
printf("%ld\t%ld\n", x, y);
return 0;
}
Po překladu a spuštění tohoto příkladu by se na standardní výstup měly vypsat původní hodnoty proměnných x a y (ty budou následně přepsány) a na druhém řádku jejich nové hodnoty (42 a 42×2):
10 20
42 84
Pro zajímavost se podívejme, jak se náš assemblerovský blok přeložil do výsledného souboru. Vidíme, že překladač vybral pracovní registry r12 a r2 (pro registr r12 je použil alias ip):
#APP
@ 10 "asm_in_c_4.c" 1
mov r0, #42
mov r1, r0, lsl #1
mov ip, r0
mov r2, r1
7. Vstupní a výstupní operandy
V dalším příkladu je ukázána kombinace vstupních a výstupních operandů. Povšimněte si především toho, že výstupní operandy jsou uvedeny na prvním místě a proto jsou jim přiřazena pořadová čísla %0 a %1. Až potom následují vstupní operandy s pořadovými čísly %2 a %3 (toto číslování může být zpočátku matoucí). I v tomto příkladu používáme instrukci mov kombinovanou s operací logického posunu doprava o dva bity (jen pro ukázku možností ARMovských procesorů):
#include <stdio.h>
unsigned long ix = 100;
unsigned long iy = 200;
unsigned long ox;
unsigned long oy;
int main()
{
printf("%ld\t%ld\n", ix, iy);
__asm__ __volatile__(
"mov r0, %2 \n\t"
"mov r1, %3 \n\t"
"mov %0, r0, lsr #2 \n\t"
"mov %1, r1, lsr #2 \n\t"
: "=r" (ox), "=r" (oy) /* vystupni operandy */
: "r" (ix), "r" (iy) /* vstupni operandy */
: "r0", "r1" /* registry pouzivane uvnitr kodu */
);
printf("%ld\t%ld\n", ox, oy);
return 0;
}
Po překladu a spuštění tohoto příkladu by se na standardní výstup měly vypsat hodnoty vstupních proměnných ix a iy a na druhém řádku hodnoty proměnných výstupních ox a oy:
100 200
25 50
Opět se podívejme na způsob překladu. První čtyři instrukce naplní obsahy pracovních registrů vstupními proměnnými, následuje vlastní assemblerovský blok a následně uložení výsledků do výstupních proměnných:
ldr r3, .L2+4
ldr r3, [r3, #0]
ldr r2, .L2+8
ldr r2, [r2, #0]
#APP
@ 12 "asm_in_c_5.c" 1
mov r0, r3
mov r1, r2
mov ip, r0, lsr #2
mov r2, r1, lsr #2
@ 0 "" 2
ldr r3, .L2+12
str ip, [r3, #0]
ldr r3, .L2+16
str r2, [r3, #0]
Pro pochopení způsobu adresování (.L2+12 atd.) je nutné se podívat na datovou sekci vygenerovaného souboru. Každé slovo má šířku čtyři bajty:
.L2:
.word .LC0
.word ix
.word iy
.word ox
.word oy
8. Použití symbolických jmen v assemblerovském bloku: cesta k čitelnému zdrojovému kódu
Již minule jsme se zmínili o možnosti použití symbolických jmen vstupních a výstupních operandů v assemblerovském bloku. Tyto operandy je nejdříve zapotřebí pojmenovat, přičemž jména se uvádí v hranatých závorkách:
: [output1] "=r" (ox), /* vystupni operandy */
[output2] "=r" (oy)
: [input1] "r" (ix), /* vstupni operandy */
[input2] "r" (iy)
Následně lze tato jména použít v assemblerovském bloku, nesmíme však zapomenout na uvedení znaku procenta před symbolické jméno:
"mov r0, %[input1] \n\t"
"mov r1, %[input2] \n\t"
"mov %[output1], r0, lsr #2 \n\t"
"mov %[output2], r1, lsr #2 \n\t"
Demonstrační příklad popsaný v předchozí kapitole můžeme velmi snadno přepsat do čitelnější podoby:
#include <stdio.h>
unsigned long ix = 100;
unsigned long iy = 200;
unsigned long ox;
unsigned long oy;
int main()
{
printf("%ld\t%ld\n", ix, iy);
__asm__ __volatile__(
"mov r0, %[input1] \n\t"
"mov r1, %[input2] \n\t"
"mov %[output1], r0, lsr #2 \n\t"
"mov %[output2], r1, lsr #2 \n\t"
: [output1] "=r" (ox), /* vystupni operandy */
[output2] "=r" (oy)
: [input1] "r" (ix), /* vstupni operandy */
[input2] "r" (iy)
: "r0", "r1" /* registry pouzivane uvnitr kodu */
);
printf("%ld\t%ld\n", ox, oy);
return 0;
}
Překlad proběhne prakticky totožným způsobem:
ldr r3, .L2+4
ldr r3, [r3, #0]
ldr r2, .L2+8
ldr r2, [r2, #0]
#APP
@ 12 "asm_in_c_6.c" 1
mov r0, r3
mov r1, r2
mov ip, r0, lsr #2
mov r2, r1, lsr #2
@ 0 "" 2
ldr r3, .L2+12
str ip, [r3, #0]
ldr r3, .L2+16
str r2, [r3, #0]
9. Makefile určený pro překlad dnešních demonstračních příkladů
Všechny demonstrační příklady, které jsme si v dnešním článku ukázali, lze přeložit příkazem make s využitím následujícího souboru Makefile. Tento soubor si raději stáhněte přímo z repositáře, neboť jen tak budete mít jistotu, že se nenahradí znaky pro Tab za mezery:
# Parametry prekladace.
CFLAGS=-Wall -O9
# Vychozi pravidlo pro vytvoreni vysledne spustitelne aplikace.
all: asm_in_c_0.s asm_in_c_0 \
asm_in_c_1.s asm_in_c_1 \
asm_in_c_2.s asm_in_c_2 \
asm_in_c_3.s asm_in_c_3 \
asm_in_c_4.s asm_in_c_4 \
asm_in_c_5.s asm_in_c_5 \
asm_in_c_6.s asm_in_c_6 \
asm_in_c_7.s asm_in_c_7 \
asm_in_c_8.s asm_in_c_8 \
asm_in_c_9.s asm_in_c_9 \
asm_in_c_10.s asm_in_c_10 \
asm_in_c_11.s asm_in_c_11
clean:
rm -f *.o
rm -f *.s
rm -f asm_in_c_[0-9]+
# Pravidlo pro slinkovani vsech objektovych souboru a vytvoreni
# vysledne spustitelne aplikace.
$(PROGNAME): $(PROGNAME).o
$(CC) -o $@ $(LDFLAGS) $<
# Pravidlo pro preklad kazdeho zdrojoveho souboru do prislusneho
# objektoveho souboru.
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Pravidlo pro preklad kazdeho zdrojoveho souboru do prislusneho
# assemblerovskeho vysledku.
%.s: %.c
$(CC) $(CFLAGS) -S -c $< -o $@
10. Repositář s demonstračními příklady
Všechny demonstrační příklady byly, podobně jako v prakticky všech předchozích částech tohoto seriálu, společně s podpůrným skriptem připraveným pro jejich překlad, uloženy do GIT repositáře dostupného na adrese https://github.com/tisnik/presentations/. Všechny zmíněné příklady jsou určeny pro překladač GNU C (podrobnosti o konkrétních verzích jsou uvedeny v úvodní kapitole):
Poznámka: poslední příklady budou podrobněji popsány příště.
11. Odkazy na Internetu
- ARM GCC Inline Assembler Cookbook
http://www.ethernut.de/en/documents/arm-inline-asm.html - Extended Asm - Assembler Instructions with C Expression Operands
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html - ARM inline asm secrets
http://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/ - How to Use Inline Assembly Language in C Code
https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html#Using-Assembly-Language-with-C - GCC-Inline-Assembly-HOWTO
http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html - A Brief Tutorial on GCC inline asm (x86 biased)
http://www.osdever.net/tutorials/view/a-brief-tutorial-on-gcc-inline-asm - GCC Inline ASM
http://locklessinc.com/articles/gcc_asm/ - 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