Hlavní navigace

Programujeme v jazyce Assembler v Linuxu: Úvod

Martin Podhola 1. 7. 2004

Můj článek se zabývá programováním v nízkoúrovňovém jazyce Assembler v Linuxu pro znalé tohoto jazyka. Pokusím se zde popsat možnosti, které nám Linux nabízí, a vlastnosti překladače NASM, volání systému a odlaďování aplikací, a také to, že Tux umí Assembler:).

Můj článek se zabývá programováním v nízkoúrovňovém jazyce Assembler v Linuxu pro znalé tohoto jazyka. Pokusím se zde popsat možnosti, které nám Linux nabízí, a vlastnosti překladače NASM, volání systému a odlaďování aplikací, a také to, že Tux umí Assembler:).

Předpokládejme tedy, že jste seznámeni s programováním v Assembleru nebo jste již pár programů vytvořili, zde jsou možnosti, jak v něm vytvořit efektivní programy pro Linux a využít jeho možnosti.

V prvním dílu tohoto seriálu se seznámíme s uspořádáním paměti procesu, předáváním argumentů příkazové řádky a voláním operačního systému.

Jak to tam uvnitř vypadá – uspořádání paměti procesoru

Linux jako víceprocesový (multitaskingový) operační systém, jehož jádro je z největší části napsáno v jazyce C, ale obsahuje i části psané v Assembleru, používá 32bitový systém adresování paměti. Díky této vlastnosti máme k dispozici 4 GB adresového prostoru pro každý proces v něm běžící. Tyto procesy „nevidí“ jádro, protože to je všem procesům skryto, a „nepoflakuje“ se v jejich paměti. To z důvodů bezpečnosti, jeden proces totiž neovlivňuje druhý. Tudíž havárie jednoho programu neshodí jiný běžící program nebo celý systém. Proces je zcela samostatný ve svém vlastním prostoru, který má k dispozici pouze pro sebe.

Tedy prostor pro náš program je veliký, je osamocen ve 4GB prostoru. Programy se skládají z několika segmentů (sekcí), Linux však podporuje mnoho formátů spustitelných souborů, my se zaměříme třeba na formát ELF – executable and linkable format. Pořadí načítání sekcí se u růzých spustitelných formátů může velmi lišit, některé formáty jsou si podobné, jiné jsou však zcela odlišné. Program bez dynamicky vázaných knihoven tedy bude spuštěn po svých částech v tomto pořadí.

Adresa 0×08048000

Tabulka č. 575
Spustitelný kód ;kód našeho programu, to co se má vykonat
Statická data ;data, která nebudou změněna
Dynamická (heap) data  
Volný prostor  
Zásobník ;zásobník dat, k jeho využití použijeme instrukci POP

Adresa 0×BFFFFFFF       hranice 4 GB

Program obvykle bývá nahrán do 128 MB adresového prostoru. Program se do paměti stránkuje (to znamená, že v paměti existuje právě jedna stránka programu). Další stránky jsou nahrány až po uvolnění té první, ve chvíli, kdy jsou zapotřebí. Původní stránka zcela z paměti mizí, části programu, které při jeho spuštění nebudou použity, se v paměti nikdy neobjeví. V programu samotném tyto sekce nejsou fyzicky odděleny, jsou rozdělovány až během zavádění programu do paměti. Na disku se jedná pouze o jeden kompletní a ucelený soubor.

Má-li program dynamicky zaváděné knihovny (linked libraries), budou jejich moduly nahrávány do stejného adresového prostoru, ale jejich adresy budou v pozici nad 1 GB a výše. V prostoru 3 GB, která nám zbývají do zásobníku, je volná pamět patřící procesu, ale ta není stránkovaná (nemá přiděleny žádné stránky). Když program zapíše na nealokované místo, bude proces ukončen (SIGKILL kernelu). Jedná se o velmi závažnou chybu, které bychom se jako programátoři měli vyvarovat. Program s touto chybou nikdy nebude proveden do svého konce, takže je zcela neužitečný, avšak důvodů k této chybě je více, podrobněji se budeme problematice chyb věnovat v nějakém z dalších dílů v sekci odlaďování programů. Pro přidělení dynamického stránkování pro data se musí jádro požádat, to ji pak přidělí, o tom si povíme později.

Kdepak to vše leží – předávání argumentů příkazove řádky

Proces je tedy naprosto sám ve své paměti, jak ale k němu dostat parametry a argumenty příkazové řádky nebo proměnné prostředí? Najdeme je na vrcholu zásobníku, který vypadá takto:

Tabulka č. 576
argc počet parametrů (dword)
argv[0] pointer na název programu
argv[1] … argv[argc-1] pointery na parametry programu
NULL konec pointerů parametrů
env[x] x=(0;n)
NULL konec pointerů na prostředí

Použití těchto parametrů se provádí přes instrukci POP pro výběr dat ze zásobníku. Nezapomeňme však, že zásobník používá metodu LIFO (last in first out), to znamená, že to, co do něj přijde jako poslední, jde ven jako první. Doporučuji jako první ze zásobníku přečíst počet parametrů (argc).

První pointer bude obsahovat jméno našeho programu, ostatní pointery, s hodnotou argc větší než 1, budou obsahovat další pointery uložené v zásobníku.

Haló, vy tam – volání operačního systému

Pro systémová volání se v Linuxu používá přerušení int 0×80. Řekněme si jak se dovolat jádra z našeho programu. Při provedení instrukce int 0×80 se změní hodnota segmentového registru a začne běžet jaderný kód. Po jeho skončení se normálně pokračuje ve vykonávání našeho programu, jakoby se nechumelilo :).

Parametry jednotlivých systémových volání (syscalls) se předávají v registrech. Každá služba má své číslo, toto číslo se předává v registru EAX. Parametr této služby, pokud nějaký má, se předává v registru EBX, další parametr je předán pomocí registru ECX a další pomocí, můžete hádat, pokud jste hádali EDX, tak jste hádali správně:). Parametry služby se tedy předávají v pevně stanovených registrech. Od jádra 2.4.0 se poslední parametr předává v registru EBP.

Závěrem

Dnes jsme si ukázali pár základních věcí o vlastnostech a chování aplikace ve formátu spustitelného souboru ELF v Linuxu a o jeho paměti a registru, ze kterého umíme vybrat důležité informace. Příště budeme pokračovat o něco dále a povíme si více o chybových kódech a o tom, kde najít více informací o nich, napíšeme si jednoduchý program a povíme si, co jsou to ASMUTILS.

Doufám, že se vám tento článek líbil a přečtete si i jeho pokračování, které nebude již tolik teoretické, vneseme do něj více praxe a ukázek:).

Našli jste v článku chybu?

18. 10. 2015 17:03

Petr2 (neregistrovaný)

Nevím, v čem je problém v nastavování/sha­zování bitů v Bajtu v assembleru? Pomocí logického OR nastavím, pomocí AND shodím

16. 2. 2008 15:33

Valery (neregistrovaný)
Na obrázky k assembleru se můžeš podívat na fórum o mikroprocesorech a mikrořadičích. Ale jinak pěkný článek.
Podnikatel.cz: Platební brány a EET? Stále s otazníkem

Platební brány a EET? Stále s otazníkem

Vitalia.cz: Jak koupit Mikuláše a nenaletět

Jak koupit Mikuláše a nenaletět

Podnikatel.cz: Přivýdělek u Airbnb nebo Uberu? Čekejte kontrolu

Přivýdělek u Airbnb nebo Uberu? Čekejte kontrolu

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET