V dnešním článku se budeme zabývat v současnosti již možná poněkud okrajovým, ale stále zajímavým a mnohdy i užitečným tématem. Jedná se o tvorbu programů popř. jejich částí s využitím assembleru neboli jazyka symbolických adres (JSA). Zaměříme se na použití assembleru jak na platformě x86_64, tak i (a to možná především) na 32bitové platformě ARM.
Obsah
1. Použití assembleru v Linuxu
2. Vznik jazyka „assembly language“ a nástroje nazvaného assembler
3. Assemblery na domácích osmibitových mikropočítačích i na počítačích s procesory Motorola 68000
7. Volání funkcí kernelu – syscalls
8. Kostra jednoduché aplikace naprogramovaná v GNU Assembleru
9. Kostra jednoduché aplikace naprogramovaná v Netwide Assembleru
10. Varianta pro 32bitové ARMy s instrukční sadou Thumb
11. Repositář se zdrojovými kódy demonstračních příkladů
1. Použití assembleru v Linuxu
V dnešním článku se seznámíme se základy práce s assemblerem v operačním systému Linux. Assembler neboli též jazyk symbolických adres (JSA) popř. alternativně jazyk symbolických instrukcí (JSI) je nízkoúrovňovým programovacím jazykem, který na hierarchii jazyků stojí nad strojovým kódem, ovšem hluboko pod vyššími kompilovanými programovacími jazyky typu C, D či C++. Typickou vlastností assembleru je jeho vazba na určitý typ procesoru popř. řadu procesorů (architekturu) – týká se to především sady dostupných instrukcí. Programy se ve většině typech assemblerů zapisují formou symbolických instrukcí, přičemž každá instrukce je představována svou mnemotechnickou zkratkou a případnými operandy (konstantami, adresami, nepřímými adresami, jmény pracovních registrů procesoru atd.). Z několika assemblerů, které jsou pro Linux dostupné, se zaměříme na GNU Assembler a taktéž na novější Netwide Assembler, který však v současnosti nepodporuje všechny používané architektury.
Obrázek 1: Díky použití assembleru není nutné, aby programátoři pracovali ručně přímo se strojovým kódem (machine language). Pokud je to přeci jen z nějakého důvodu vyžadováno (mikrořadiče atd.), lze pro tento účel využít nástroje nazvané „monitory“.
Programování v jazyku symbolických adres již v současnosti není nijak masivní záležitostí, a to především z toho důvodu, že tvorba aplikací ve vyšších programovacích jazycích je v porovnání s assemblerem mnohem rychlejší, aplikace jsou snáze přenositelné na jiné platformy a změna aplikací, tj. přidávání nových vlastností či refaktoring, je ve vyšších programovacích jazycích jednodušší. Nesmíme taktéž zapomenout na to, že díky vývoji překladačů vyšších programovacích jazyků se běžně stává, že například algoritmus naprogramovaný v jazyku C může co do rychlosti snadno soutěžit s programem napsaným průměrným programátorem v assembleru. I přesto si však myslím, že assembler stále má své nezastupitelné místo, a to jak při zkoumání systémových volání v Linuxu a programování speciálního SW (části ovladačů, multimediální kodeky, některé kritické algoritmy typu FFT), tak i při práci na dnes velmi oblíbených osmibitových čipech tvořících například srdce Arduina a podobných jednodeskových mikropočítačů. Z tohoto důvodu se dnes seznámíme se způsobem tvorby jednoduchých aplikací v Linuxu, a to jak na platformě x86_64, tak i na platformě ARM. Podrobnějším popisem jednotlivých instrukcí se budeme zabývat až příště; dnes nás bude zajímat především toolchain a nástroje, které jsou v něm obsažené.
Obrázek 2: Nestrukturovaný zdrojový kód psaný v assembleru.
2. Vznik jazyka „assembly language“ a nástroje nazvaného assembler
Assemblery za sebou mají velmi dlouhý vývoj, protože první nástroje, které se začaly tímto názvem označovat, vznikly již v padesátých letech minulého století, a to na mainframech vyráběných společností IBM i jejími konkurenty (UNIVAC, Burroughs, Honeywell, General Electric atd.). Před vznikem skutečných assemblerů byla situace poněkud složitá. První aplikace pro mainframy totiž byly programovány přímo ve strojovém kódu, který bylo možné přímo zadávat z takzvaného řídicího panelu (control panel) počítače či načítat z externích paměťových médií (děrných štítků, magnetických pásek atd.). Ovšem zapisovat programy přímo ve strojovém kódu je zdlouhavé, vedoucí k častým chybám a pro větší aplikace z mnoha důvodů nepraktické, o čemž se mohli relativně nedávno přesvědčit například i studenti programující na československém mikropočítači PMI-80. Z důvodu usnadnění práce programátorů tedy vznikly první utility, jejichž úkolem bylo transformovat programy zapsané s využitím symbolických jmen strojových instrukcí do (binárního) strojového kódu určeného pro konkrétní typ počítače a jeho procesoru.
Obrázek 3: Kód v assembleru je však možné psát i strukturovaně, používat subrutiny a funkce atd.
Těmto programům, jejichž možnosti se postupně vylepšovaly (například do nich přibyla podpora textových maker, řízení víceprůchodového překladu, vytváření výstupních sestav s překládanými symboly, později i skutečné linkování s knihovnami atd.), se začalo říkat assemblery a jazyku pro symbolický zápis programů pak jazyk symbolických instrukcí či jazyk symbolických adres – assembly language (někdy též zkráceně nazývaný assembler, takže toto slovo má vlastně dodnes oba dva významy). Jednalo se o svým způsobem převratnou myšlenku: sám počítač byl použit pro tvorbu programů, čímž odpadla namáhavá práce s tužkou a papírem. Posléze se zjistilo, že i programování přímo v assembleru je většinou pracné a zdlouhavé, takže se na mainframech začaly používat různé vyšší programovací jazyky, zejména FORTRAN a COBOL. Použití vyšších programovacích jazyků bylo umožněno relativně vysokým výpočetním výkonem mainframů i (opět relativně) velkou kapacitou operační paměti; naopak se díky vyšším programovacím jazykům mohly aplikace přenášet na různé typy počítačů, což je nesporná výhoda.
Obrázek 4: Assembler pro počítače Commodore C64.
3. Assemblery na domácích osmibitových mikropočítačích i na počítačích s procesory Motorola 68000
Oživení zájmu o programování v assembleru přinesl vznik minipočítačů (například známé řady PDP) a na konci sedmdesátých let minulého století pak zcela nového fenoménu, který nakonec přepsal celé dějiny výpočetní techniky – domácích osmibitových mikropočítačů. Na osmibitových domácích mikropočítačích se používaly dva typy assemblerů. Prvním typem byly assemblery interaktivní, které uživateli nabízely poměrně komfortní vývojové prostředí, v němž bylo možné zapisovat jednotlivé instrukce v symbolické podobě, spouštět programy, krokovat je, vypisovat obsahy pracovních registrů mikroprocesoru atd. Výhodou byla nezávislost těchto assemblerů na rychlém externím paměťovém médiu (například disketové jednotce), který mnoho uživatelů a programátorů ani nevlastnilo. Druhý typ assemblerů je používán dodnes – jedná se vlastně o běžné překladače, kterým se na vstupu předloží zdrojový kód (uložený na kazetě či disketě) a po překladu se výsledný nativní kód taktéž uloží na paměťové médium (odkud ho lze následně spustit). Tyto assemblery byly mnohdy vybaveny více či méně dokonalým systémem maker (odtud ostatně pochází i označení macroassembler).
Obrázek 5: Atari Macro Assembler.
Assemblery byly mezi programátory poměrně populární i na počítačích Amiga a Atari ST, a to i díky tomu, že instrukční kód mikroprocesorů Motorola 68000 byl do značné míry ortogonální, obsahoval relativně velké množství registrů (univerzální datové registry D0 až D7 a adresové registry A0 až A7) a navíc bylo možné používat i takové adresovací režimy, které korespondovaly s konstrukcemi používanými ve vyšších programovacích jazycích (přístupy k prvkům polí, přístup k lokálním proměnným umístěných v zásobníkovém rámci, autoinkrementace adresy atd.). Podívejme se na jednoduchý příklad rutiny (originál najdete zde), která sečte všechny prvky (16bitové integery – načítá se vždy jen 16bitové slovo) v poli. V tomto příkladu se používá autoinkrementace adresy při adresování prvků polí a taktéž instrukce DBRA provádí dvě činnosti – snížení hodnoty registru o jedničku a skok v případě, že je výsledek nenulový:
moveq #0, d0 ; potřebujeme vynulovat horních 16 bitů d0 moveq #0, d1 ; mezivýsledek loop: move.w (a0)+, d0 ; horních 16 bitů d0 je pořád nastaveno na 0 add.l d0, d1 dbra d2, loop ; d2 je použit jako počitadlo
4. Assemblery v Linuxu
V této kapitole budeme pod termínem „assembler“ chápat programový nástroj určený pro transformaci zdrojového kódu naprogramovaného v jazyku symbolických adres do strojového kódu. Pro Linux vzniklo hned několik takových nástrojů, přičemž některé nástroje jsou komerční a jiné patří mezi open source. Z nekomerčních nástrojů, které nás samozřejmě na serveru mojefedora.cz zajímají především, se jedná o známý GNU Assembler, dále pak o nástroj nazvaný Netwide assembler (NASM), nástroj Yasm Modular Assembler či až překvapivě výkonný vasm. NASM a Yasm jsou pro první krůčky v assembleru velmi dobře použitelné, neboť mají dobře zpracovaný mechanismus reakce na chyby, dají se v nich psát čitelné programy atd. Určitý problém nastává v případě, kdy je nutné vyvíjet aplikace určené pro jinou architekturu, než je i386 či x86_64, a to z toho důvodu, že ani Netwide assembler ani Yasm nedokážou pracovat s odlišnou instrukční sadou. Naproti tomu GNU Assembler tímto problémem ani zdaleka netrpí, takže se v následujících kapitolách budeme zabývat jak nástrojem NASM, tak i GNU Assemblerem.
5. GNU Assembler
GNU Assembler (gas) je součástí skupiny nástrojů nazvaných GNU Binutils. Jedná se o nástroje určené pro vytváření a správu binárních souborů obsahujících takzvaný „objektový kód“, dále nástrojů určených pro práci s knihovnami strojových funkcí i pro profilování. Mezi GNU Binutils patří vedle GNU Assembleru i linker ld, profiler gprof, správce archivů strojových funkcí ar, nástroj pro odstranění symbolů z objektových a spustitelných souborů strip a několik pomocných utilit typu nm, objdump, size a strings. GNU Assembler je možné použít buď pro překlad uživatelem vytvořených zdrojových kódů nebo pro zpracování kódů vygenerovaných překladači vyšších programovacích jazyků (GCC atd.). Zajímavé je, že všechny moderní verze GNU Assembleru podporují jak původní AT&T syntaxi, tak i (podle mě čitelnější) syntaxi používanou společností Intel.
6. Netwide Assembler (NASM)
Netwide Assembler (NASM) vznikl v době, kdy začali na operační systém Linux přecházet programátoři znající operační systémy DOS a (16/32bit) Windows. Tito programátoři byli většinou dobře seznámeni s možnostmi assemblerů, které se na těchto platformách používaly nejčastěji – Turbo Assembleru (TASM) společnosti Borland i Microsoft Macro Assembleru (MASM) a tak jim možnosti GNU Assembleru (který má své kořeny na odlišných architekturách) příliš nevyhovovaly. Výsledkem snah o vytvoření nástroje podobnému TASMu či MASMu byl právě NASM, který podporuje stejný způsob zápisu operandů instrukcí a navíc ještě zjednodušuje zápis těch instrukcí, u nichž je jeden operand tvořen nepřímou adresou. NASM byl následován projektem Yasm (fork+přepis), ovšem základní vlastnosti a především pak vazba na platformu i386 a x86_64 zůstaly zachovány (to mj. znamená, že například na Raspberry Pi možnosti těchto dvou nástrojů plně nevyužijeme, což je určitě škoda).
7. Volání funkcí kernelu – syscalls
Vzhledem k tomu, že i ta nejjednodušší aplikace naprogramovaná v assembleru musí nějakým způsobem ukončit svou činnost, je nutné buď zavolat vhodnou knihovní funkci (z libc) popř. použít takzvaný „syscall“. V kontextu Linuxu se pod tímto termínem skrývá volání nějaké funkce umístěné přímo v jádru operačního systému. V praxi to funguje následovně: podle požadavků konkrétní funkce se naplní pracovní registry popř. datové struktury uložené v paměti, následně se číslo služby uloží do pracovního registru eax (i386/x86_64) nebo do pracovního registru r7 (32bitový ARM s použitím EABI) popř. x8 (ARM64) a následně se zavolá nějaká instrukce, která přepne kontext procesoru do privilegovaného režimu „jádra“ (vyvolá výjimku atd.). Na procesorech s architekturou i386 či x86_64 je touto instrukcí INT 80h, u 32bitových ARMů s EABI je to instrukce SWI 0h a u ARM64 instrukce SVC #0:
Architektura | Číslo služby v | Instrukce pro syscall | Návratová hodnota v |
---|---|---|---|
i386 | eax | INT 80h | eax |
x86_64 | rax | SYSCALL | rax |
ARM 32 s EABI | r7 | SWI 0h | r0 |
ARM 64 | x8 | SVC #0 | x0 |
Motorola 68k | d0 | TRAP #0 | d0 |
Samotná čísla jednotlivých funkcí kernelu naleznete například na adrese http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html. Nás bude zajímat hned první řádek této tabulky, který říká:
%eax Name Source %ebx %ecx %edx %esx %edi 1 sys_exit kernel/exit.c int - - - -
Co to znamená? Jedná se o funkci určenou pro ukončení aplikace, přičemž číslo syscallu je rovno jedné a zapisuje se do registru eax. Jediným parametrem je návratová hodnota (typu int), která se zapisuje do registru ebx (na ARMu je to r0, což se však zde nedozvíme). Podobně lze používat další funkce, jak si ostatně ukážeme příště.
8. Kostra jednoduché aplikace naprogramovaná v GNU Assembleru
Podívejme se nyní na to, jak může vypadat kostra velmi jednoduché aplikace naprogramované v GNU Assembleru pro procesory řady i386 či x86_64. Celý zdrojový kód je rozdělen na řádky, přičemž na jednotlivých řádcích mohou být komentáře, deklarace různých konstant a symbolů (sys_exit=1), speciální direktivy (.section), návěští/labels (_start) a samozřejmě i samotný kód reprezentovaný mnemotechnickými názvy instrukcí a jejich operandů. Důležitý je symbol _start, protože ten je používán i linkerem a specifikuje vstupní bod do programu:
# asmsyntax=as # Sablona pro zdrojovy kod Linuxoveho programu naprogramovaneho # v assembleru GNU AS. # # Autor: Pavel Tisnovsky # Linux kernel system call table sys_exit=1 #----------------------------------------------------------------------------- .section .data #----------------------------------------------------------------------------- .section .bss #----------------------------------------------------------------------------- .section .text .global _start # tento symbol ma byt dostupny i linkeru _start: movl $sys_exit,%eax # cislo sycallu pro funkci "exit" movl $0,%ebx # exit code = 0 int $0x80 # volani Linuxoveho kernelu
Povšimněte si rozdělení do sekcí – sekce pojmenované .data a .bss jsou prázdné, samotný kód je umístěn do sekce pojmenované .text, což může být matoucí, protože ve výsledném binárním souboru tato sekce taktéž obsahuje binární data (instrukce). Instrukce jsou v programu pouze tři a slouží pro naplnění pracovních registrů eax a ebx (funkce číslo 1, návratová hodnota 0) a zavolání syscallu. Používáme zde původní AT&T syntaxi GNU Assembleru, proto se do instrukce movl operandy zapisují v pořadí zdroj,cíl.
Překlad (assemblerem) a následné slinkování do spustitelného souboru se provede následovně:
as template.s -o template.o ld -s template.o
Výsledný soubor má velikost 344 bajtů:
0000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 .ELF............ 0000010: 02 00 3e 00 01 00 00 00 78 00 40 00 00 00 00 00 ..>.....x.@..... 0000020: 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 @............... 0000030: 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 ....@.8...@..... 0000040: 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 ................ 0000050: 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 ..@.......@..... 0000060: 84 00 00 00 00 00 00 00 84 00 00 00 00 00 00 00 ................ 0000070: 00 00 20 00 00 00 00 00 b8 01 00 00 00 bb 00 00 .. ............. 0000080: 00 00 cd 80 00 2e 73 68 73 74 72 74 61 62 00 2e ......shstrtab.. 0000090: 74 65 78 74 00 00 00 00 00 00 00 00 00 00 00 00 text............ 00000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000d0: 00 00 00 00 00 00 00 00 0b 00 00 00 01 00 00 00 ................ 00000e0: 06 00 00 00 00 00 00 00 78 00 40 00 00 00 00 00 ........x.@..... 00000f0: 78 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 x............... 0000100: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ 0000110: 00 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 ................ 0000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0000130: 84 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 ................ 0000140: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ 0000150: 00 00 00 00 00 00 00 00 ........
Na interní obsah souboru se můžeme podívat utilitkou objdump, a to následujícím způsobem:
objdump -f -d -t -h a.out
a.out: file format elf32-i386 architecture: i386, flags 0x00000102: EXEC_P, D_PAGED start address 0x08048054 Sections: Idx Name Size VMA LMA File off Algn 0 .text 0000000c 08048054 08048054 00000054 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE SYMBOL TABLE: no symbols Disassembly of section .text: 08048054 <.text>: 8048054: b8 01 00 00 00 mov $0x1,%eax 8048059: bb 00 00 00 00 mov $0x0,%ebx 804805e: cd 80 int $0x80
Vidíme, že uvnitř spustitelného souboru se skutečně nachází sekce nazvaná .text. Tato sekce je neměnitelná a obsahuje kód; její zarovnání je na celá slova. Obsahem je dvanáct bajtů obsahujících trojici instrukcí (ty jsou zde vypsány tak, jak je disassembler získal ze souboru, tj. již bez symbolických konstant atd.).
V 64bitové variantě je soubor nepatrně odlišný, ale ne příliš:
a.out: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000102: EXEC_P, D_PAGED start address 0x0000000000400078 Sections: Idx Name Size VMA LMA File off Algn 0 .text 0000000c 0000000000400078 0000000000400078 00000078 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE SYMBOL TABLE: no symbols Disassembly of section .text: 0000000000400078 <.text>: 400078: b8 01 00 00 00 mov $0x1,%eax 40007d: bb 00 00 00 00 mov $0x0,%ebx 400082: cd 80 int $0x80
Poznámka: význam jednotlivých instrukcí si podrobněji popíšeme příště, dnes se seznamujeme především s použitím toolchainu.
9. Kostra jednoduché aplikace naprogramovaná v Netwide Assembleru
V Netwide Assembleru se stejná aplikace naprogramuje nepatrně odlišným způsobem, a to kvůli rozdílné syntaxi a sémantice. Důležité a na první pohled viditelné je otočení operandů u instrukcí (cíl, zdroj) a taktéž to, že u instrukce mov se nemusí nijak specifikovat typ operandů – to je zajištěno assemblerem automaticky. Dále se odlišně zapisují symbolické konstanty s využitím direktivy equ:
; asmsyntax=nasm ; Sablona pro zdrojovy kod Linuxoveho programu naprogramovaneho ; v assembleru NASM. ; ; Autor: Pavel Tisnovsky ; Linux kernel system call table sys_exit equ 1 ;----------------------------------------------------------------------------- section .data ;----------------------------------------------------------------------------- section .bss ;----------------------------------------------------------------------------- section .text global _start ; tento symbol ma byt dostupny i linkeru _start: mov eax,sys_exit ; cislo sycallu pro funkci "exit" mov ebx,0 ; exit code = 0 int 80h ; volani Linuxoveho kernelu
Překlad se provede příkazem:
nasm -felf32 template.asm ld -s template.o
popř. pro 64bitový systém příkazem:
nasm -felf64 template.asm ld -s template.o
10. Varianta pro 32bitové ARMy s instrukční sadou Thumb
Stejná aplikace, ale určená pro 32bitové mikroprocesory ARM (například pro Raspberry Pi), musí být v GNU Assembleru vytvořena nepatrně odlišně, což je ostatně patrné z následujícího kódu. Povšimněte si především toho, že komentáře u instrukcí musí začínat znakem @ a samozřejmě i instrukční soubor je jiný:
# asmsyntax=as # Sablona pro zdrojovy kod Linuxoveho programu naprogramovaneho # v assembleru GNU AS. # # Autor: Pavel Tisnovsky # Linux kernel system call table sys_exit=1 #----------------------------------------------------------------------------- .section .data #----------------------------------------------------------------------------- .section .bss #----------------------------------------------------------------------------- .section .text .global _start @ tento symbol ma byt dostupny i z linkeru _start: mov r7,$sys_exit @ cislo sycallu pro funkci "exit" mov r0,#0 @ exit code = 0 svc 0 @ volani Linuxoveho kernelu
Překlad a slinkování proveďte těmito dvěma příkazy:
as arm_thumb.s -o arm_thumb.o ld -s arm_thumb.o
Výsledkem by měl být binární soubor o délce pouhých 311 bajtů:
0000000: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 .ELF............ 0000010: 02 00 28 00 01 00 00 00 54 80 00 00 34 00 00 00 ..(.....T...4... 0000020: 98 00 00 00 00 02 00 05 34 00 20 00 01 00 28 00 ........4. ...(. 0000030: 04 00 03 00 01 00 00 00 00 00 00 00 00 80 00 00 ................ 0000040: 00 80 00 00 60 00 00 00 60 00 00 00 05 00 00 00 ....`...`....... 0000050: 00 80 00 00 01 70 a0 e3 00 00 a0 e3 00 00 00 ef .....p.......... 0000060: 41 13 00 00 00 61 65 61 62 69 00 01 09 00 00 00 A....aeabi...... 0000070: 06 01 08 01 00 2e 73 68 73 74 72 74 61 62 00 2e ......shstrtab.. 0000080: 74 65 78 74 00 2e 41 52 4d 2e 61 74 74 72 69 62 text..ARM.attrib 0000090: 75 74 65 73 00 00 00 00 00 00 00 00 00 00 00 00 utes............ 00000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000c0: 0b 00 00 00 01 00 00 00 06 00 00 00 54 80 00 00 ............T... 00000d0: 54 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 T............... 00000e0: 04 00 00 00 00 00 00 00 11 00 00 00 03 00 00 70 ...............p 00000f0: 00 00 00 00 00 00 00 00 60 00 00 00 14 00 00 00 ........`....... 0000100: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ 0000110: 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................ 0000120: 74 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 t...!........... 0000130: 01 00 00 00 00 00 00 00 ........
Pokud vás zajímá interní struktura tohoto souboru, opět pomůže nástroj objdump:
objdump -f -d -t -h a.out
a.out: file format elf32-littlearm architecture: armv4, flags 0x00000102: EXEC_P, D_PAGED start address 0x00008054 Sections: Idx Name Size VMA LMA File off Algn 0 .text 0000000c 00008054 00008054 00000054 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .ARM.attributes 00000014 00000000 00000000 00000060 2**0 CONTENTS, READONLY SYMBOL TABLE: no symbols Disassembly of section .text: 00008054 <.text>: 8054: e3a07001 mov r7, #1 8058: e3a00000 mov r0, #0 805c: ef000000 svc 0x00000000
V následující části si řekneme, jak vytvořit složitější kód obsahující podmínky, smyčky atd., a to opět v assembleru procesorů i386/x86_64 i ARM (s instrukční sadou Thumb).
11. Repositář se zdrojovými kódy demonstračních příkladů
Oba dva demonstrační příklady byly společně s podpůrnými skripty uloženy do GIT repositáře dostupného na adrese https://github.com/tisnik/presentations/:
12. Odkazy na Internetu
- 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
25. 5. 2016 at 19:56
Nikdy jsem AT&T syntaxi nepřišel na chuť, překvapením pro mě je, že gasm umí Intel syntaxi…
25. 5. 2016 at 20:47
Tak tak, stara dobra Inteli syntaxe, na te jsem vyrostl (i kdyz kupodivu ne na Intelim cipu)
28. 5. 2016 at 20:45
Taky mam radeji intel syntaxi 🙂 Nechapu proc kolem „linuxu“ je vsude jenom at&t syntaxe.
27. 5. 2016 at 13:54
Asi bych měl udělat pull request, když už jsem ty příklady převedl i na mainframe 🙂
27. 5. 2016 at 14:08
jj urcite, to by bylo fajn 🙂
28. 5. 2016 at 09:33
Zavzpomínal jsem si na staré dobré časy s assemblerem na ZX Spectrum. 🙂
28. 5. 2016 at 10:37
A skvely editor Prometheus. Prvni legalni soft na ZX Spectrum+, ktery jsem si poridil 🙂