EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

EuroAssembler dokumentace


English version of this manual

O aplikaci €ASM ↓

Vstup/výstup ↓

Struktura €ASM programu ↓

Prvky zdrojového kódu ↓

Instrukce ↓

Programové formáty ↓

Funkce EuroAssembleru ↓


↑ O aplikaci EuroAssembler

Identifikace ↓

Stručná charakteristika ↓

Typografické konvence ↓

Proč asembler ↓

K čemu další asembler ↓

Proč EuroAssembler ↓

Licence ↓

Historie

Stažení

Instalace ↓


↑ Identifikace

Jméno tohoto softwaru je EuroAssembler. Všimněte si chybějící mezery mezi Euro a Assembler.
Název se často zkracuje jako €ASM.
V 7-bitovém (ASCII) prostředí bývá rovněž uváděn jako EUROASM a v některých interních identifikátorech je to pouze ea.

Znak Euro je na klávesnici v MS-Windows dostupný jako Alt~0128 nebo jako HTML entita €.

↑ Stručná charakteristika

Některé další vlastnosti se u jiných asemblerů vidí pouze zřídka:

↑ Typografické konvence

Tento manuál reprezentuje dokumentaci, referenční příručku, příklady a implementační poznámky. K jejich rozlišení slouží rozličné styly.

Podkladová barva stránky rozlišuje

   tento manuál a seznam odkazů knihovny makroinstrukcí zdrojové kódy €ASM testovací soubory objekty a vzorové programy.

Přerušované podtržení odkazuje na odstavec v rámci téže webové strany.

Podtržení naviguje na jinou HTML stránku v rámci tohoto webu.

Podtržení s ikonou Link odkazuje na stránku Links soustřeďující externí odkazy.

Podtržení s ikonou Exit naviguje mimo web EuroAssembleru, možná je budete chtít otevřít v novém okně nebo tabu.

Obsah tohoto návodu je organizován do kapitol se stromovou strukturou.

↑ Title

Šipka nahoru u názvu kapitoly naviguje o jednu úroveň výše..

Title ↓

Šipka dolů za názvem kapitoly naviguje na konkrétní text.
Pravidla stojící za zapamatování jsou označena ikonou žárovky.

Definice nových pojmů jsou psány tučnou modrou kurzívou.

Implementační detaily, diskuse a osobní poznámky se zobrazují menším fontem.

Názvy souborů jsou zvýrazněny uvozovkami.

Znaky použité v textu mají bílé pozadí.

Krátké úseky zdrojového kódu se zobrazují neproporciálním fontem černě na žluté v toku textu.

; Delší ukázky zdrojového kódu se zobrazují v rámečku.
; Mohou mít více řádků.
; Negativní příklady jsou přeškrtnuty.
 
Ukázky kódu v makroknihovnách a zdrojových souborech jsou ignorovýny EuroAssemblerem, neboť jejich vyzické řádky začínají HTML tagem <.
vysvětlující metaindormace ┐ |0000:0000| ; Tištěný výstup EuroAssembleru (listing) se zobrazuje černě na bílém papíru. |0000:0000| ; Obsahuje sestavený strojový kód, kopie zdrojových instrukcí |0000:0000| ; a chybová hlášení.

↑ Proč asembler

Asembler (ASM) je jediný programovací jazyk, který nám dává plnou kontrolu nad strojovým kódem. Muset ručně zapisovat každou instrukci pro Central Processing Unit (CPU) je ovšem značně namáhavé, proto byly vynalezeny podprogramy: procedury, funkce, makroinstrukce.
Podprogram je něco jako černá skříňka s dokumentovaným účelem, vstupem a výstupem. Hlavní rozdíl mezi naším vlastním podprogramem a funkcí vyššího jazyka (HLL) je v tom, že pokud nepracuje dle očekávání, můžeme snadno vystopovat chybu krokováním programu v debugeru, a je to pouze naše vlastní chyba.

Podprogram v asembleru může vykonávat stejnou funkci jako povely vyššího programovacího jazyka (HLL) nebo volání operačního systému (OS). Makrojazyk EuroAssembleru dovoluje připravit pokročilá makra šitá na míru řešenému problému a vyvíjet pak programy v ASM téměř stejně rychle jako HLL.

Výhoda znalosti asembleru se projeví, když nějaký špatně napsaný cizí program způsobí výjimku a skončí. Dr.Watson, disasembler, debuger ukazuje pouze kód ve strojových instrukcích, který bez znalosti asembleru budeme jen stěží umět interpretovat, zatímco zkušený ASM programátor se bude cítit jako ryba ve vodě.

Hlavní nevýhodou asemblerů jsou chybějící standardní knihovny, které sjednocují programování v HLL jako C nebo Java. Mnoho ASM programátorů buduje své vlastní knihovny, což vyžaduje poskytovat jejich kód současně s programem. Ovšem tvorba vlastní knihovny je zároveň nejlepší metoda, jak si zapamatovat názvy a parametry v ní obsažených funkcí.
Distribuce EuroAssembleru obsahuje několik makroknihoven pro začátek a pro inspiraci.
Asembler je univerzální stavebnice. Můžete si naprogramovat téměř cokoli, ale nejprve je třeba připravit nástroje.
Postup tvorby programu
FázePoužitý nástroj
design-timepředstavivost
write-timetextový editor
assembly-timeasembler
combine-timelinker
link-timelinker
load-timeloader operačního systému
bind-timeloader operačního systému
run-timeprocesor

↑ K čemu další asembler

Nespokojenos s existujícími nástroji je hlavní důvod, proč někteří programátoři vyvíjejí vlastní programovací jazyk.

Nezanedbatelná je skutečnost, že vytvoření asembleru je velmi zajímavá činnost. Nekompletní seznam nástrojů, se kterými jsem měl potěšení se setkat, je uveden na odkazu [Assemblers] a [UsefulTools].

První nástroj, se kterým jsem se setkal když jsem začal v raných osmdesátých letech flirtovat s asemblerem, byl FDOS od IBM pro mainframy S360 [HLASM]. Což byl na svou dobu velmi sofistikovaný produkt s pokročilými funkcemi, jako sekce, klíčové operandy (keywords), s literály, s makrojazykem, jenž dovolovat manipulovat nejen se strojovými instrukcemi, ale i s vlastními makroproměnnými a jejich názvy.

V asemblerech pro architekturu Intel jsem pak postrádal mnohé z těchto funkcí. [NASM] ver.0.99 byl poměrně dobrý, první bootstrapová verze €ASM byla napsána právě v něm, ale byl jsem rozčarován jeho neschopností automaticky vybírat SHORT nebo NEAR formu instrukce JMP a dalšími návrhovými vadami, jako třeba neexpandovat %proměnné v řetězcích.

Nechápal jsem, proč konstantní symboly definované pomocí EQU musely být deklarovány před prvním užitím. Proč nemohu deklarovat makro v makru. Jak řešit situace, kdy soubor A ikluduje soubory B a C, a soubor C rovněž inkluduje soubor B a duplikuje tak jeho definice.

Nemám rád jazyky zamořené mezerami. V jazyce HLASM mezera za seznamem operandů znamenala začátek komentáře, který končil až s koncem děrného štítku. €ASM není tak přísný v tomto horror vacui, ve skutečnosti mezery mohou být vloženy mezi jazykové elementy kvůli zlepšení čitelnosti. Nicméně netisknutelné mezery nejsou téměř nikdy vyžadovány syntaxí.

€ASM nepoužívá anglické slovní modifikátory, jako SHORT, NEAR, DWORD PTR, NOSPLIT identifikované pouze jejich hodnotou. Místo toho preferuje paradigma Name=Value spolu s klíčovými modifikátory instrukcí, jako DATA=QWORD,IMM=BYTE,MASK=K5,ZEROING=ON, jež odstraňují nejednoznačnosti a nahrazují nehezké dekorátory navrhované v dokumentaci od Intelu.

↑ Proč EuroAssembler

  1. Euro neboť přichází z Česka ležícího v srdci Evropy ( Czechia, the heart of Europe).
  2. Jak Evropa, tak i €ASM jsou mnohojazyčné tím, jak podporují národní znaky v identifikátorech a řetězcích.
  3. je jeden z posledních neobsazených znaků mezi ostatními *ASM asemblery :-)

↑ Licence

Právo užívat EuroAssembler je poskytnuto každému, kdo se řídí touto licencí.
Nejsou žádná omezení ohledně účelu aplikací vyrobených tímto nástrojem. Mohou být svobodně používány v soukromém, výukovém i komerčním prostředí.

EuroAssembler je poskytnut bezplatně tak, jak je, bez jakékoli záruky od jeho autora.

Tento software smí být redistribuován v nezměněné zipované podobě, tak jak byl stažen z EuroAssembler.eu. Za právo používat tento software nesmí být vyžadován žádný poplatek.

Můžete rozšiřovat euroasm.zip na jiné weby, repozitáře, archivy FTP, kompaktní disky a obdobná média. Snažte se prosím vždy šířit nejnovější verzi EuroAssembleru.

Zdrojový kód EuroAssembleru napsal Pavel Šrubař, AKA vitsoft, a jako takový je chráněn autorským zákonem.

Makroknihovny a vzorové projekty jsou uvolněny jako public domain a mohou být libovolně upravovány.

Modifikaci dodaných knihoven nicméně nemohu doporučit, protože vaše vylepšení by mohly být přepsány po vydání novější verze €ASM. Vytvořte raději soubory s vlastními názvy.

Smíte modifikovat zdrojový kód €ASM za výhradním účelem opravy chyb nebo obohacením o nové funkce, avšak nesmíte distribuovat takto upravený software. Smí být používán pouze na tomtéž počítači, kde byl upraven, sestaven a znovu slinkován.

EuroAssembler není open source. Nechci větvit vývoj EuroAssembleru do navzájem nekompatibilních verzí, kde každá větev poskytuje odlišné vylepšení. Raději prosím zašlete své modifikace autorovi nebo je napište do diskusního fóra, aby mohly být zařazeny do dalších vydání EuroAssembleru.

↑ Instalace

Distribuovaný soubor euroasm.zip obsahuje adresáře a soubory jak jsou vyjmenovány na stránce Sitemap Čas poslední modifikace všech souborů je nastaven na nominální hodnotu vydání. Názvy souborů jsou malými písmeny (Linuxová konvence) a ve 8.3 formátu (DOSová konvence), takže je rozbalí jakákoli starší DOSová utilita.
K instalaci na novější verzi MS-Windows budete muset spustit konzolu jako administrátor.

Zvolte a vytvořte domovský adresář, například C:\euroasm, přejděte do něj a rozzipujte stažený soubor euroasm.zip. Přesuňte nebo zkopírujte spustitelný soubor euroasm.exe do některé složky obsažené v proměnné environmentu PATH, takže bude moci být spouštěn jako euroasm odkudkoli. Při prvním spuštění se pokusí vytvořit globální konfigurační soubor euroasm.ini v tomtéž adresáři. Nyní byste jej měli upravit plain-text editorem.

Možná budete chtít upravit relativní hodnoty IncludePath= and LinkPath= v sekci [EUROASM] absolutní cestou specifikující domácí adresář EuroAssembleru.
V sekci [PROGRAM] možná budete chtít upravit preferovaný formát generovaných souborů, např. Format=PE, Subsystem=CON a Width=32. Také můžete nahradit IconFile="euroasm.ico" za svou preferovanou ikonu a nahrát ji do složky objlib.

Pro (nedoporučenou) holou minimální instalaci můžete vymazat celý domácí adresář. Soubor euroasm.exe nepotřebuje žádné další podpůrné soubory, úpravy environmentu nebo registrů MS-Windows.

Pokud byste chtěli číst tuto dokumentaci v jiném jazyce, přejmenujte defaultní anglickou verzi tohoto manuálu eadoc\index.htm na eadoc\man_eng.htm a pak přejmenujte dostupný překlad, např. eadoc\man_cze.htm na eadoc\index.htm.

Pro vývojářskou instalaci rozbalte v domovském adresáři vývojářské skripty z podarchivu generate.zip. Budete muset mít na svém počítači instalován webserver a PHP (verze 5.3 nebo novější).

Většina souborů EuroAssembleru je v HTML formátu, takže asi budete chtít začlenit €ASM do vašeho lokálního webserveru.

V mé instalaci Apache jsem do jeho konfiguračního souboru httpd.conf nebo apache2.conf přidal

<VirtualHost *:80>
    DocumentRoot C:/euroasm/
    ServerName euroasm.localhost
</VirtualHost>

Dále jsem přidal řádek 127.0.0.1 euroasm.localhost do souboru %SystemRoot%\SYSTEM32\drivers\etc\hosts. Nyní mohu napsat euroasm.localhost do adresního řádku internetového prohlížeče a číst soubory EuroAssembleru lokálně.


↑ Vstup/Výstup

Standardní kanály ↓

Další kanály ↓

Oznámení ↓

Vstupní a výstupní soubory ↓


Počítače komunikují s uživateli rozličnými kanály: standardní vstup a výstup, parametry příkazové řádky, proměnné environmentu, hodnota errorlevel, diskové soubory, hardwarová zařízení.

↑ Standardní kanály

Základní forma komunikace mezi programem a lidským uživatelem má podobu proudu znaků, defaultně směrovaného na konzolu terminálu, kde byl program spuštěn. Může být přesměrován do souboru nebo do ovladače zařízení pomocí operátorů příkazové řádky >, >>, <, |.

Standardní vstup není v €ASM používán.

Standardní výstup zobrazuje chyby, varování a informativní zprávy generované EuroAssemblerem.

Standardní chybový výstup není v €ASM používán.

↑ Další kanály

Parametry příkazové řádky nejsou používány. €ASM předpokládá, že vše na příkazové řádce jsou názvy souborů, které má přeložit. Veškeré parametry řídící asembler a linker jsou definovány v konfiguračních souborech euroasm.ini nebo přímo ve zdrojovém kódu.

Ve skutečnosti sice je několik parametrů EUROASM rozeznáváno na příkazovém řádku, avšak jejich preferované umístění je konfigurační soubor anebo zdrojový kód. Parametry z příkazového řádku jsou využity pouze v testech, kde potlačují některé informaticní zprávy.

Proměnné environmentu nejsou v €ASM používány. Mohou však být začleněny do zdrojového textu v asm-time pomocí pseudoinstrukce %SETE. A je samozřejmě také možné číst tyto proměnné v run-time pomocí příslušného systémového volání, jako GetEnvironmentVariable().

€ASM nepoužívá žádná další zařízení (I/O porty, tiskárny,zvukové a grafické adaptéry apod.) během asm-time.

↑ Oznámení

Informace detekované EuroAssemblerem během jeho činnosti jsou publikovány ve formě krátkých textových oznámení směrovaných na standardní výstup a do listingového souboru.

Závažnost oznámení ↓

Oznámení na standardním výstupu ↓

Oznámení v listingu ↓

Oznámení je identifikováno kombinací písmene následovaného čtyřmi dekadickými číslicemi. Jejich kompletní text je definován ve zdrojovém souboru €ASM msg.htm.

Písmenový prefix a první číslice (0..9) určují závažnost tohoto oznámení. Nejvyšší závažnost zjištěná během činnosti €ASM určuje hodnotu errorlevel, se kterou euroasm.exe končí.

Závažnost oznámení
Druh zprávyPrefixRozsah
identifikátorů
ZávažnostVyhledávací
značka
InformativníII0000..I09990|#
LadicíDD1000..D19991|#
VarováníWW2000..W39992..3|##
Nepotlačitelná varováníWW4000..W49994|##
Uživatelem definovaná chybaUU5000..U59995|###
ChybaEE6000..E89996..8|###
Fatální chybaFF9000..F99999|###

EuroAssembler je upovídaný, avšak může být zcela umlčen při spuštění s parametrem NOWARN=0000..0999, a pokud nezjistí žádnou chybu.

Varování zpravidla nebrání zkompilovanému programu ve spuštění, jsou to spíše upozornění, že programátor něco opomenul nebo učinil překlep.

Oznámení se závažností 5..8 indikují, že některé řádky nebyly přeloženy kvůli chybě. Cílový soubor může být formálně v pořádku, ale pravděpodobně nebude fungovat, jak by měl.

Fatální chyby upozorňují na chybu interakce s operačním systémem, vyčerpání zdrojů, chybu v práci se soubory nebo interní chybu EuroAssembleru. Cílový soubor při fatální chybě nejspíš nebyl vůbec vytvořen.

Oznámení a varování v rozsahu I0000..W3999 mohou být potlačena parametrem EUROASM NOWARN=, ovšem tato pštrosí politika není dobrý nápad, vždy je lepší odstranit příčinu varování.
Hodláte-li publikovat svůj kód, měl by jít zkompilovat s hodnotou errorlevel 0.

↑ Oznámení na standardním výstupu

Typické oznámení sestává z identifikátoru, za kterým následuje upravený text zprávy. Při jeho zobrazení na standardním výstupu je doprovázen pozičním indikátorem ve formě názvu zdrojového souboru následovaného číslem fyzického řádku ve složených závorkách, například

E6601 Symbol "UnknownSym" mentioned at "t1646.htm"{71} was not found. "t1646.htm"{71}
▲▲▲▲▲                                                                 ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
Identifikátor                                                        poziční indikátor

Obvykle vidíme pouze jeden poziční indikátor, pouze v případě zjištění chyby ve fázi expanze makra je přidán další indikátor určující číslo řádku v makroknihovně. V případě expanze makra uvnitř jiného makra budou poziční indikátory dále zřetězeny.

↑ Oznámení v listingu

Oznámení zapisovaná do listingového souboru mají lehce odlišný formát. Poziční indikátor je vynechán, neboť chybové zprávy jsou vkládány hned pod zdrojový řádek způsobující chybu.:

|002B: | MOV SI,UnknownSym: ; E6601 expected. |### E6601 Symbol "UnknownSym" mentioned at "t1646.htm"{71} was not found. ▲▲▲▲ marker

Textu oznámení předchází vyhledávací značka, která pomáhá nalézt chybu v listingu.

Pomocí vyhledávací funkce Find/FindNext (Ctrl-F) editoru nebo prohlížeče použitého ke čtení listingového souboru můžeme přeskakovat od jedné chyby ke druhé.
K prohlížení listingu můžete rovněž využít specializovaný €ASM listing viewer distribuovaný jako vzorový projekt.

Ladicí oznámení D1??? generovaná pseudoinstrukcí %DISPLAY se vypisují i v případech jejího umístění do false větve příkazu %IF nebo do bloku vyřazeného z kompilace pomocí %COMMENT..%ENDCOMMENT.

Listing se generuje pouze v posledním průchodu (final pass). Informativní oznámení se do listingu vůbec nezapisují, s výjimkou zpráv I056?.


↑ Vstupní a výstupní soubory

Konfigurační soubor ↓

Zdrojový kód ↓

Cílový soubor ↓

Listingový soubor ↓

Cesty k souborům ↓

EuroAssembler čte dva druhy vstupních souborů: konfigurační a zdrojový.

EuroAssembler zapisuje dva druhy výstupních souborů: cílový a listing.

Pokud výstupní soubor existoval, €ASM ho bez varování přepíše

Konfigurační soubor

Konfigurační soubor s pevným názvem euroasm.ini specifikuje výchozí volby pro assembler. €ASM je načítá ze dvou souborů s identickým názvem a strukturou:

Globální konfigurační soubor je umístěn ve stejném adresáři jako spustitelný soubor euroasm.exe a zpracovává se jednou, když byl €ASM spuštěn. Pokud předtím neexistoval, €ASM se jej pokusí vytvořit s výchozími hodnotami parametrů (factory-default).

Lokální konfigurační soubor se hledá ve stejném adresáři jako zdrojový text. Pokud byl na příkazovém řádku definován více než jeden zdrojový soubor, lokální konfigurační soubor se načítá znovu vždy při zahájení zpracování zdrojového souboru.
Lokální euroasm.ini není EuroAssemblerem vytvářen, musíte zkopírovat globální soubor a případně vymazat opakující se volby kvůli lepší výkonnosti.

Příklad povelu, který kompiluje dva zdroje:
C:\PgmFiles\euroasm.exe Source1.asm D:\Temp\Source2.asm
EuroAssembler se pokusí načíst počáteční konfiguraci ze tří souborů: C:\PgmFiles\euroasm.ini, .\euroasm.ini, D:\Temp\euroasm.ini.

Počáteční obsah konfigurace zabudovaný do euroasm.exe jako factory-defaults je definován v objlib/euroasm.ini. Soubor obsahuje dvě sekce: [EUROASM] a [PROGRAM].

Ta první určuje parametry pro samotný €ASM, jako např. volbu CPU, druh informací zapisovaných do listingu, která varování se mají potlačit atd. Parametry ze sekce [EUROASM] mohou být redefinovány později ve zdrojovém textu pseudoinstrukcí EUROASM, kde také naleznete podrobnější popis parametrů.

Sekce [PROGRAM] určuje defaultní parametry vytvářeného programu, například paměťový model, formát, název výstupního souboru apod. Tyto parametry mohou být změněny později ve zdrojovém kódu pseudoinstrukcí PROGRAM.

Pořadí parametrů v konfiguračním souboru není důležité. Na velikosti písmen v názvech parametrů nezáleží. Parametry s logickými hodnotami (boolean) akceptují následující možnosti: ON, YES, TRUE, ENABLE, ENABLED jako zapnout a OFF, NO, FALSE, DISABLE, DISABLED jako vypnout. Akceptují se rovněž numerické hodnoty, které budou převedeny na logické.

Rozhodnete-li se zveřejnit svůj program v EuroAssembleru, nemusíte specifikovat parametry příkazového řádku nutného ke kompilaci a linkování, neboť tyto mohou být definovány v samotném zdrojovém kódu. Typický program v €ASM začíná konfigurační pseudoinstrukcí, jako např. EUROASM AUTOALIGN=YES,CPU=PENTIUM, takže pak není obtížné uhodnout, ve kterém asembleru byl napsán.
Jako vývojář programů v EuroAssembleru byste neměli spoléhat, že uživatelé budou mít stejný obsah euroasn.ini jako vy. Specifikujte všechna důležitá nastavení na začátku publikovaného zdrojového kódu. Lokální konfigurační soubor se hodí během vývoje, kdy zdroje ve stejném adresáři nemusejí explicitně specifikovat všechny parametry EUROASM a PROGRAM.

Povely ke konfiguraci EuroAssembleru jsou definovány v konfiguračních souborech a ve zdrojových souborech pseudoinstrukcí EUROASM). Jejich pořadí zpracování je následující:

  1. Když se euroasm.exe spustí, výchozí volby jsou již definovány pomocí factory defaults.
  2. €ASM se nyní podívá na příkazový řádek, kterým byl spuštěn. Pokud zde byly definovány některé EUROASM volby, nahradí ty aktuálně platné.
  3. €ASM nyní načte globální konfigurační soubor a reaplikuje jeho volby.
  4. Volby z příkazového řádku (pokud existují) jsou reaplikovány (krok 2 se opakuje).
  5. Pak se €ASM podívá na název zdrojového souboru na příkazové řádce, a pokud lokální konfigurační soubor existuje ve stejném adresáři, je načten a aplikován na současně platné hodnoty.
  6. Zdrojový soubor je kompilován. Každá pseudoinstrukce EUROASM nalezená v kódu přepisuje současně platnou verzi
  7. Pokud je na příkazovém řádku nalezen další zdrojový soubor, €ASM obnoví konfiguraci uloženou na konci kroku 4 a pak pokračuje od kroku 5.

↑ Zdrojový kód

Soubor se zdrojovým kódem obsahuje instrukce k překladu, obvykle se jedná o soubor s prostým textem nebo HTML text uzpůsobený pro €ASM. Název souboru bude uveden na příkazovém řádku spouštějícím euroasm.exe. Může být doplněn absolutní cestou k souboru, například euroasm /user/home/euroasm/MyProject/MySource.asm, nebo relativní či vynechanou cestou.

Struktura a obsah zdrojového kódu, který je €ASM schopen asemblovat a linkovat, je popsán níže v tomto dokumentu.

↑ Cílový soubor

Hlavním účelem programování je získat ze zdrojového soubor cílový soubor. Může jím být objektový soubor (modul) nebo knihovna linkovatelná k jiným souborům, nebo to může být binární soubor ke speciálním účelům, anebo spustitelný soubor.

Formát cílového souboru je určen parametrem FORMAT= pseudoinstrukce PROGRAM. Pro podrobnější informace o výstupních formátech viz kapitolu Programové formáty.

Název výstupního souboru je určen návěštím pseudoinstrukce PROGRAM, k němuž je připojena přípona závislá na zvoleném formátu. Název cílového souboru není nezbytně odvozen od názvu zdrojového souboru, jako u mnoha jiných asemblerů. Pokud je například ve zdrojovém souboru povel Hello PROGRAM FORMAT=COM, jeho výstupní soubor bude vytvořen v aktuálním adresáři a dostane název Hello.com bez ohledu na název zdrojového souboru. Defaultní jméno může být změněno parametrem OUTFILE= pseudoinstrukce PROGRAM. Pokud je OUTFILE= uvedeno s relativní (nebo s žádnou) cestou, použije se aktuální adresář.

↑ Listingový soubor

Parametry dumpu ↓
Oddělovače sloupců ↓
Dekorátory dumpu ↓
Parametry výpisu ↓

Listingový soubor je prostý text, kam €ASM zapisuje svou činnost:

  1. výsledek sestavení každého povelu asembleru (strojové instrukce) je zobrazen ve sloupci dump (generovaný hexadecimální kód)
  2. zpracované povely jsou kopírovány do zdrojového sloupce.

Název listingového souboru vychází z názvu a cesty zdrojového souboru, k němuž je připojena přípona .lst.
Tuto výchozí cestu a název listingu lze změnit parametrem LISTFILE= pseudoinstrukce EUROASM.

↑ Parametry dumpu

Vytvořme zdrojový soubor Hello.asm s následujícím obsahem:

      EUROASM DUMP=ON,DUMPWIDTH=18,DUMPALL=YES
Hello PROGRAM FORMAT=COM,LISTLITERALS=ON, \
              LISTMAP=OFF,LISTGLOBALS=OFF
       MOV DX,=B"Hello, world!$"
       MOV AH,9
       INT 21h
       RET
      ENDPROGRAM Hello

Předložíme-li tento soubor EuroAssembleru příkazem euroasm Hello.asm, vygeneruje se mimo jiné listing Hello.asm.lst.

Šířka hexadecimálního výstupu (levý sloupec listingu) je určena volbou EUROASM DUMPWIDTH=. Další volby EUROASM, které ovlivňují levý sloupec, jsou DUMPALL= a DUMP=OFF, která umí kompletně potlačit levý sloupec.

|<-Sloupec dump->|<--Zdrojový sloupec----- <--DumpWidth=18--> | | EUROASM DUMP=ON,DUMPWIDTH=18,DUMPALL=YES | |Hello PROGRAM FORMAT=COM,LISTLITERALS=ON, \ | | LISTMAP=OFF,LISTGLOBALS=OFF |[COM] ::::Section changed. |0100:BA[0801] | MOV DX,=B"Hello, world!$" |0103:B409 | MOV AH,9 |0105:CD21 | INT 21h |0107:C3 | RET |[@LT1] ====ListLiterals in section [@LT1]. |0108:48656C6C6F =B"Hello, world!$" |010D:2C20776F72 ----Dumping all. (kvůli DUMPALL=YES) |0112:6C64212400 ----Dumping all. | | ENDPROGRAM Hello ▲ oddělovač sloupců
↑ Oddělovače sloupců

Levý sloupec listingu vždy začíná indikátorem strojové poznámky (znakem roura |) a je ukončen oddělovačem sloupců, který určuje původ řádku.

Oddělovač sloupců
ZnakFunkce
| (roura)Konec strojové poznámky. Používá se u běžných instrukcí, které mohou být znovu užity jako €ASM zdroj.
! (vykřičník)Kopie zdrojového řádku s expandovanými %proměnnými (pokud LISTVAR=ENABLED).
+ (plus)Zdrojové řádky generované při expanzi z %FOR,%WHILE,%REPEAT (pokud LISTREPEAT=ENABLED).
+ (plus)Zdrojové řádky generované při expanzi z %MACRO (pokud LISTMACRO=ENABLED).
: (dvojtečka)Řádka přidaná do listingu k zobrazení změněné [sekce].
. (tečka)Řádka přidaná do listingu k zobrazení autoalignmentu (pokud AUTOALIGN=ENABLED).
- (minus)Řádka přidaná do listingu k zobrazení celého dumpu (pokud DUMPALL=ENABLED).
= (rovnítko)Řádka přidaná do listingu k zobrazení literálů (pokud LISTLITERALS=ENABLED).
  (mezera)Řádka přidaná do listingu k zobrazení obálkových řádků PROGRAM..ENDPROGRAM.
* (hvězdička)Řádka přidaná do listingu k zobrazení povelu INCLUDE* s vyřešením zástupných znaků *?

S výjimkou oddělovače roura | mají řádky listingu formu strojové poznámky a jsou tudíž ignorovány, pokud bude listing znovu předložen EuroAssembleru jako zdrojový soubor.

↑ Dekorátory dumpu

Hexadecimální výpis strojového kódu (dump) u emitujících povelů začíná hexadecimální adresou (ofsetem v aktuální sekci), která je ukončena dvojtečkou :. V 16bitové sekci je tato adresa široká 16 bitů (čtyři hexadecimální cifry), v 32bitové a 64bitové sekci je to 32 bitů. Pak následují emitované (generované) bajty. Čísla v levém sloupci jsou vždy v hexadecimálním tvaru, bez uvádění explicitního číselného modifikátoru.

Pokud je zvolený parametr DUMPWIDTH= příliš nízký k zobrazení všech dat, jsou buď vpravo oříznuty a nahrazeny tildou ~ (pokud DUMPALL=OFF), anebo jsou do listingu přidány další řádky s oddělovačem - (pokud DUMPALL=ON).

V hexadecimálním výpisu mohou být použity ještě další dekorátory:

Dekorátory dumpu
DekorátorPopis
~indikace zkrácení výpisu, používaná pokud DUMPALL=OFF
..bajt rezervovaných dat (namísto hexadecimální hodnoty jsou-li data inicializována)
[]indikátor absolutní relokace
()indikátor relativní relokace
{}indikátor paragrafové relokace
<Npoužita komprese disp8*N

Závorky [], () a {} obklopující hexadecimálně vypsané slovo nebo dvojslovo indikují, že adresa vyžaduje relokaci v link-time. Hodnota zobrazená v listingu se bude lišit od ofsetu zobrazovaného ve slinkovaném kódu nebo v debugeru při běhu programu.

Znak < následovaný dekadickou číslicí (N) signalizuje, že předchozí 8bitový displacement má být posunout vlevo o N bitů k získání efektivní hodnoty. (takzvaná komprese disp8*N). Číslice 1..6 specifikující kompresní faktor N není do sestaveného kódu emitována.

Závorky [ ] a { } indikují relokabilní hodnoty. | | EUROASM DUMPWIDTH=30,CPU=X64,SIMD=AVX512,EVEX=ENABLED |[CODE] ▼ ▼▼ ▼ |[CODE] SEGMENT WIDTH=16 |0000:EA[0500]{0000} | JMPF Label ; Absolute far jump encodes immediate seg:offset. |0005:CB |Label: RETF |[CODE64] |[CODE64] SEGMENT WIDTH=64 |00000000:62F36D28234D02<504 | VSHUFF32X4 YMM1,YMM2,[RBP+40h],4 |00000008:C3 ▲▲ | RET <5 je neemitovaný dekorátor disp8*N. ▲▲Displacement +02h bude posunut vlevo 5krát, takže efektivní displacement je ve skutečnosti +40h.

U neemitujících instrukcí je sloupec dumpu buď prázdný, nebo obsahuje přídavné informace:

|[DATA] |[DATA] ; Přepnutí segment|section opakuje název ve sloupci dumpu. |0000: |; Prázdný nebo komentářový řádek zobrazuje ve sloupci dumpu pouze adresu v současné sekci. |0000: |Label: ; Ditto. | |;; Řádkový komentář začínající dvojitým středníkem potlačí výpis adresy ve sloupci dumpu. |[DATA]:0000 |Target EQU Label: ; Adresní symbol je zobrazen jako [segment]:offset. |4358 |%Counter %SET CX ; Nastavení %variable vypisuje její obsah hexadecimálně. |TRUE | %IF "%Counter" == "CX" ; Předasemblerovský konstrukt zobrazuje vyhodnocenou logickou podmínku. |[]:0010 | Bits EQU 16 ; Skalár (numerický symbol) je zobrazen s prázdným segmentem. |FALSE | %ELSE ; Logické podmínky se týkají pseudoinstrukcí %IF, %ELSE, %WHILE, %UNTIL. | | Bits EQU 32 ; Dump je prázdný v neemitovaných větvích %IF. | | %ENDIF
↑ Parametry výpisu

Listingový soubor ve své defaultní konfiguraci je víceméně přesnou kopií zdrojového souboru, až na přidaný sloupec dumpu. V některých případech může být potřeba zkontrolovat, zda určité konstrukty fungují podle očekávání. To se řídí následujícími parametry pseudoinstrukce EUROASM:
LISTINCLUDE=ON zobrazuje obsah vloženého souboru, který by byl jinak skryt.
LISTVAR=ON vytváří kopii každého povelu, ve které nahradí preprocesorovou %proměnnou její expandovanou hodnotou.
LISTMACRO=ON vkládá do listingu povely expandované v makroinstrukci.
LISTREPEAT=ON vkládá všechny iterace opakujících se konstruktů %FOR..%ENDFOR, %WHILE..%ENDWHILE, %REPEAT..%ENDREPEAT. Opakující se expanze jsou v listingu zobrazeny jako vykomentované pomocí separátoru +. Ve výchozím stavu, kdy je LISTREPEAT=DISABLED, je zobrazována pouze první expanze.

Užitečnou vlastností listingu v €ASM je snaha udržovat jej znovupoužitelný jako zdrojový kód.

Chtěl jsem udržet tuto funkčnost bez ohledu na stav parametrů LIST*. Ve výchozím stavu, kdy je LISTINCLUDE=OFF, je povel INCLUDE normálně zobrazen a obsah vloženého souboru je skryt. Povelem EUROASM LISTINCLUDE=ON se to obrací: originální pseudoinstrukce INCLUDE je odkomentována separátorem dumpu *, avšak řádky vložené tímto souborem jsou vloženy do listingu a stávají se tak platnými zdrojovými příkazy. Viz test t2220.

Jsou li volby LISTVAR, LISTMACRO, LISTREPEAT zapnuty (enabled), originální řádek s parametrem EUROASM LISTVAR=ENABLED je zachován a expandované řádky budou vloženy pod něj a odkomentovány separátorem ! nebo +. Viz test t2230.

Volba EUROASM LIST=DISABLE zcela vypne generování listingu až do opětovného povolení, případně do konce souboru. Takový listing samozřejmě nebude znovupoužitelný jako zdrojový soubor.

↑ Cesty k souborům

Diskové soubory mohou být specifikovány včetně absolutní cesty, tj. cesty jež začíná v kořenu souborového systému, např. C:\ProgFiles\euroasm.exe D:\Project\source.asm.

Soubory mohou být rovněž určeny relativní cestou, např. euroasm ..\prowin32\skeleton.asm. Relativní cesta se vždy vztahuje k současnému pracovnímu adresáři.

Soubory mohou být specifikovány bez cesty, tj, pokud jejich název nebosahuje dvojtečku ani lomítko :, \, /. Umístění takových souborů je pak rekapitulováno níže uvedenou tabulkou:

Adresář použitý při specifikaci souboru bez cesty
SouborVýznamUmístěníViz také
Executableeuroasm.exeAdresář s euroasm.exeOS PATH
InputGlobalní euroasm.iniAdresář s euroasm.exeOS PATH
OutputGlobalní euroasm.iniAdresář s euroasm.exeOS PATH
InputLokální euroasm.iniAdresář se zdrojem
InputZdrojový souborAktuální adresář
InputVložený zdrojový souborAdresář vkládaných souborůEUROASM INCLUDEPATH=
OutputCílový soubor Aktuální adresářPROGRAM OUTFILE=
OutputListingový souborAdresář se zdrojemEUROASM LISTFILE=
InputLinkovaný modulAdresář linkovaných modulůEUROASM LINKPATH=
InputLinkovaný stubAdresář linkovaných modulůPROGRAM STUBFILE=
InputLinkovaný soubor ikonyAdresář linkovaných modulůPROGRAM ICONFILE=
ImportDynamicky importovaná funkceZávisí na OSIMPORT LIB=

Aktuálním adresářem se rozumí složka přiřazená shellu v okamžiku, kdy by euroasm.exe spuštěn. €ASM ho nikdy nemění.

Adresář s euroasm.exe je složka, v níž se nachází euroasm.exe, obvykle jeden z adresářů uvedených v proměnné environmentu PATH.

Adresář se zdrojem je složka, v níž je umístěn soubor s překládaným zdrojovým kódem.

Adresář vkládaných souborů je jeden z adresářů uvedených v parametru EUROASM INCLUDEPATH=.

Adresář linkovaných modulů je jeden z adresářů uvedených v parametru EUROASM LINKPATH=.


↑ Struktura €ASM programu

Znaková struktura ↓

Horizontální struktura ↓

Vertikální struktura ↓

Tato kapitola popisuje formát zdrojového souboru, kterému €ASM rozumí a je schopen jej překládat.


↑ Znaková sktruktura

Šířka znaků ↓

Kódování znaků ↓

Velikost písmen ↓

Klasifikace znaků ↓


↑ Šířka znaků

Zdrojový soubor obsahuje sled znaků s šířkou 8 bitů nebo s proměnnou šířkou 8..32 bitů (v kódu UTF-8).

Pokud byl zdrojový text napsán editorem používajícím WIDE (16bitové) kódování znaků (UTF-16), musí být nejprve uložen jako prostý text v UTF-8 nebo v 8bitovém kódování ANSI nebo OEM, než bude předložen EuroAssembleru.

↑ Kódování znaků

Program napsaný v €ASM může chtít zobrazovat texty v jiných jazycích než v angličtině. Takový text obsahuje znaky s hodnotou codepointu nad 127 (codepoint je pořadové číslo znaku v tabulce [Unicode]).
Mnoho evropských jazyků je spokojeno s omezenou sadou 256 znaků. Relace mezi jejich kódy a odpovídajícím fontem se nazývá kódová stránka (Codepage).

MS-Windows používá různé kódové strany v konzolových aplikacích (OEM) a v grafických aplikacích (ANSI) a občas mezi nimi provádí automatické konverze. Avšak €ASM kódovou stranu zdrojového textu nikdy nemění.

Programátor používající v aplikaci několik lidských jazyků by měl v MS-Windows používat 16bitové znaky WIDE namísto 8bitových ANSI znaků v textových řetězcích. Jako demo-ukázku viz cpmix32.

Široké kódování (UTF-16) je definováno pseudoinstrukcí DU (Define data in Unichars) namísto DB (Define data in Bytes). Příslušné volání WinAPI musí být ve variantě WIDE pro správnou vizuální reprezentaci za běhu, např. TextOutW() namísto ANSI varianty TextOutA(). I tak ale kódování znaků v definici DU je stále 8bitové. Měli byste sdělit EuroAssembleru, která kódová strana byla použita při psaní 8bitového zdrojového textu. Tuto informaci poskytuje parametr EUROASM CODEPAGE=. Kódová strana se může v rámci zdrojového textu dynamicky měnit a dovoluje tak střídat více jazyků v rámci téhož programu.

Texty mířící na konzolu (používající ANSI verzi WinAPI funkcí, jako např. WriteConsoleA() nebo makroinstrukci StdOutput) by měly být psány v kódové stránce OEM. Asi budete používat dosový editor plain-textu, jako např. EDIT.COM ke psaní konzolových programů. Tyto editory používají konzolové fonty v OEM kódových stránkách, takže texty jsou zobrazeny korektně jak v editoru během psaní programu, tak i za jeho běhu.

Texty s volbou PROGRAM SUBSYSTEM=GUI zamýšlené pro grafický mód (používající WinAPI funkce jako TextOutA()) by měly být psány v kódové straně ANSI, např. pomocí Notepad.exe.

Výchozí volbou je EUROASM CODEPAGE=UTF-8, kdy znaky mají proměnnou šířku od jednoho do čtyř bajtů. Díky inteligentnímu kódování [UTF8] jsou všechny non-ASCII UTF-8 znaky kódovány jako bajty s hodnotou 128..255, což €ASM považuje za písmena, takže mohou být beze změny použity v indentifikátorech.

Doporučené kódování zdrojových textů EuroAssembleru je UTF-8.

Na rozdíl od 8bitových kódování ANSI nebo OEM, které omezují repertoár na 256 znaků, CODEPAGE=UTF-8 dovoluje mísení libovolných znaků definovaných v tabulce [Unicode] včetně neevropských abeced. MS-Windows API nepodporuje přímo řetězce v UTF-8, tyto vyžadují překódování za běhu na UTF-16, které jsou používány variantou WIDE u WinAPI funkcí jako TextOutW(). Toto překódování zajistí WinAPI MultiByteToWideChar() anebo makro DecodeUTF8. Samozřejmě ke korektnímu zobrazování exotických znaků (asijské abecedy, emoji ap.) je potřeba mít instalovány patřičné fonty.

Příklad freeware textového editoru podporujícího kódování UTF-8 je [PSPad].
Některé editory vkládají na začátek souboru sekvenci Byte Order Mark, tj. 0xEF, 0xBB, 0xBF. EuroAssembler považuje tyto tři znaky za tříznakové nepoužité návěstí na začátku zdrojového souboru, což obvykle ničemu nevadí.

↑ Velikost písmen

€ASM je částečně nezávislý na velikosti písmen.

U všech identifikátorů vytvořených vámi (programátorem) na velikosti písmen záleží: návěští, konstanty, uživatelské %proměnné, struktury, sekce, názvy maker. Naopak u vestavěných názvů na velikosti písmen nezáleží. Necitlivost k velikosti se týká všech výčtových hodnot: názvů registrů, strojových instrukcí a prefixů, vestavěných datových typů, číselných modifikátorů, jmen a parametrů pseudoinstrukcí, souborových atributů, systémových %^proměnných.

Názvy nezávislé na velikosti znaků jsou v tomto manuálu uváděny VELKÝMI PÍSMENY, ale mohly být zrovna tak psány malými nebo smíšenými znaky.

↑ Klasifikace znaků

Každý bajt (8 bitů) ve zdrojovém textu €ASM je považován za znak. Mnoho znaků má v syntaxi asembleru speciální funkci, až na případy, kdy jsou umístěny uvnitř dvojitých nebo jednoduchých uvozovek. Znak je považován za neuvozený (unquoted) pokud se mezi ním a mezi počátkem řádku vyskytlo nula nebo sudý počet uvozovek.

Konec řádku
Znak určující konec řádku je Line Feed alias EOL (ASCII 10).
Netisknutelné znaky
Ostatní řídicí znaky, delete a mezera se považují za netisknutelné znaky (white spaces). Mohou být použity jako oddělovače zlepšující čitelnost, avšak jen zřídka mají nějaký syntaktický význam. Neuvozené vícenásobné netisknutelné znaky jsou zpracovány stejně jako znak jediný.
Číslice
Číslice 0..9 tvoří čísla a identifikátory. Hexadecimální čísla mohou navíc obsahovat hexadecimální číslice A..F, a..f.
Písmena
Za písmena se v €ASM považují znaky a..z, A..Z, podtržení _, komerční at @, dolar $, přízvuk grave `, otazník ? a všechny znaky z horní poloviny ASCII tabulky (128..255).
Několik písmen je v €ASM využito ke speciálním účelům:
Podtržítko _ je používáno v identifikátorech a číslech jako oddělovač namísto mezery.
Komerční at na začátku názvu indikuje název sekce s literály.
Samotné znaménko dolaru $ představuje symbol reprezentující současný ofset v rámci sekce.
Znak grave ` se používá jako prefix v případech, kdy název souboru nezačínající písmenem má představovat platný identifikátor.
Ostatní
Všechny ostatní znaky mají v €ASM speciální význam – operátory, oddělovače, modifikátory apod.– ledaže by byly umístěny uvnitř dvojice jednoduchých ' nebo dvojitých " uvozovek. S výjimkou procenta % a konce řádku EOL jsou tyto znaky považovány za běžná písmena, pokud jsou umístěny uvnitř řetězce v uvozovkách.
Tabulka klasifikace znaků
ASCIIznak jméno funkce v €ASM
0..9 řídicí netisknutelný znak neboli bílá mezera
10 konec řádku konec řádku
11..31 řídicí netisknutelný znak neboli bílá mezera
32 mezera netisknutelný znak neboli bílá mezera
33! vykřičník logický operátor
34" dvojitá uvozovka ohraničení řetězce
35# modifikátor modifikátor
36$ dolar písmeno
37% procento prefix preprocesingu
38& ampersand logický operátor
39' apostrof ohraničení řetězce
40( levá závorka prioritní závorka
41) pravá závorka prioritní závorka
42* hvězdička aritmetický a speciální operátor
43+ plus aritmetický operátor
44, čárka oddělovač operandů
45- minus aritmetický operátor
46. tečka oddělovač členů
47/ lomítko aritmetický operátor
48..570..9 číslice číslice
58: dvojtečka oddělovač
59; středník indikátor komentáře
60< méně než logický operátor, oddělovač komentáře
61= rovnítko logický operátor, klíčový oddělovač, indikátor literálu
62> více než logický operátor
63? otazník písmeno
64@ komerční at písmeno
65..90A..Z velká písmena písmeno
91[ levá hranatá závorkazávorka paměťového obsahu, operátor substringu
92\ zpětné lomítko aritmetický operátor, pokračování řádku
93] pravá hranatá závorkazávorka paměťového obsahu, operátor substringu
94^ caret logický operátor
95_ podtržítko písmeno, oddělovač číslic
96` grave písmeno
97..122a..zmalá písmena písmeno
123{ levá složená závorkaoperátor sublistu
124| roura logický operátor, oddělovač strojové poznámky
125} pravá složená závorkaoperátor sublistu
126~ tilda logický operátor, indikace zkratky
127 delete netisknutelný znak neboli bílá mezera
128..255 non ASCII znaky písmeno
ASCIIznak jméno funkce v €ASM

↑ Horizontální struktura

Fyzický řádek ↓

Instrukce ↓

Strojová poznámka ↓

Návěstí ↓

Prefix ↓

Operace ↓

Operand(y) ↓

Řádková poznámka ↓

Pokračování řádku ↓

Zdrojový soubor považujeme za text sestávající z řádků zpracovávaných zleva doprava, shora dolů.


↑ Fyzický řádek

Zdrojový soubor sestává z fyzických řádků. Fyzický řádek je řada znaků zakončená EOL (ASCII 10). Znak EOL je rovněž součástí fyzického řádku. Může být vynechán pouze pokud se jedná o poslední fyzický řádek souboru.

↑ Instrukce

Instrukce (statement) je příkaz pro €ASM provést určitou akci, obvykle emitovat nějaký kód do cílového souboru nebo změnit svůj vnitřní stav. Typická instrukce zabírá právě jeden fyzický řádek, avšak delší instrukce mohou přesahovat do dalších řádků, pokud je použito pokračování řádku.

Instrukce sestává z několika polí, ty jsou rozlišovány podle pozice v řádku, podle separátoru nebo podle jejich obsahu. Všechna pole instrukce jsou nepovinná, kterékoli může být vynecháno, jen pole operandů nelze použít, bylo-li vynecháno pole operace.

Pole v rámci instrukce
PořadíNázev poleUkončení
1.Strojová poznámka| nebo EOL
2.Návěstí : nebo bílá mezera
3.Prefix : nebo bílá mezera
4.Operace bílá mezera
5.Operand ,
6.Řádkový komentářEOL

Příklad instrukce:

| strojová poznámka |Návěstí|Prefix|Operace | Operand | Řádkový komentář |00001234:F08705[78560000] |Mutex: LOCK: XCHG EAX,[TheLock] ; Guard the thread.

↑ Strojová poznámka

Strojová poznámka začíná znakem vertikální čára (roura) |, pokud je to první nebílý znak na řádku. Poznámka je ukončena druhým výskytem téhož znaku anebo koncem fyzického řádku.

Obsahem strojové poznámky je obvykle hexadeciální adresa následovaná strojovým kódem generovaným dotyčnou instrukcí. Jak její název napovídá, strojovou poznámku generuje počítač do listingového souboru; programátor ji nikdy nepotřebuje generovat ručně
Strojové poznámky jsou ve zdrojovém kódu ignorovány, takže platný listing může být beze změny znovupoužit jako zdrojový soubor.

↑ Návěstí

Pole pro návěstí může hostit kterýkoli z těchto prvků:

  1. Jméno struktury nebo symbolu nebo identifikátor bloku, např. My1stStructure, My1stLabel:, Outer
  2. Jméno sekce, segmentu nebo grupy v hranatých závorkách. např. [.data]
  3. Jméno předprocesorové %proměnné nastavované pomocí %SET*, např. %Count
  4. Samotná dvojtečka : výslovně říká EuroAssembleru, že je použito prázdné návěstí, takže následující pole musí být prefix nebo operace.

V prvním případě může jméno symbolu nebo struktury začínat tečkou ., což je činí lokálním. Symbol v poli návěstí může být zakončen jednou nebo více dvojtečkami : bezprostředně za identifikátorem. Mezera mezi návěstím a následným polem může být v tom případě vynechána.

↑ Prefix

Strojový prefix je povel pro CPU změnit svůj vnitřní stav za běhu programu (v run-time). Podobá se strojové instrukci a ovlivňuje následující instrukci za běhu. Každý prefix se překládá na jednobytový operační kód.

Tabulka prefixů
JménoSkupinaOperační kód
LOCK10xF0
REP10xF3
REPE10xF3
REPZ10xF3
REPNE10xF2
REPNZ10xF2
XACQUIRE10xF2
XRELEASE10xF3
SEGCS20x2E
SEGSS20x36
SEGDS20x3E
SEGES20x26
SEGFS20x64
SEGGS20x65
SELDOM20x2E
OFTEN20x3E
OTOGGLE30x66
ATOGGLE40x67

Poslední čtyři názvy jsou implementovány pouze v EuroAssembleru.
SELDOM a OFTEN lze použít před podmíněnými skoky jako nápovědu pro novější CPU, jak předvídat výsledek.
OTOGGLE a ATOGGLE přepínají mezi 16bitovou a 32bitovou šířkou operandů a adresní částí strojového kódu. Tyto prefixy jsou normálně generovány asemblerem interně, bez explicitní žádosti.

V jedné instrukci mohou být definovány až čtyři prefixy, avšak z každé skupiny pouze jeden.

Jméno prefixu nelze použít jako návěstí, bez ohledu na velikost písmen.

Názvy prefixů jsou rezervovány, nelze je použít jako návěstí. Název může být zakončen dvojtečkou :, podobně jako symbol.

64bitová architektura AMD a Intel zavedla speciální prefixy REX, XOP, VEX, MVEX, EVEX. €ASM považuje tyto prefixy za součást zakódování operace a neposkytuje proto mnemoniku pro jejich přímou deklaraci.

[AMDSSE5] zavedl ještě jeden prefix DREX, avšak jelikož se instrukce s tímto prefixem nedostaly do výroby, €ASM je nepodporuje.

Prefixy pro změnu segmentu SEG*S mohou být alternativně předpisovány jako komponenty paměťových proměnných v rámci registrového výrazu. V tom případě je prefix emitován pouze pokud není redundantní (pokud specifikuje nedefaultní segment). Explicitně specifikované prefixy jsou emitovány vždy, v pořadí, v jakém se objevily v instrukci.

EuroAssembler vydává varování, pokud byl prefix použit v rozporu s doporučením pro CPU. Lze to přepsat uvedením prefixu na samostatném řádku.

|0000:F091 |LOCK: XCHG AX,CX ; Prefix Lock by neměl být použit s registrovými operandy. |## W2356 Prefix LOCK: is not expected in this instruction. |0002:F0 |LOCK: ; Varování W2356 lze zamezit uvedením prefixu na samostatném řádku, |0003:91 | XCHG AX,CX ; např. kvůli zjišťování chování procesoru v takové situaci. |0004: | |0004:6691 | XCHG EAX,ECX ; Prefix 0x66 je emitován interně (v 16bitovém segmentu). |0006:6691 |OTOGGLE: XCHG EAX,ECX ; Jeho explicitní specifikace se nijak neprojeví, |0008:6691 |OTOGGLE: XCHG AX,CX ; avšak zde mění šířku registrů z 16 na 32 bitů.

↑ Operace

Pole operace je nejdůležitější část instrukce, předepisuje EuroAssembleru, co má dělat: něco deklarovat, změnit svůj vnitřní stav, emitovat něco do cílového souboru. Často udává jméno celé instrukci: mluvíme např. o operaci EXTERN namísto o instrukci s pseudoinstrukcí EXTERN v poli operace.

€ASM rozlišuje tři rody operací:

Instrukce mohou mít pole operace prázdné:

[CODE]   ; Přesměruj další emitování do sekce [CODE].
         ; Prázdnou instrukci lze použít pro optické oddělení nebo pro poznámku.
Label:   ; Definice návěstí, které však neemituje žádný kód ani data.
LOCK:    ; Definice strojového prefixu pro následnou instrukci.

Většina instrukcí žádá €ASM o generování strojového kódu nebo dat do cílového souboru, říká se jim emitující instrukce:

↑ Operand(y)

Pořadové operandy ↓
Klíčové operandy ↓
Mísení operandů ↓

Operandy specifikují data, s nimiž instrukce pracuje. Počet operandů v instrukci není omezen a závisí na poli operace. Operandem může být jméno registru, číslo, matematický výraz, identifikátor, řetězec nebo jejich kombinace.

Pole operace je odděleno od prvního operandu nejméně jednou bílou mezerou. Operandy jsou navzájem odděleny čárkou ,, která není v uvozovkách. €ASM rozlišuje dva druhy operandů: pořadové a klíčové.


↑ Pořadové operandy

Pořadové operandy (neboli stručně ordinály) jsou definovány jejich pořadím v instrukci. První operand má pořadové číslo jedna; v makrech je identifikován jako %1. Například v instrukci MOV AL,BL má registr AL pořadové číslo 1 a BL číslo 2. Strojová instrukce MOV kopíruje obsah druhého operandu do prvního. Čárka mezi operandy zvyšuje pořadové číslo následujícího operandu i v případě, že je prázdný (obsahuje nanejvýš netisknutelné znaky).

Operand strojové instrukce může představovat registr, bezprostřední číselnou hodnotu, adresu nebo paměťovou proměnnou v hranatých závorkách, např. MOV AL,[ES:SI+16].

Jiné asemblery akceptují odlišnou syntaxi v paměťové proměnné, která však není podporována v €ASM, např. MOV AL,ES:[SI+16] nebo MOV AL,[ES:16]+SI.
€ASM vyžaduje, aby byl celý paměťový operand umístěn do hranatých závorek [].
↑ Klíčové operandy

Vedle pořadových operandů zavádí €ASM ještě jeden typ parametrů: klíčové operandy (neboli stručně klíče). Na klíče odkazujeme jménem (klíčovým slovem) namísto jejich pořadí v seznamu operandů. Klíčový operand má formát jméno=hodnota, kde jméno je identifikátor bezprostředně následovaný rovnítkem.

Klíčové operandy mají řadu výhod: jsou samopopisné (při rozumně zvoleném klíčovém slovu), nezáleží na jejich pořadí v seznamu operandů (žádné počítání čárek), mohou mít přiřazenu výchozí hodnotu a mohou být zcela vynechány, pokud mají výchozí hodnotu.

Klíčové operandy se nejčastěji pouívají u makroinstrukcí, avšak €ASM je umí využít u některých pseudoinstrukcí a dokonce i u strojových instrukcí. Například v instrukci INC [EDI],DATA=DWORD klíčový operand DATA= informuje, kterou formu z možných strojových instrukcí INC chceme použít (inkrementovat BYTE, WORD nebo DWORD).

Pozor na vložení mezery mezi klíč a rovnítko:

|0000: |; Definujme dvě paměťové proměnné (s nedoporučenými názvy). |0000:3412 |DATA: DW 1234h |0002:7856 |WORD: DW 5678h |0004: | |0004:50 | PUSH AX, DATA=WORD |0005: |; Přeloženo jako PUSH AX. |0005: |; Operand DATA=WORD je rozpoznán jako redundantní avšak platný modifikátor. |0005: | |0005:506A00 | PUSH AX, DATA = WORD |0008: |; Operand DATA = WORD není rozpoznán jako klíčový |0008: |; kvůli mezeře následující klíč DATA. |0008: |; €ASM vidí druhý operand jako numerické srovnání symbolů DATA a WORD, |0008: |; které náhodou v program existují (jinak by se vydalo hlášení E6601). |0008: |; Jejich ofsety (0000h a 0002h) se liší, výsledkem je logické FALSE |0008: |; reprezentované hodnotou 0. Instrukce je vyhodnocena jako PUSH AX, 0 |0008: |; což je legální, neboť €ASM akceptuje sjednocování vícenásobných operandů |0008: |; do jedné instrukce v případě PUSH, POP, INC, DEC. |0008: |; Řádek je přeložen do dvou strojových instrukcí: PUSH AX a PUSH 0.
↑ Mísení operandů

Na pořadí klíčových operandů nezáleží. Je dobrým zvykem nejprve uvádět pořadové operandy a teprve pak všechny klíčové, avšak klíče mohou být rovněž rozptýleny mezi ordinály.

Klíčový operand nezvyšuje pořadové číslo.
Label1: Operation1 Ordinal1,Ordinal2,,Ordinal4,,
Label2: Operation2 Ordinal1,Keyword1=Value1,Ordinal2,,Ordinal4

Operation1 v předchozím příkladu má tři operandy s pořadovými čísly 1,2 a 4. Třetí oprand je prázdný a poslední dvě čárky na konci se ignorují, jelikož nenásleduje žádný neprázdný operand.

U Operation2 jsou použity smísené operandy. Všimněte si, že Ordinal2 má pořadové číslo 2, přestože je to třetí operand na seznamu. Klíčové operandy se nepočítají do pořadových čísel ordinálů, avšak prázdné operandy ano.

↑ Řádková poznámka

Řádková poznámka začíná neuvozeným středníkem ; a končí až s koncem fyzického řádku. Řádkové poznámky asembler ignoruje, jsou určeny pro lidského čtenáře strojového kódu.

↑ Pokračování řádku

Instrukce pokračuje na dalším fyzickém řádku, pokud se na pozici začátku některého pole vyskytne pokračovací znak, kterým je neuvozené zpětné lomítko \.

 aLabel:       \ ; Tento středník je redundantní
     MOV EAX,  \ První operand instrukce MOV je cíl
         EBX   ; a druhý operand je zdroj.

Vše za pokračovacím znakem se považuje za komentář a nepřekládá, takže středník pak může být vynechán. V mnohořádkových instrukcích můžeme komentovat kterýkoli fyzický řádek.

Pokračovací znak se může vyskytnou na začátku kteréhokoli pole, avšak ne uvnitř pole.

Celé pole se musí vejít na jeden fyzický řádek.

Zpětné lomítko \ je v €ASM rovněž použito jako binární operátor modulo, avšak binární operátor se nemůže vyskytnout na začátku operace a být tudíž zaměněn za pokračovací znak.

;                   modulo  modulo pokračovací znak
;                      |      |    |  
|0000:01000200 |  DW 5 \ 4, 6 \ 4, \
|0004:03000000 |     7 \ 4, 8 \ 4

↑ Vertikállní struktura

Blokové instrukce ↓

Přepínací instrukce ↓

Samostatné instrukce ↓

Instrukce jsou zpracovávány jedna po druhé shora dolů; některé mohou ovlivňovat své následníky, nicméně většina z nich jsou samostatné. Z toho pohledu jsou tři druhy instrukcí


↑ Blokové instrukce

Bloková instrukce se musí vyskytovat v páru se svou zakončující instrukcí. Interní stav €ASM se změnil pouze mezi blokovou a zakončující instrukcí. Tomuto rozsahu se říká block.

Blok je souvislý zdrojový kód mezi instrukcemi začátek-bloku a konec-bloku.

Blok začíná na poli operace instrukce začátku-bloku a končí na poli operace instrukce konce-bloku.

Některé blokové operace mohou být předčasně zrušeny operací přerušení-bloku (EXIT), například po zjištění chyby během expanze makra.

Blokové instrukce
NávěstíOperace
ZávaznostCo představujeCo deklaruje Počátek-blokuPřerušení-bloku Konec-bloku
povinnénázev programuprogram PROGRAMnepoužívá se ENDPROGRAM
povinnénázev procedurysymbol PROC nepoužívá se ENDPROC
povinnénázev procedurysymbol PROC1 nepoužívá se ENDPROC1
povinnénázev strukturystructuruSTRUC nepoužívá se ENDSTRUC
volitelnéidentifikátor blokunic HEAD nepoužívá se ENDHEAD
volitelnéidentifikátor blokunic %COMMENTnepoužívá se %ENDCOMMENT
volitelnéidentifikátor blokunic %IF %ELSE %ENDIF
volitelnéidentifikátor blokunic %WHILE %EXITWHILE %ENDWHILE
volitelnépřehozené identifikátorynic %REPEAT %EXITREPEAT%ENDREPEAT
povinnéformální %proměnná%variable%FOR %EXITFOR %ENDFOR
povinnénázev makramakro %MACRO %EXITMACRO %ENDMACRO

Některé blokové instrukce mají více jmen (aliasů):
místo ENDPROC lze použít ENDP,
místo ENDPROC1 lze použít ENDP1,
místo %ENDREPEAT lze použít %UNTIL.

Pole návěstí blokové instrukce definuje název programu, procedury, struktury nebo makra.
V případě bloku %FOR..%ENDFOR návěstí deklaruje formální %proměnnou, která mění svou hodnotu v každém cyklu.
V ostatních preprocesorových smyčkách (%REPEAT, %WHILE) je pole návěstí nepovinné. Může obsahovat identifikátor, který opticky spojuje počáteční a koncovou blokovou instrukci (kvůli kontrole na vnořování), avšak jinak nemá žádný význam - nedeklaruje symbol.

Identifikátor bloku může být použit jako první (a jediný) operand odpovídající instrukce pro přerušení-bloku a konce-bloku.

Asemblery nejsou jednotné v syntaxi bloků. MASM používá tentýž blokový identifikátor v poli návěstí u obou instrukcí počátek-procedury i konec-procedury:

MyProcedure PROC    ; MASM syntaxe
     ; kód procedury
MyProcedure ENDP

To je vhodné pro rychlé vyhledání procedury, kdy nás její název uhodí do oka při projíždění levého sloupce. Na druhé straně se ale totéž návěstí objevuje dvakrát, což je v rozporu s nutností unikátnosti názvů symbolů.

Možná to byl důvod, proč Borland ve svém TASM IDEAL módu zvolil odlišnou syntaxi:

 PROC MyProcedure   ; TASM syntaxe
        ; kód procedury
 ENDP MyProcedure

Toto řeší problém dvojího výskytu téhož návěstí, avšak název MyProcedure se nikdy neobjevuje v poli návěstí, třebaže se jedná o řádný symbol.

€ASM přináší kompromisní řešení: jméno bloku je definováno v poli návěstí instrukce začátku-bloku a zároveň se může objevit v poli operandů instrukce konec-bloku.

MyProcedure PROC  ; €ASM syntaxe
                  ; kód procedury
            ENDP MyProcedure

Operand instrukce konec-bloku může být vynechán, avšak pokud je použit, musí být identický s návěstím instrukce začátek-bloku. To umožňuje kontrolu vnoření, neboť €ASM ohlásí chybu, pokud identifikátory nesouhlasí.

Bloky se mohou vnořovat, avšak pouze korektně.

Dva bloky jsou korektně vnořeny, pokud jeden blok obsahuje celičký druhý blok.

Blok %MACRO..%ENDMACRO v následujícím příkladu obsahuje korektně vnořený block %IF..%ENDIF:

WriteCMOS %MACRO Address,Value
           %IF %1 <= 30h
             %ERROR "Checksum protected area!"
             %EXITMACRO WriteCMOS
           %ENDIF
           MOV AL,%1
           OUT 70h,AL
           MOV AL,%2
           OUT 71h,AL
          %ENDMACRO WriteCMOS
Chybné vnoření bloků bude tolerováno pouze v procedurách deklarovaných s parametrem NESTINGCHECK=OFF.

Identifikátor v poli operandů instrukcí konec-bloku a přerušení-bloku slouží obvykle pouze ke kontrole správného vnoření. Jsou-li však dva bloky téhož typu vnořeny do sebe, identifikátor přerušení-bloku může být použit k definování, který blok se má přerušit. Jako příklad viz test t2642, kde jeden Inner %FOR blok je vnořen do vnějšího Outer %FOR bloku, a operand instrukce %EXITFOR určuje, který blok se má přerušit (vnější či vnitřní).

↑ Přepínací instrukce

Přepínací instrukce mění interní stav €ASM pro všechny následné instrukce až do jeho změny následující přepínací instrukcí, anebo až do konce zdrojového kodu.

V €ASM jsou pouze dvě přepínací instrukce: EUROASM, a SEGMENT. Ten druhý má dvě podoby:
[jméno] SEGMENT – definice nového segmentu), a
[jméno] – definice nové sekce v aktuálním segmentu (pokud dosud nebyla definována) a přepnutí výstupu do této sekce.
Příklady přepínacích instrukcí:

 EUROASM  AUTOSEGMENT=OFF, CPU=486 ; Změň stav €ASM pro všechny následující instrukce.
[Subprocedures] SEGMENT PURPOSE=CODE, ALIGN=BYTE  ; Deklaruj nový segment.
[.data]                  ; Přesměruj výstup následujících instrukcí do dříve definovaného segmentu [.data].
[StringData]             ; Definuj novou sekci současného segmentu (v segmentu [.data]).

↑ Samostatné instrukce

Všechny ostatní instrukce nejsou logicky vázány s ostatními ve svislé struktuře programu, a jsou tedy samostatné.


↑ Elementy programu v €ASM

Velikost EuroAssemblerových elementů není v principu omezena. To se týká délky řetězců, fyzických řádků, identifikátrů, zápisu čísel, matematických výrazů, hloubky vnoření, počtu operandů apod. Interně jsou jejich velikosti udržovány jako 32bitové číslo, takže teoretický limit je 2 GB = 2_147_483_647 bajtů (znaků).

V praxi jsme ovšem oemzeni množstvím dostupné paměti a rozměry zásobníku, takže €ASM může zhavarovat s fatální chybou F9110 Cannot allocate virtual memory. nebo F9210 Memory reserved for machine stack is too small for this source file.

Adresa ↓

Adresní prostor ↓

Alignment ↓

Booleovské hodnoty ↓

Booleovská rozšíření ↓

Čísla ↓

Datové typy ↓

Délka ↓

Distance ↓

Grupy ↓

Identifikátory ↓

Jmenný prostor ↓

Komentáře ↓

Literály ↓

Matematické výrazy ↓

Operátory ↓

Paměťové proměnné ↓

Podmínkové kódy ↓

%Proměnné ↓

Registry ↓

Řetězce ↓

Scope ↓

Sekce ↓

Segmenty ↓

Segmentace ↓

Struktury ↓

Symboly ↓

Šířka ↓

Velikost ↓

Výčtové hodnoty ↓


↑ Komentáře

Blokové komentáře ↓

Řádkové poznámky ↓

Strojové poznámky ↓

Značkovací komentáře ↓

Komentáře neboli poznámky jsou části zdrojového kódu, které nejsou zpracovávány asemblerem; jejich účelem je vysvětlování kódu pro lidského čtenáře. V €ASM rozlišujeme čtyři typy komentářů:


↑ Řádkové poznámky

Řádková poznámka začíná neuvozeným středníkem ;; vše následující až do konce řádku asembler ignoruje. Řádkové poznámky jsou doslovně kopírovány do listingového souboru.

 Label: CALL SomeProc ; Toto je řádková poznámka.

↑ Strojové poznámky

Strojové poznámky jsou zapisovány EuroAssemblerem do listingového souboru a obsahují generovaný strojový kód v hexadecimální notaci.

Strojová poznámka začíná vertikální čarou |, která je prvním tisknutelným znakem na řádku a končí jeho druhým výskytem na tomtéř řádku, anebo koncem fyzického řádku (podle toho, co přijde dříve). Je-li ukončovací znak | vynechán, celý řádek je považován za komentář. To je využito ke vkládání chybových oznámení do listingu, hned pod chybnou instrukci.

|0030:E81234   |Label1: CALL SomeProc  ; Toto je řádková poznámka.
|0033:         |Label2: COLL OtherProc ; Zde došlo k překlepu.
|### E6860 Unrecognized operation "COLL", ignored.

Strojové poznámky jsou EuroAssemblerem ignorovány a nekopírují se do listingu. Namísto toho se generují znova, když byl listing předložen €ASM k nové kompilaci jako zdrojový kód.

U strojových poznámek se nepředpokládá, že by byly programátorem vkládány do programu.

↑ Značkovací komentáře

Začíná-li fyzický řádek znakem méně než <, je celý považován za značkovací komentář a ignorován. To umožňuje směšovat zdrojový kód s tagy hypertextového značkovacího jazyka. Značkovací komentáře se nekopírují do listingového souboru.

Díky implementaci značkovacích komentářů může být zdrojový kód v €ASM ukládán nejen jako prostý text, ale též ve formě HTML nebo XML hypertextu.

<h2>Popis MéProcedury</h2>
<img src="JejiVyobrazeni.png"/>
MéProcedury  PROC  ; Viz obrázek nahoře pro její popis.

Všechny zdrojové kódy dodávané s €ASM jsou kompletně uloženy ve formátu HTML, což umožnilo dokumentovat kód hypertextovými odkazy, tabulkami, obrázky a lepší vizuální reprezentací, než by poskytly prosté řádkové komentáře.

Chcete-li udržovat své kódy v HTML, ubezpečte se, že běžné povely pro assembler nezačínají znakem < a přeskupte zdrojový text tak, aby každý značkovací komentář začínal některým tagem HTML. Taky lze začínat komentářové řádky prázdným HTML tagem <span/> nebo <!---->.

↑ Blokové komentáře

Blokový komentář lze využít k dočasnému zneplatnění větší části zdrojového kódu nebo k začlenění dokumentace.

Blokový komentář začíná pseudoinstrukcí %COMMENT a končí odpovídající pseudoinstrukcí %ENDCOMMENT. Může zahrnovat mnoho programových řádků, které pak nemusejí začínat středníkem.
Blokové komentáře jsou kopírovány do listingového souboru.

€ASM sice nepřekládá text uvnitř takto vykomentovaného bloku, avšak musí jej i tak číst, aby našel odpovídající instrukci %ENDCOMMENT, takže odkomentovaný text musí být platný zdrojový kód.

Blokové komentáře se mohou vnořovat.

Text v bloku %COMMENT..%ENDCOMMENT musí být řádně vnořený, i když se ignoruje.

Pseudoinstrukci %COMMENT bychom mohli nahradit pomocí %IF 0, avšak je intuitivnější.
 CALL SomeProc  ; Toto je řádková poznámka.
 %COMMENT       ; Toto je blokový komentář.
 COLL OtherProc ; Tady došlo k překlepu.
    %COMMENT    ; Toto je vložený blokový komentář.
    %ENDCOMMENT ; Konec vloženého komentáře.
    ; Tato instrukce je rovněž ignorována.
 %ENDCOMMENT
    ; Emitování pokračuje zde.

↑ Identifikátor

Identifikátor je text, který dává jméno prvkům programu: symbolu, registru, instrukci, struktuře apod.

Identifikátor je kombinace písmen a číslic, který začíná písmenem.

Délka identifikátoru není omezena a všechny jeho znaky jsou platné.


↑ Čísla

Dekadická čísla ↓

Binární čísla ↓

Oktalová čísla ↓

Hexadecimální čísla ↓

Přehled celých čísel ↓

Čísla s plovoucí tečkou ↓

Speciální hodnoty FP čísel ↓

Znakové konstanty ↓

Číselná notace je způsob, kterým zapisujeme numerické hodnoty. Interně jsou celočíselné hodnoty uchovávány v €ASM jako 64bitová čísla se znaménkem.

Číslo je ve zdrojovém textu EuroAssembleru zapisováno jako kombinace číslic a číselných modifikátorů, které začíná dekadickou číslicí 0..9.

Číselný modifikátor je jeden ze znaků B D E G H K M P Q T přpojených za sekvenci číslic, nebo 0N 0O 0X 0Y (nula následovaná písmenem) na začátku číselného zápisu. Všechny modifikátory jsou nezávislé na velikosti písmen. Modifikátor musí být použit u všech notací s výjimkou dekadického formátu, který je výchozí.

Čísla s pohyblivou desetinnou tečkou (FP) mohou používat tečku . k oddělení celočíselné a desetinné části.

Dalším číselným modifikátorem je podtržítko _, které je asemblerem ignorováno a slouží jen jako oddělovač číslic pro lepší čitelnost delších čísel. V žádném zápisu čísel nejsou povoleny mezery.

↑ Dekadická čísla

Dekadické číslo je kombinací dekadických číslic 0..9 s volitelně připojovaným dekadickým modifikátorem D. Ještě existuje pět dalších dekadických přípon:
K (Kilo), říká EuroAssembleru, že má číslo vynásobit 210=1024,
M (Mega), říká EuroAssembleru, že má číslo vynásobit 220=1_048_576,
G (Giga), říká EuroAssembleru, že má číslo vynásobit 230=1_073_741_824,
T (Tera), říká EuroAssembleru, že má číslo vynásobit 240=1_099_511_627_776,
P (Peta), říká EuroAssembleru, že má číslo vynásobit 250=1_125_899_906_842_624.

Dekadické číslo může být také prefixováno modifikátorem 0N.

Všech šest čísel v následujícím příkladu má tutéž hodnotu: 1048576, 1048576d, 0n1048576, 1_048_576, 1024K, 1M.

Největší číslo, které se vejde do 32 bitů je 0xFFFF_FFFF=4_294_967_295.

Největší číslo, které se vejde do 63 bitů je 0x7FFF_FFFF_FFFF_FFFF=9_223_372_036_854_775_807.

↑ Binární čísla

Binární číslo je zapsáno jako sled číslic 0 a 1 s připojeným binárním modifikátorem B anebo s prefixem 0Y. Příklady: 0y101, 101b, 00110010b, 1_1111_0100B odpovídají dekadickým číslům 5, 5, 50, 500.

Největší 32bitové binární číslo je 1111_1111__1111_1111__1111_1111__1111_1111b.

↑ Oktalová čísla

Každá oktalová číslice 0..7 reprezentuje tři bity z odpovídající binární notace. Číslo je zakončeno oktalovou příponou Q anebo mu předchází předpona 0O nebo 0o (číslice nula následovaná velkým či malým písmenem O).

Příklad: 177_377q = 0o177_377 = 0xFEFF

Největší 32bitové oktalové číslo je 37_777_777_777q.

Největší 64bitové oktalové číslo je 1_777_777_777_777_777_777_777q.

↑ Hexadecimální čísla

Každá hexadecimální číslice kóduje čtyři bity do jednoho znaku. což vyžaduje 24=16 možných hodnot. Proto je deset dekadických čísli rozšířeno písmeny A, B, C, D, E, F s hodnotami 10, 11, 12, 13, 14, 15. U hexadecimálních cifer A..F nezáleží na velikosti písmen. Pokud by měla být první číslice hexadecimálního čísla reprezentována písmenem A..F, je třeba před číslo přidat nevýznamnou vedoucí nulu. Hexadecimální číslo je zakončeno příponou H, anebo začíná předponou 0X.

Příklad: 5h, 0x32, 1F4H, 0x1388, 0C350H reprezentuje postupně čísla 5, 50, 500, 5000, 50000.

Všechna čísla jsou v €ASM interně uchovávána jako 64bitové integery se znaménkem. Přestože instrukce MOV EAX,0xFFFF_FFFF a MOV EAX,-1 se překládají na identické kódy, interně jsou jejich operandy uchovávány jako 0x0000_0000_FFFF_FFFF a 0xFFFF_FFFF_FFFF_FFFF. Logický výraz 0xFFFF_FFFF = -1 je nepravda. |00000000:B8FFFFFFFF | MOV EAX, 0xFFFF_FFFF |00000005:B8FFFFFFFF | MOV EAX, -1 |FALSE | %IF 0xFFFF_FFFF = -1

↑ Přehled celých čísel

Celá čísla mohou být zapsána jako binární, oktalová, dekadická nebo hexadecimání. Některé číselné modifikátory se překrývají s hexadecimálními číslicemi B, D, E. €ASM se snaží rozebírat co nejdelší zápis, aby předešel nejednoznačnostem:
1BH je pochopeno jako hexadecimální číslo 0x1B=27 a nikoliv jako binární číslo 1 následovaná písmenem H.
2DH je pochopeno jako hexadecimální číslo 0x2D=45 a nikoliv jako dekadické číslo 2 následované písmenem H.
3E2H je pochopeno jako hexadecimální číslo 0x3E2=994 a nikoliv jako 3 * 102 následované písmenem H.

Zápis celých čísel
NotacePředponaBázePříponaNásobitel
Binární0Y2B1
Oktalová0O8Q1
Dekadická0N10D1
K210
M220
G230
T240
P250
Hexadecimální0X16H1

Binární, oktalová a hexadecimální čísla musejí být vždy uváděna s předponou nebo s příponou (nebo s oběma, i když to není obvyklé). V EuroAssembleru není direktiva RADIX.

Pro více příkladů syntaxe čísel viz testy €ASM numbers tests.

↑ Čísla s pohyblivou tečkou

Čísla s pohyblivou desetinnou tečkou, neboli reálná čísla se načítají ze zápisu s desetinnou tečkou a exponentu deseti v následující syntaxi:

Anatomie čísel s plovoucí tečkou
PořadíNázev poleObsah
1znaménko čísla+, - nebo žádné
2celočíselná částčíslice 0..9, separátor _
3desetinná tečka.
4neceločíselná částčíslice 0..9, separátor _
5číselný modifikátorE nebo e
6znaménko exponentu+, - nebo žádné
7exponentová částčíslice0..9, separátor_

Kupříkladu reálné číslo 1234.56E3 má hodnotu 1234.56 * 103=1234560.

Chybějící znaménko se považuje za +.

Neceločíselnou část lze vynechat, pokud je nula: 123.00E2 = 123.E2

Desetinnou tečku lze vynechat, pokud je neceločíselná část vynechána (je nulová). Modifikátor E stále určuje, že se jedná o formát plovoucí tečky. 123.00E2 = 123.E2 = 123E2 = 12300.

Exponentovou část lze vynechat, pokud je nulová. Modifikátor E se v tom případě může také vynechat. Bez modifikátoru je to existence desetinné tečky, která určuje, zda je číslo zapsáno jako celočíselné (integer) nebo s plovoucí tečkou (real). Příklad: 12345.67E0 = 12345.67E = 12345.67

V zápisu čísla s plovoucí tečkou nejsou dovoleny žádné mezery.

Číslo se považuje za plovoucí pokud jeho zápis obsahuje buď desetinnou tečku ., nebo modifikátor E (velké nebo malé písmeno) anebo obojí.

€ASM nepočítá s čísly ve formátu plovoucí tečky v asm-time.

Všechny interní kalkulace jsou v €ASM prováděny pouze s 64bitovými celými čísly. Pokud by bylo číslo s plovoucí tečkou (FP) použito v matematickém výrazu, bude nejprve převedeno na celočíselnou hodnotu. Pokud by se číslo nevešlo do 64 bitů, ohlásí se chyba E6130 (number overflow). Pokud došlo ke ztrátě přesnosti zanedbáním neceločíselné části čísla, ohlásí se varování W2210 (precision lost).

Formát FP čísla dle [IEEE754] se zachovává pouze pokud je vědecká notace použita ke statické deklaraci čísel v pseudoinstrukcích DD, DQ, DT.

FP čísla s poloviční přesností (float16) nejsou podporována EuroAssemblerem ani procesory, s výjimkou dvou SIMD instrukcí VCVTPS2PH a VCVTPH2PS, a s výjimkou několika konverzních operací kódovaných s prefixem MVEX.

Na rozdíl od celých čísel, znaménko v FP notaci je neoddělitelné od následnujícíh číslic. Pokud omylem vložíte mezeru mezi znaménko a číslo s plovoucí tečkou, namísto definice FP čísla to bude €ASM považovat za operaci (unární minus aplikované na číslo) a tudíž nejprve převede FP číslo na integer, než je vyhodnotí. |00000000:001DF1C7 | DD -123.45E3 ; Single-precision FP number -123.45*103. |00000004:C61DFEFF | DD - 123.45E3 ; Dword signed integer number -123450. |00000008:00000000A023FEC0 | DQ -123.45E3 ; Double-precision FP number -123.45*103. |00000010:C61DFEFFFFFFFFFF | DQ - 123.45E3 ; Qword signed integer number -123450. |00000018:0000000000001DF10FC0 | DT -123.45E3 ; Extended-precision FP number -123.45*103. |00000022: | DT - 123.45E3 ; Tbyte integer number není podporováno. |### E6725 Datatype TBYTE expects plain floating-point number.

↑ Speciální hodnoty FP čísel

Vedle standardních hodnot mohou čísla s plovoucí tečkou nabývat speciální FP konstanty:

Speciální FP konstanty (v hexadecimálním formátu)
KonstantaInterpretacesingle precision (DD)double precision (DQ)extended precision (DT)
#ZEROzero0000000000000000_00000000 0000_00000000_00000000
+#ZEROpositive zero0000000000000000_00000000 0000_00000000_00000000
-#ZEROnegative zero8000000080000000_00000000 8000_00000000_00000000
#INFinfinity7F8000007FF00000_00000000 7FFF_80000000_00000000
+#INFpositive infinity7F8000007FF00000_00000000 7FFF_80000000_00000000
-#INFnegative infinityFF800000FFF00000_00000000 FFFF_80000000_00000000
#PINFpseudo infinity7F8000007FF00000_00000000 7FFF_00000000_00000000
+#PINFpositive pseudo infinity7F8000007FF00000_00000000 7FFF_00000000_00000000
-#PINFnegative pseudo infinityFF800000FFF00000_00000000 FFFF_00000000_00000000
#NANnot a number7FC000007FF80000_00000000 7FFF_C0000000_00000000
+#NANpositive not a number7FC000007FF80000_00000000 7FFF_C0000000_00000000
-#NANnegative not a numberFFC00000FFF80000_00000000 FFFF_C0000000_00000000
#PNANpseudo not a number7F8000017FF00000_00000001 7FFF_00000000_00000001
+#PNANpositive pseudo not a number7F8000017FF00000_00000001 7FFF_00000000_00000001
-#PNANnegative pseudo not a numberFF800001FFF00000_00000001 FFFF_00000000_00000001
#QNANquiet not a number7FC000007FF80000_00000000 7FFF_C0000000_00000000
+#QNANpositive quiet not a number7FC000007FF80000_00000000 7FFF_C0000000_00000000
-#QNANnegative quiet not a numberFFC00000FFF80000_00000000 FFFF_C0000000_00000000
#SNANsignaling not a number7F8000017FF00000_00000001 7FFF_80000000_00000001
+#SNANpositive signaling not a number7F8000017FF00000_00000001 7FFF_80000000_00000001
-#SNANnegative signaling not a numberFF800001FFF00000_00000001 FFFF_80000000_00000001

U jmen speciálních FP konstant nezáleží na velikosti písmen. Pokud je užito znaménko + nebo -, je neoddělitelné. Příklady:
FourNans DY 4 * QWORD #NaN ; Definuj vektor čtyř hodnot not-a-number s dvojitou přesností.
MOV ESI,=8*Q#ZERO ; Definuj 8*8 nulových bajtů v literální sekci a nechej na ně ukazovat ESI

↑ Znakové konstanty

Číslo můžr být zapsáno také jako znaková konstanta, cože je řetězec nanejvýš osmi znaků. Jeho číselná hodnota se bere z pořadového čísla znaků v tabulce ASCII. Příklad znakových konstant a jejich hodnot:

'0'   =     30h =      48
'abc' = 636261h = 6513249
"4%%" =   2534h =    9524
Znaky s nejméně významnou hodnotou jsou v řetězci vlevo.

Asemblery nejsou jednotné v interpretaci znakových konstant. MASM a TASM používají zápisovou konvenci, kdy pořadí znaků ve zdrojovém kódu odpovídá tomu, jak píšeme dekadická čísla: nejméně významná číslice je zcela vpravo.

€ASM a s ním i většina novějších asemblerů používají paměťovou konvenci, kde pořadí znaků odpovídá uložení znaků v oprační paměti paměti procesorů s architekturou little endian:

| | ; MASM and TASM: |00000000:616263 | DB 'abc' ; Řetězec. |00000003:63626100 | DD 'abc' ; Znaková konstanta |00000007:B863626100 | MOV EAX,'abc' ; AL='c'. | | ; €ASM, FASM, GoASM, NASM, SpASM: |00000000:616263 | DB 'abc' ; Řetězec. |00000003:61626300 | DD 'abc' ; Znaková konstanta. |00000007:B861626300 | MOV EAX,'abc' ; AL='a'.

↑ Výčtové hodnoty

Některé parametry mohou nabývat pouze předdefinované hodnoty, například volba EUROASM CPU= může být 086, 186, 286, 386, 486, 586, 686, PENTIUM, P6, X64.

Třebaže některé výčtové hodnoty mohou vypadat jako čísla, nejsou počitatelné.

↑ Booleovské hodnoty

Kterékoli číslo může být interpretováno jako booleovská (logická) hodnota. Booleovská hodnota může mít jeden ze dvou stavů: pravda nebo nepravda. Číslo 0 je považováno za booleovskou hodnotu nepravda, zatímco jakékoli nenulové číslo je vyhodnoceno jako pravda.

↑ Booleovská rozšíření

Všechny vestavěné booleovské volby v €ASM mají rozšířený repertoár možných hodnot. Tyto volby akceptují

To se týká

Tento rozšířený repertoár platí pouze pro operandy vestavěné do €ASM. Nejedná se o kdekoli použitelné symboly, jako MOV EAX,TRUE. K získání podobné funkčnosti v makrech by programátor nejprve musel takové symboly nadefinovat, např.

FALSE   EQU 0
false   EQU 0
TRUE    EQU -1
true    EQU !false
MOV EAX,TRUE

Je-li booleovské rozšíření použito jako klíčový operand makra, může být rovněž testován v těle makra pomocí %IF, %WHILE, %UNTIL, například

MacroWithBool  %MACRO Bool=On
  %IF %Bool
    ; Instrukce pokud Bool je pravda.
  %ELSE
    ; Instrukce pokud Bool je nepravda.
  %ENDIF
 %ENDMACRO MacroWithBool

Nyní můžeme makro vyvolat pomocí MacroWithBool Bool=Enable, MacroWithBool Bool=No apod.

Booleovská rozšíření nejsou povoleny v logických výrazech
MacroWithBool  %MACRO Bool=0
  %IF ! %Bool  ; Toto je logický výraz.
    ; Instrukce pokud Bool je nepravda.
  %ENDIF
  %ENDMACRO MacroWithBool

Předchozí příklad nebude fungovat s booleovským rozšířením, např. MacroWithBool Bool=False si bude stěžovat, že E6601 Symbol "False" was not found.. Avšak po převrácení logiky by měl fungovat dobře:

MacroWithBool  %MACRO Bool=0
  %IF  %Bool
  %ELSE
    ; Instrukce pokud Bool je nepravda.
  %ENDIF
  %ENDMACRO MacroWithBool

↑ Řetězce

Řetězec je sled libovolných znaků obklopený uvozovkami. Lze používat jak uvozovky dvojité ", tak i jednoduché ' (rovněž nazývané apostrofy). Obklopující uvozovky se nezapočítávají do obsahu řetězce. Všechny znaky uvnitř řetězce ztrácejí svůj sémantický význam, jsou jen tři výjimky:

  1. EOL nelze použít v řetězci. Jinými slovy každá část řetězce se musí vejít na fyzický řádek. Definici delších řetězců ovšem můžeme rozdělit, například |0000:5468697320697320 |MultilineString: DB "This is the first line",13,10, \ |0008:7468652066697273~| "and this is the second one.",13,10,0 |0036: |
  2. Znak použitý k ohraničení řetězce nelze použít uvnitř něho, ledaž by byl zdvojen, např. |0000:4F27427269656E00 |Surname: DB 'O''Brien',0 |0008: |
  3. Znak procenta % si zachovává svou funkci předpony preprocesorové %proměnné. Použijte dvě sousedící procenta tam, kde je v řetězci požadováno jednoduché %, např. |0000:313030252073617665642E00 |Status: DB "100%% saved.",0 |000C: |
Preprocesingové %proměnné jsou expandovány i v řetězcích.

€ASM nepoužívá únikový znak (escape), procento a uvozovky escapují samy sebe. Chcete-li takový znak použít v řetězci, musí být zdvojen. Tato duplikace se týká pouze zápisu řetězce ve zdrojovém textu a neprodlužuje obsah řetězce v paměti počítače.

Řetězce uzavřené v 'apostrofech' a ve "dvojitých uvozovkách" jsou ekvivalentní s jedinou výjimkou: má-li být obsahem řetězce název souboru,lze použít pouze dvojité uvozovky. neboť apostrof je platným znakem použitelným v názvech souborů na většině souborových systémů.
Další příklady řetězců:

|0000:3830202520 |DB "80 %% " |0005:766F74656420224E6F22 |DB "voted ""No""" |000F: |DB '' ; Prázdný řetězec. |000F:27 |DB "'" ; Jednoduchý apostrof. |0010:27 |DB '''' ; Jednoduchý apostrof. |0011: |; Příklady neplatné syntaxe (lichý počet uvozovek): |0011: |DB """ |### E6721 Invalid data expression """"". |0011: |DB "It ain't necessarilly so' |### E6721 Invalid data expression ""It ain't necessarilly so'". |0011: |

↑ Adresní prostor

Processor, neboli Central Processing Unit (CPU), operuje s daty a komunikuje s okolím (registry, paměť, zařízení). Typická operace načte informaci z registru, paměti nebo portu (I/O zařízení), učiní s ní nějakou transformaci a zapíše ji zpět do okolí. Nejmenší adresovatelnou jednotkou paměti je jeden bajt (1 B) a jejich počet je omezen adresním prostorem.

Registr je identifikován svým názvem, zařízení je identifikováno číslem portu, bajt paměti je identifikován jeho adresou.

Adresní prostor
CPU módGPR I/O port Adresní prostor
16bit 8* 2 B64 KB (216)1 MB (216+4)
32bit 8* 4 B64 KB (216)4 GB (232)
64bit16* 8 B64 KB (216)16384 PB (264)

↑ Adresy

Adresní prostor je limitován architekturou a počtem vodičů mezi procesorem a paměťovými čipy. Kombinace logických jedniček a nul, která by se dala naměřit na těchto drátech, se nazývá fyzická adresa (PhA).

Z pohledu aplikačního programátora procesor zapisuje a čte z virtuální adresy (VA). Neuvažujeme-li segmentaci paměti, můžeme virtuální adrese říkat lineární adresa (LA). Virtuální a fyzická adresa byly totožné pouze u první generaci procesorů bez vyrovnávací paměti a stránkování.

Objekty sestaveného obrazu programů v chráněném módu jsou adresovány pomocí ofsetu od začátku obrazu v paměti (od ImageBase). Tento ofset se nazývá relativní virtuální adresa (RVA).

Pozice objektů v souboru bývá identifikována pomocí adresy v souboru (FA), definované vzdáleností objektu od začátku souboru.

Adresa je symbolická repreentace určité pozice v paměti.

PhA, VA, LA, RVA, FA jsou celočíselná nezáporná prostá čísla, avšak adresování v asm-time je komplikovanější. Z historických důvodů je adresní prostor rozdělen na segmenty paměti a každý segment je identifikován obsahem segmentového registru. Adresa v době kompilace je vyjádřena jako počet bajtů (ofset) mezi pozicí a počátkem segmentu, a samotnou identifikací segmentu. Viz také kapitoly Adresní symboly a Adresní výrazy.

↑ Alignment

Procesor přistupuje k datům v paměti rychleji, pokud je jejich adresa zarovnána (aligned), tedy zaokrouhlena na násobek mocniny dvou. Většina strojových instrukcí IA-32 si sice poradí s nezarovnanými daty, avšak trvá to déle, pokud data nejsou ve stejné stránce vyrovnávací paměti.

Paměťové proměnné by měly být zarovnány na jejich přirozený alignment odpovídající jejich velikosti, viz sloupec Autoalign v tabulce datatypů. Dvojslova DWORD mají hodnotu autoalignmentu rovnou 4, což znamená, že poslední dva bity by při správném zarovnání měly být nulové. QWORD jsou zarovnány k 8, takže nulové jsou poslední tři bity (8=23).

Zarovnání lze dosáhnout buď explicitně pomocí pseudoinstrukce ALIGN, anebo klíčem ALIGN= ve strojové instrukci nebo v definici procedury PROC nebo PROC1.

Paměťové proměnné budou automaticky zarovnány, pokud volba EUROASM AUTOALIGN=ON. Například instrukce Dvojslovo: DD 1234 bude automaticky zarovnána na 4 (ofset Dvojslovo bude dělitelný čtyřmi beze zbytku). Výplňový znak, vkládaný podle potřeby před zarovnávanou proměnnou, je nula 0x00 v datovém segmentu nebo NOP 0x90, případně vícebajtový NOP v kódovém segmentu.

Hodnota parametru ALIGN= může být numerický výraze vyhodnocený na 1, 2, 4, 8 nebo vyšší mocniny dvou. €ASM rovněž akceptuje nulu nebo prázdnou hodnotu, což pak je identické s ALIGN=1 (bez efektu). Vedle těchto číselných hodnot ALIGN= rovněž akceptuje výčtové hodnoty BYTE, WORD, DWORD, QWORD, OWORD, YWORD, ZWORD nebo jejich krátké varianty B, W, D, Q, O, Y, Z.

Zarovnání je omezeno alignmentem segmentu, v němž příkaz leží. Pokud je altuální segment zarovnán na DWORD, nelze žádat o zarovnání na QWORD nebo OWORD. Výchozí zarovnání segmentů je OWORD (10h) a zvyšuje se na SectionAlign (obvykle na 1000h), pokud je program ve formátu ELFX nebo PE/DLL.

Kromě instrukčního modifikátoru ALIGN= může být zarovnání vyžádáno také samostatnou pseudoinstrukcí ALIGN, která dovoluje i záměrné zrušení zarovnání.

↑ Registry

Registr je malá rychlá proměnná s pevnou velikostí umístěná přímo na čipu CPU.

Třebaže si registr pamatuje zapsanou informaci, není součástí adresovatelné paměti. Registr může být osloven pouze svým jménem, nemá adresu.

Přehled registrů
RodinaREGTYPE#ČlenovéVelikost
GPR 8bit'B'AL, AH, BL, BH, CL, CH, DL, DH,
DIB, SIB, BPB, SPB, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B
DIL, SIL, BPL, SPL, R8L, R9L, R10L, R11L, R12L, R13L, R14L, R15L
1
GPR 16bit'W'AX, BX, CX, DX, BP, SP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W2
GPR 32bit'D'EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D4
GPR 64bit'Q'RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R158
Segment'S'CS, SS, DS, ES, FS, GS2
FPU'F'ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST710
MMX'M'MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM78
XMM'X'XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM16, XMM17, XMM18, XMM19, XMM20, XMM21, XMM22, XMM23, XMM24, XMM25, XMM26, XMM27, XMM28, XMM29, XMM30, XMM3116
AVX'Y'YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15, YMM16, YMM17, YMM18, YMM19, YMM20, YMM21, YMM22, YMM23, YMM24, YMM25, YMM26, YMM27, YMM28, YMM29, YMM30, YMM3132
AVX-512'Z'ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7, ZMM8, ZMM9, ZMM10, ZMM11, ZMM12, ZMM13, ZMM14, ZMM15, ZMM16, ZMM17, ZMM18, ZMM19, ZMM20, ZMM21, ZMM22, ZMM23, ZMM24, ZMM25, ZMM26, ZMM27, ZMM28, ZMM29, ZMM30, ZMM3164
Mask'K'K0. K1, K2. K3, K4, K5, K6, K78
Bound'N'BND0, BND1, BND2, BND316
Control'C'CR0, CR2, CR3, CR4, CR84
Debug'E'DR0, DR1, DR2, DR3, DR6, DR74
Test'T'TR3, TR4, TR54

U jmen registrů nezáleží na velikosti písmen. Některé General Purpose Registers (GPR) mají aliasy, například AL je jiný název pro nižší polovinu AX, což je jiný název pro nižší polovinu EAX, což je jiný název pro nižší polovinu RAX.

Podobné aliasy mají SIMD (AVX) registry: XMM0 je jiný název pro nižší polovinu YMM0, což je jiný název pro nižší polovinu ZMM0.

Názvy 8bitových registrů DIB, SIB, BPB, SPB, R8B..R15B jsou aliasy pro nejméně významný bajt registrů RDI, RSI, RBP, RSP, R8..R15. Mohou být nazývány také jako DIL, SIL, BPL, SPL, R8L..R15L v souladu s dokumentací v manuálech Intelu. €ASM podporuje obě přípoy ~L i ~B. Tyto registry jsou dostupné pouze v 64bitovém módu.

Některé asemblery a manuály používají zápis ST(0), ST(1)..ST(7) pro registry jednotky pohyblivé desetinné tečky, tato syntaxe však není EuroAssemblerem akceptována. Podobně nefunguje ani záměna registru ST0 za ST (vrchol stacku FPU).

Procesor x86 obsahuje ještě některé další registry, které obsahují flagy, tabulky deskriptorů, řídicí a stavové registry FPU, avšak ty zde nejsou uvedeny, neboť nejsou přímo dostupné pomocí svého názvu.

↑ Podmínkové kódy

Všeobecné podmínkové kódy ↓

Podmínkové kódy instrukcí SSE ↓

Výsledek některých operací procesoru lze považovat za predikát, kterému lze přidělit mnemotechnické jméno a použít jako součást názvu strojových instrukcí.

↑ Všeobecné podmínkové kody

Některým kombinacím aritmetických flagů CPU ZF, CF, OF, SF, PF lze přiřadit speciální jména, tzv. podmínkové kódy. Jsou použity v mnemonice podmíněného větvení Jcc nebo v instrukcích podmíněných přesunů CMOVcc.

Invertovaný kód může být použit v makroinstrukcích k přeskočení kódu, pokud podmínka není splněna. Viz sloupec invertovaná mnemonika.

Tabulka všeobecných podmínkových kódů
Num.
hodnota
MnemonikaAliasPopisPodmínkaInvertovaná
mnemonika
0x4E Z Equal ZF=1 NE
0x5NE NZ Not Equal ZF=0 E
0x4Z E Zero ZF=1 NZ
0x5NZ NE Not Zero ZF=0 Z
0x2C B Carry CF=1 NC
0x3NC NB Not Carry CF=0 C
0x2B C Borrow CF=1 NB
0x3NB NC Not Borrow CF=0 B
0x0O Overflow OF=1 NO
0x1NO Not Overflow OF=0 O
0x8S Sign SF=1 NS
0x9NS Not Sign SF=0 S
0xAP PE Parity PF=1 NP
0xBNP PO Not Parity PF=0 P
0xAPE P Parity Even PF=1 PO
0xBPO NP Parity Odd PF=0 PE
0x7A NBEAbove CF=0 && ZF=0 NA
0x6NA BE Not Above CF=1 || ZF=1 A
0x3AE NB Above or Equal CF=0 NAE
0x2NAE B Not Above nor Equal CF=1 AE
0x2B NAEBelow CF=1 NB
0x3NB AE Not Below CF=0 B
0x6BE NA Below or Equal CF=1 || ZF=1 NBE
0x7NBE A Not Below nor Equal CF=0 && ZF=0 BE
0xFG NLEGreater SF=OF && ZF=0 NG
0xENG LE Not Greater SF<>OF || ZF=1G
0xDGE NL Greater or Equal SF=OF NGE
0xCNGE L Not Greater nor EqualSF<>OF GE
0xCL NGELess SF<>OF NL
0xDNL GE Not Less SF=OF L
0xELE NG Less or Equal SF<>OF || ZF=1NLE
0xFNLE G Not Less nor Equal SF=OF && ZF=0 LE
CXZ CX register je Zero CX=0
ECXZ ECX register je Zero ECX=0
RCXZ RCX register je Zero RCX=0

↑ Podmínkové kódy SSE

Instrukce rozšíření Single Instruction Multiple Data (V)CMPccSS,(V)CMPccSD,(V)CMPccPS,(V)CMPccPD používají jiné než všeobecné podmínkové kódy cc.

Pro původní instrukce CMPccSS,CMPccSD,CMPccPS,CMPccPD jsou dokumentovány pouze ty uvedené ve sloupci Alias.
Podmínkové kódy SSE
Num.
hodnota
MnemonikaAliasPopis
0x00EQ_OQEQEqual, Ordered, Quiet
0x01LT_OSLTLess Than, Ordered, Signaling
0x02LE_OSLELess than or Equal, Ordered, Signaling
0x03UNORD_QUNORDUnordered, Quiet
0x04NEQ_UQNEQNot Equal, Unordered, Quiet
0x05NLT_USNLTNot Less Than, Unordered, Signaling
0x06NLE_USNLENot Less than or Equal,Unordered, Signaling
0x07ORD_QORDOrdered, Quiet
0x08EQ_UQ Equal, Unordered, Quiet
0x09NGE_USNGENot Greater than or Equal, Unordered, Signaling
0x0ANGT_USNGTNot Greater Than, Unordered, Signaling
0x0BFALSE_OQFALSEFalse, Ordered, Quiet
0x0CNEQ_OQ Not Equal, Ordered, Quiet
0x0DGE_OSGEGreater than or Equal, Ordered, Signaling
0x0EGT_OSGTGreater Than, Ordered, Signaling
0x0FTRUE_UQTRUETrue, Unordered, Quiet
0x10EQ_OSEqual, Ordered, Signaling
0x11LT_OQLess Than, Ordered, Quiet
0x12LE_OQLess than or Equal, Ordered, Quiet
0x13UNORD_SUnordered, Signaling
0x14NEQ_USNot Equal, Unordered, Signaling
0x15NLT_UQNot Less Than, Unordered, Quiet
0x16NLE_UQNot Less than or Equal, Unordered, Quiet
0x17ORD_SOrdered, Signaling
0x18EQ_USEqual, Unordered, Signaling
0x19NGE_UQNot Greater than or Equal, Unordered, Quiet
0x1ANGT_UQNot Greater Than, Unordered, Quiet
0x1BFALSE_OSFalse, Ordered, Signaling
0x1CNEQ_OSNot Equal, Ordered, Signaling
0x1DGE_OQGreater than or Equal, Ordered, Quiet
0x1EGT_OQGreater Than, Ordered, Quiet
0x1FTRUE_USTrue, Unordered, Signaling

↑ Operátory

Operátor je příkaz k počítání v době překladu (asm-time).

K předepsání matematických operací jsou v €ASM použity kombinace speciálních znaků. Umístění binárního operátoru mezi dvě čísla instruuje €ASMm aby nahradil tyto tři prvky výsledkem operace. Některé operátory jsou unární, modifikují hodnotu operandu, před kterým stojí.

Matematické operqace implementované v €ASM jsou uvedeny v následující tabulce.

Tabulka operací
Operation PrioritaVlastnosti Levý
operand
Operátor Pravý
operand
VýsledekII (6)
Membership 16binární nekomut. (1)identifier. identifieridentifikátor
Attribute 15unární noncomm. (3) attr# element číslo nebo adresa
Case-insens. Equal 14binární komutativní (2)string== string logický CMPS
Case-sens. Equal 14binární komutativní string === string logický CMPS
Case-insens. Nonequal 14binární komutativní (2)string!== string logický CMPS
Case-sens. Nonequal 14binární komutativní string !=== string logický CMPS
Plus 13unární (3) + number číselný NOP
Minus 13unární (3) - number číselný NEG
Shift Logical Left 12binární nekomutativní number << number číselný SHL
Shift Arithmetic Left 12binární nekomutativní number #<< number číselný SAL
Shift Logical Right 12binární nekomutativní number >> number číselný SHR
Shift Arithmetic Right12binární nekomutativní number #>> number číselný SAR
Signed Division 11binární nekomutativní number #/ number číselný IDIV
Division 11binární nekomutativní number / number číselný DIV
Signed Modulo 11binární nekomutativní number #\ number číselný IDIV
Modulo 11binární nekomutativní number \ number číselný DIV
Signed Multiplication 11binární komutativní number #* number číselný IMUL
Multiplication 11binární komutativní number * number číselný MUL
Scaling 10binární komutativní (5)number* register adresní výraz
Addition 9binární komutativní number + number číselný ADD
Subtraction 9binární nekomutativní number - number číselný SUB
Indexing 9binární komutativní (5)number+ register adresní výraz
Bitwise NOT 8unární (3) ~ number číselný NOT
Bitwise AND 7binární komutativní number & number číselný AND
Bitwise OR 6binární komutativní number | number číselný OR
Bitwise XOR 6binární komutativní number ^ number číselný XOR
Above 5binární nekomutativní number > number logický JA
Greater 5binární nekomutativní number #> number logický JG
Below 5binární nekomutativní number < number logický JB
Lower 5binární nekomutativní number #< number logický JL
Above or Equal 5binární nekomutativní number >= number logický JAE
Greater or Equal 5binární nekomutativní number #>= number logický JGE
Below or Equal 5binární nekomutativní number <= number logický JBE
Lower or Equal 5binární nekomutativní number #<= number logický JLE
číselný Equal 5binární komutativní number = number logický JE
číselný Nonequal 5binární komutativní (4)number!= or <>number logický JNE
Logical NOT 4unární (3) ! number logický NOT
Logical AND 3binární komutativní number && number logický AND
Logical OR 2binární komutativní number || number logický OR
Logical XOR 2binární komutativní number ^^ number logický XOR
Segment separation 1binární nekomutativní number : number adresní výraz
Data duplication 0binární nekomut. (1) (5)number* datatype datový výraz
Range 0binární nekomut. (1)number .. number range
Substring 0binární nekomut. (1)text [ ] range text
Sublist 0binární nekomut. (1)text { } range text

(1) Speciální operace Membership, Duplication, Range, Substring, Sublist se řeší už na úrovni rozkladu textu místo výpočtu pomocí evaluátoru výrazů, jsou zde uvedeny pouze kvůli kompletnosti.

(2) Porovnávání řetězcu nezávislé na velikosti ignoruje velikost písmen A..Z avšak nikoli velikost písmen s diakritikou větších než ASCII 127.

(3) Unární operátor je aplikován na následující operand. Binární operátor pracuje se dvěma operandy. Operátor atributu je aplikován na následující element nebo výraz v závorkách.

(4) Numerická operace Nonequal má dva shodné operátory != a <>. Můžete si vybrat.

(5) Operace Multiplication, Scaling a Duplication sdílejí tentýž operátor *. Podobně Addition a Indexing sdílejí operátor +. Druh operace je určen typy operandů.

(6) Sloupec II ilustruje, která strojová instrukce je interně použita k vyhodnocení během překladu.

Komutativnost určuje, zda oba operátory binární operace mohou být zaměněny bez vlivu na výsledek.

Slouoec Priorita určuje pořadí zpracování operátorů. Výrazy s operátory s vyšší prioritou se zpracovávají dříve, avšak lze to změnit použitím prioritních závorek ( ). Operace se shodnou prioritou se zpracovávají v pořadí zápisu (zleva doprava).

Operace kalkulující s čísly se znaménky mají operátor prefixován znakem #. Operace Addition a Subtraction nepotřebují speciální znaménkovou verzi, neboť počítají se signed i unsigned čísly stejně.

Číselné i logické operace vracejí 64bitové číslo. V případě booleovských operací má výsledek jednu ze dvou možných hodnot: 0 (nepravda) nebo -1 = 0xFFFF_FFFF_FFFF_FFFF (pravda). Kupříkladu výraz
'+' & %1 #>= 0 | '-' & %1 #< 0 je vyhodnocen jako
('+' & (%1 #>= 0)) | ('-' & (%1 #< 0)) a výsledkem je znaménko mínus (45) pokud je %1 negativní, nebo znaménko plus (43) v ostatních případech.

Mezery oddělující operandy a operátory slouží jen pro lepší čitelnost a nejsou vyžadovány syntaktickými pravidly.

Skupina operátorů Shift dostala vyšší prioritu než v jiných jazycích, neboť považuji posuvy za speciální druh násobení a dělení.
Výraz 4+3<<2 vyhodnocuje NASM jako (4+3)<<2 = 28, zatímco v €ASM je vyhodnocen jako 4+(3<<2) = 16).


↑ Výrazy

Číselné a logické výrazy ↓

Adresové výrazy ↓

Registrové výrazy ↓

Datové výrazy ↓

Speciální výrazy ↓

Výraz (expression) je kombinace operandů, operátorů a prioritních závorek () zachovávající pravidla z níže uvedené tabulky.

Syntaxe výrazu
Co může následovatlevá závorkaunární operátor operandbinární operátorpravá závorkakonec výrazu
začátek výrazuanoanoanoneneano (2)
levou závorkuanoanoanoneano (2)ne
unární operátoranoneanonenene
operandneneneanoanoano
binární operátoranoano (1)anonenene
pravou závorkuneneneanoanoano

(1) Unární operátor za binárním je povolen, např. 5*-3 se vyhodnotí jako 5*(-3).

(2) Prázdné výrazy, prázdný obsah závorek a nadbytečné závorky se tolerují.

Tabulka vypisuje, které kombinace jsou přípustné. Měla by se číst po řádkách, např. první řádek sděluje, že výraz může začínat levou závorkou, unárním operátorem nebo operandem.

Výraz je rozdělen na elementární unární a binární operace, které jsou vyhodnocovány podle priority. Operace se shodnou prioritou jsou počítány zleva doprava. Prioritu lze zvětšit pomocí závorek ( ).

↑ Číselné a logické výrazy

Porovnání řetězců ↓
Číselné porovnání ↓
Číselná aritmetika ↓
Posuvy ↓
Bitová aritmetika ↓
Booleovská algebra ↓
Číselné operace interně kalkulují s 64bitovými integery, bez ohledu zda má cílový program běžet ve 64bitovém módu nebo ne.

Výsledek číselného nebo logického výrazu je 64bitová numerická hodnota (signed integer). Lze ji považovat za číslo nebo za logickou hodnotu. Nulový výsledek se považuje za logickou hodnotu nepravda a nenulový výsledek za hodnotu pravda. Čistě logické výrazy, jako logické NOT, AND, OR, XOR a všechny porovnávací operace vracejí 0 anebo 0xFFFF_FFFF_FFFF_FFFF = -1. To umožňuje použít výsledek logických operací s následnými bitovými operacemi se všemi bity.

↑ Porovnání řetězců

Porovnávací operace vracejí logickou hodnotu. Operace necitlivé na velikost písmen nejprve převádějí oba řetězce na stejnou velikost písmen před samotným srovnáním, to se ale týká pouze ASCII písmen A..Z, nikoli národních znaků s diakritikou.

Řetězcová porovnávání mají tu nejvyšší prioritu, neboť v asm-time nelze provádět žádnou jinou operaci kromě testu na rovnost. €ASM nemůže říci, který řetězec je "větší". |00000000:FFFFFFFFFFFFFFFF | DQ "EAX" == "eax" ; Pravda, řetězce jsou si rovny (až na velikost písmen). |00000008:0000000000000000 | DQ "EAX" === "eax" ; Nepravda, řetězce se liší velikostí písmen. |00000010:FFFFFFFFFFFFFFFF | DQ "I'm OK." === 'I''m OK.' ; Pravda, jejich netto hodnoty se shodují. |00000018:0000000000000000 | DQ "Müller" == "MÜLLER" ; Nepravda kvůli odlišné velikosti přehlasovaného U. |00000020:0000000000000000 | DQ "012" == "12" ; Nepravda, řetězce se neshodují. |00000028:0000000000000000 | DQ "123" = 123 ; Nepravda, znaková konstanta "123"=3355185 se liší od čísla 123. |00000030: | DQ "123" == 123 ; Syntaktická chyba; pravý operand není řetězcem. |### E6321 String compare InsensEqual with non-string operand in expression ""123" == 123". |00000030:

Porovnávání nezávislé na velikosti písmen by se mělo používat na vestavěné elementy €ASM, jako jsou názvy registrů nebo datatypů, např.

 %IF '%1' !== 'ECX'
   %ERROR Only register ECX is expected as the first macro operand.
 %ENDIF

V ostatních případech je vhodnější použít srovnání citlivé na velikost písmen, neboť €ASM pak nemusí nejprve převádět řetězce na shodnou velikost:

DoSomethingWithMemoryVar %MACRO
 %IF '%1[1]' !=== '['  ; Zjisti, zda první operand makra začíná lomenou závorkou.
   %ERROR The first operand should be a memory variable in [brackets].
 %ENDIF
%ENDMACRO DoSomethingWithMemoryVar

Test složené závorky z předchozího příkladu selhává, pokud je prvním operandem makra řetězec nebo znaková konstanta v uvozovkách, např. DoSomethingWithMemoryVar 'xyz'. Operace porovnání řetězců vyvolá E6101 Expression "''' !=== '" is followed by unexpected character "[". kvůli chybě syntaxe. Jeden trik, jak se vyhnout chybě E6101, je porovnávat zdvojené hodnoty. V tom případě se jednoduché i dvojité uvozovky navzájem escapují:

DoSomethingWithMemoryVar %MACRO
 %IF '%1[1]%1[1]' !=== '[['  ; Zjisti, zda první operand makra začíná lomenou závorkou.
   %ERROR The first operand should be a memory variable in [brackets].
 %ENDIF
↑ Číselné porovnání

Číselné porovnání používá jeden znak rovnítka =, případně ještě doplněný znaky < nebo > a může srovnávat hodnoty dvou prostých čísel nebo dvou adres v rámci téhož segmentu.

Číselné porovnání určí, která strana operace je větší. Termín above/below se používá při srovnávání adres nebo čísel bez znamének. Termín greater/lower se použije při srovnávání znaménkových čísel. Operátory považující čísla za znaménková mají předřazen znak #. Virtuální adresy jsou vždy bez znaménka, takže se nemůžeme zeptat, zda jsou "greater" nebo "lower".

|00000000:FFFFFFFFFFFFFFFF | DQ 5 < 7 ; Pravda, 5 je pod 7. |00000008:FFFFFFFFFFFFFFFF | DQ 5 #< 7 ; Pravda, 5 je menší než 7. |00000010:0000000000000000 | DQ 5 #< -7 ; Nepravda, 5 není menší než -7. |00000018:FFFFFFFFFFFFFFFF | DQ 5 < -7 ; Pravda, 5=0x0000_0000_0000_0005 je pod -7=0xFFFF_FFFF_FFFF_FFF9. |00000020:FFFFFFFFFFFFFFFF | DQ 123 = 0123 ; Pravda, obě čísla jsou shodná. |00000028:0000000000000000 | DQ "123" == "0123" ; Nepravda, oba řetězce se liší. |00000030:0000000000000000 | DQ "123" = "0123" ; Nepravda, obě strany se považují za znakové konstanty s různými hodnotami. |00000038: | DQ "123" = "000000123" ; "000000123" není číslo, je příliš velké na znakovou konstantu. |### E6131 Character constant "123" = "000000123" is too big for 64 bits. |00000038: |
↑ Číselná aritmetika

Podporované aritmetické operace jsou Addition, Subtraction, Multiplication, Division a Modulo (zbytek po dělení).

Unární mínus lze aplikovat pouze na skalární operandy. Unární plus nemění hodnotu operandu; v seznamu operátorů je zařazen kvůli kompletnosti. Sousedící binární a unární numerický operátor je v €ASM akceptován, i když to vypadá divně. Je to užitečné při operacích s nahrazenou hodnotou, jako 5 + %1, kde symbolický argument %1 je náhodou negativní, třeba -2. Výraz je vyhodnocován jako 5 + %1 -> 5 + -2 -> 5 + (-2) -> 3.

Nejvyšší přípustná hodnota celého čísla ve zdrojovém kódu €ASM je 0xFFFF_FFFF_FFFF_FFFF -> 18_446_744_073_709_551_615 jako bezznaménková, anebo 0x7FFF_FFFF_FFFF_FFFF -> 9_223_372_036_854_775_808 jako znaménková. Přetečení během překladu je ignorováno u operací Addition, Subtraction a Shift Logical. Chyba se ohlásí, pokud dojde k přetečení během Multiplication a Shift Arithmetic Left, nebo pokud dojde k dělení nulou (division-by-zero) během Division nebo Modulo. Toto maximum nelze překročit ani u mezivýsledků, jako 0x7FFF_FFFF_FFFF_FFFF * 2 / 2 (€ASM hlásí chybu). Nicméně přeskupený kód 0x7FFF_FFFF_FFFF_FFFFF * (2 / 2) se přeloží dobře.

Přetečení není hlášeno během následujících číselných operací:

|00000000:0E00000000000000 | DQ 2 + 3 * 4 ; Výsledek je 14. |00000008:0200000000000000 | DQ 0xFFFF_FFFF_FFFF_FFF9 + 0x0000_0000_0000_0009 ; Výsledek je 2. |00000010:0200000000000000 | DQ -7 + 9 ; Výsledek je 2 (0xFFFF_FFFF_FFFF_FFF9 + 0x0000_0000_0000_0009). |00000018:0200010000000000 | DQ 0xFFF9 + 0x0009 ; Výsledek je 65538 (0x0000_0000_0000_FFF9 + 0x0000_0000_0000_0009). |00000020: |

€ASM kalkuluje s celočíselným ořezaným dělením a s [Modulo] operací během překladu stejně jako strojová instrukce IDIV.

Než se uplatní znaménkové dělení, dělenec i dělitel jsou nejprve interně převedeny na pozitivní čísla. Teprve pak, po vydělení kladných čísel, je výsledek převeden na negativní, pokud jeden z operandů (ale ne oba) byly negativní.
Zbytek po dělení se znaménky je převeden na negativní pouze pokud divident byl negativní.

|00000000: |; Znaménkové dělení: |00000000:0300000000000000 | DQ +14 #/ +4 ; +(0x0000_0000_0000_000E / 0x0000_0000_0000_0004) is +3. |00000008:FDFFFFFFFFFFFFFF | DQ -14 #/ +4 ; -(0x0000_0000_0000_000E / 0x0000_0000_0000_0004) is -3. |00000010:FDFFFFFFFFFFFFFF | DQ +14 #/ -4 ; -(0x0000_0000_0000_000E / 0x0000_0000_0000_0004) is -3. |00000018:0300000000000000 | DQ -14 #/ -4 ; +(0x0000_0000_0000_000E / 0x0000_0000_0000_0004) is +3. |00000020: |; Bezznaménkové dělení: |00000020:0300000000000000 | DQ +14 / +4 ; (0x0000_0000_0000_000E / 0x0000_0000_0000_0004) is 3. |00000028:FCFFFFFFFFFFFF3F | DQ -14 / +4 ; (0xFFFF_FFFF_FFFF_FFF2 / 0x0000_0000_0000_0004) is 4_611_686_018_427_387_900. |00000030:0000000000000000 | DQ +14 / -4 ; (0x0000_0000_0000_000E / 0xFFFF_FFFF_FFFF_FFFC) is 0. |00000038:0000000000000000 | DQ -14 / -4 ; (0xFFFF_FFFF_FFFF_FFF2 / 0xFFFF_FFFF_FFFF_FFFC) is 0. |00000040: |; Zneménkové modulo: |00000040:0200000000000000 | DQ +14 #\ +4 ; +(0x0000_0000_0000_000E \ 0x0000_0000_0000_0004) is +2. |00000048:FEFFFFFFFFFFFFFF | DQ -14 #\ +4 ; -(0x0000_0000_0000_000E \ 0x0000_0000_0000_0004) is -2. |00000050:0200000000000000 | DQ +14 #\ -4 ; +(0x0000_0000_0000_000E \ 0x0000_0000_0000_0004) is +2. |00000058:FEFFFFFFFFFFFFFF | DQ -14 #\ -4 ; -(0x0000_0000_0000_000E \ 0x0000_0000_0000_0004) is -2. |00000060: |; Bezznaménkové modulo: |00000060:0200000000000000 | DQ +14 \ +4 ; (0x0000_0000_0000_000E \ 0x0000_0000_0000_0004) is 2. |00000068:0200000000000000 | DQ -14 \ +4 ; (0xFFFF_FFFF_FFFF_FFF2 \ 0x0000_0000_0000_0004) is 2. |00000070:0E00000000000000 | DQ +14 \ -4 ; (0x0000_0000_0000_000E \ 0xFFFF_FFFF_FFFF_FFFC) is 14. |00000078:F2FFFFFFFFFFFFFF | DQ -14 \ -4 ; (0xFFFF_FFFF_FFFF_FFF2 \ 0xFFFF_FFFF_FFFF_FFFC) is 18_446_744_073_709_551_602. |00000080: |
↑ Posuvy

Posuvy nejsou komutativní. Operand na levé straně je považován za 64bitový integer a jeho hodnota bude posunuta vlevo či vpravo o počet bitů určený operandem na pravé straně.

Posuvy mají vyšší prioritu oproti jiným aritmetickým operacím, neboť korespondují s výpočtem mocnin dvou a ne s násobením či dělením. Tak například 1 << 7 je ekvivalentní 1 * 27.

NASM vyhodnocuje výraz 4 + 3 << 2 jako (4 + 3) << 2 -> 28, zatímco €ASM jako 4 + (3 << 2) -> 16.

Bity vstupující do nejméně významného bitu (LSb) během operací Shift Left jsou vždy 0. Bity vstupující do nejvýznamnějšího bitu (MSb) během operací Shift Right jsou buď 0 (v případě Shift Logical Right), nebo kopírují jeho předchozí hodnotu (v případě Shift Arithmetic Right), zachovávajíce tak znaménko operandu.

Bity opouštějící LSb během Shift Right jsou zahazovány. Bity opouštějící MSb během Shift Left jsou také zahazovány, avšak €ASM ohlásí chybu overflow E6311, pokud se změnilo znaménko (udržované v MSb) výsledné hodnoty. Citlivost na přetečení (overflow) v asm-time je tedy jediný rozdíl mezi operacemi Shift Arithmetic Left a Shift Logical Left.

Operand vpravo od operátoru Shift může být libovolné číslo, nicméně pokud je větší než 64, výsledkem posuvu je 0 s jednou výjimkou: negativní číslo posunuté aritmeticky vpravo o víc než 64 bitů dává výsledek 0xFFFF_FFFF_FFFF_FFFF -> -1.

Posun o 0 bitů nedělá nic. Posuv o negativní číslo jen obrací směr posuvu zprava doleva a obráceně.

Operace rotace během asm-time nejsou podporovány.

|00000000:0000010000000000 | DQ 1 << 16 ; Výsledek je 65536. |00000008:F4FFFFFFFFFFFFFF | DQ -3 #<< 2 ; Výsledek je -12. |00000010:8078675645342312 | DQ 0x1122_3344_5566_7788 << 4 ; Výsledek je 0x1223_3445_5667_7880. |00000018:98A9BACBDCEDFE0F | DQ 0xFFEE_DDCC_BBAA_9988 >> 4 ; Výsledek je 0x0FFE_EDDC_CBBA_A998. |00000020:98A9BACBDCEDFEFF | DQ 0xFFEE_DDCC_BBAA_9988 #>> 4 ; Výsledek je 0xFFFE_EDDC_CBBA_A998. |00000028:0000000000000000 | DQ 0x8000_0000_0000_0000 << 1 ; Výsledek je 0x0000_0000_0000_0000. |00000030: | DQ 0x8000_0000_0000_0000 #<< 1 ; Přetečení, MSb by se změnilo. |### E6311 ShiftArithmeticLeft 64bit overflow in "0x8000_0000_0000_0000 #<< 1". |00000030: |
↑ Bitová aritmetika

Bitové operace NOT, AND, OR, XOR provádějí logické operace s celým operandem bit po bitu.

|0000:FA | DB ~ 5 ; ~ 0000_0101b je 1111_1010b což je -6. |0001:04 | DB 5 & 12 ; 0000_0101b & 0000_1100b je 0000_0100b což je 4. |0002:0D | DB 5 | 12 ; 0000_0101b | 0000_1100b je 0000_1101b což je 13. |0003:09 | DB 5 ^ 12 ; 0000_0101b ^ 0000_1100b je 0000_1001b což je 9.
↑ Booleovská algebra

Logické operace NOT, AND, OR, XOR umějí operovat s čísly stejně jako s booleovskými hodnotami.
Každý operand, interně uložený jako nenulové 64bitové číslo, je převeden na booleovské pravda (0xFFFF_FFFF_FFFF_FFFF) před vlastní logickou operací.
Operand s hodnotou 0 je považován za nepravda.

|0000:FF | DB 3 && 4 ; 0000_0011b && 0000_0100b je TRUE && TRUE (oba operandy jsou nenulové), tedy pravda. |0001:00 | DB 3 & 4 ; 0000_0011b & 0000_0100b nemají žádný společný bit, výsledek je 0000_0000b, tedy nepravda.

↑ Adresové výrazy

Číselné výrazy operují s numerickými hodnotami, jako 1, 0x23, '4567' nebo se symboly reprezentujícími takové skalární hodnoty, jako NumericSymbolTen EQU 10. Na druhé straně, většina symbolů ve skutečném programu reprezentuje hodnotu adresy ukazující na určitou pozici v programovém kódu.

Zatímco prosté číslo (skalár) je interně uloženo v €ASM v osmi bajtech, adresa potřebuje přídavný prostor k udržování informace, do kterého segmentu patří.

Představte si, že řídíte automobil a minuli jste na dálnici kilometrovník označený 123. V tom vám telefonují vaši přátelé, že právě minuli kilometrovník 97. Jaká je vzdálenost mezi vašimi auty? Odpověď je prostá jako odečítání dvou čísel pouze pokud obě auta jedou po téže dálnici.

Operace prováděné s adresami jsou omezeny. Nemohou být násobeny, děleny, posouvány. Jsou povoleny pouze dva druhy operací s adresami:

  1. K adresnímu symbolu může být přičteno nebo odečteno prosté číslo (skalár). Výsledkem je opět adresní symbol; operace ovlivňuje pouze ofsetovou část adresy.
  2. Dva symboly mohou být odečteny nebo porovnány, pokud oba leží v téže sekci. Výsledkem je skalární číselná hodnota odpovídající rozdílu jejich ofsetů.

↑ Registrový výraz

Paměťové proměnné jsou adresovány ofsetem proti prvnímu bajtu segmentu, kterému se říká displacement. Mohou být také doplněny za běhu obsahem jednoho nebo dvou registrů. Takovému zápisu se říká registrový výraz.

Na rozdíl od instrukcí s číselnou hodnotou vestavěnou do instrukčního kódu, jako třeba ADD EAX,1234, instrukce ukládající nebo čtoucí data z paměti musí mít celý operand uzavřený v hranatých závorkách [ ]. Například ADD EAX,[1234], kde 1234 je ofset proměnné typu DWORD v datovém segmentu, odkud bude načtena.

MASM dovoluje vynechat hranaté závorky i v případě, že je operandem proměnná v paměti, např. ADD EAX,Something. Ubohý čtenář programu psaného v MASM pak musí vyhledat definici proměnné, aby zjistil, zda byla definována v paměti (Something DD 1) anebo jako konstanta (Something EQU 1). Novější asemblery naštěstí tento nedostatek napravují.

Adresní výraz může být doprovázen názvy registrů, stává se z něj registrový výraz. Kompletní adresní výraz je definován schématem
segment: base + scale * index + displacement kde
segment je segmentový registr CS, DS, ES, SS, FS, GS,
base je BX, BP v 16bitovém adresním módu, nebo EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI, R8D..R15D v 32bitovém adresním módu, nebo RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI, R8..R15 v 64bitovém adresním módu,
scale je numerický výraz vyhodnocený na prosté číslo 0, 1, 2, 4 or 8,
index je SI, DI v 16bitovém adresním módu, nebo EAX, EBX, ECX, EDX, EBP, ESI, EDI, R8D..R15D v 32bitovém adresním módu, nebo RAX, RBX, RCX, RDX, RBP, RSI, RDI, R8..R15 v 64bitovém adresním módu,
displacement je adresa nebo číselný výraz s šířkou nepřesahující adresní mód (16, 32, 64).

Jiné asemblery povolují odlišnou syntaxi adresace paměti, např. MOV EAX,Displ[ESI], MOV EAX,dword ptr [Displ+ESI], MOV EAX,Displ+[4*ESI], MOV EAX,Displ+4*[ESI]+[EBX].
EuroAssembler vyžaduje, aby byl celý operand uzavřen do hranatých závorek: MOV EAX,[Disp+4*ESI+EBX].

Pořadí komponent v registrovém výrazu je libovolné. Kterákoli část může být vynechána.
Měřítko (scale) není povoleno v 16bitovém adresním módu a nelze je použít, pokud není specifikován indexregistr.
ESP a RSP nemohou být použity jako indexregistr (nelze je škálovat).
Adresní módy různých šířek nelze kombinovat, např. [EBX+SI].
16bitový adresní mód není dostupný v 64bitovém CPU módu.

Registry povolené v adresních módech
16bitový adresní mód v 16bitovém a 32bitovém segmentu
baseregistrBX SS:BP
indexregistrSI DI
displacement16bitový integer se znaménkem, znaménkově roztažený na šířku segmentu
32bitový adresní mód v 16bitovém a 32bitovém segmentu
baseregisterEAX EBX ECX EDX ESI EDI SS:EBP SS:ESP
indexregisterEAX EBX ECX EDX ESI EDI EBP
displacement32bitový integer se znaménkem, znaménkově roztažený nebo oříznutý na šířku segmentu
32bitový adresní mód v 64bitovém segmentu
baseregisterEAX EBX ECX EDX ESI EDI SS:EBP SS:ESP R8D..R15D
indexregisterEAX EBX ECX EDX ESI EDI EBP R8D..R15D
displacement32bitový integer se znaménkem, znaménkově rozšířený na šířku segmentu
64bitový adresní mód v 64bitovém segmentu
baseregisterRAX RBX RCX RDX RSI RDI SS:RBP SS:RSP R8..R15
indexregisterRAX RBX RCX RDX RSI RDI RBP R8..R15
displacement32bitový integer se znaménkem, znaménkově rozšířený na šířku segmentu
MOFFS adresní mód v 16bitovém, 32bitovém a 64bitovém segmentu
baseregisteržádný
indexregisteržádný
displacementinteger bez znaménka v šířce segmentu (16|32|64 bitů)

Není-li segmentový registr explicitně specifikován, použije se k adresaci defaultní segment. Pokud byl BP, EBP, RBP, ESP nebo RSP použit jako a baseregistr, defaultní segment je SS, jinak DS. Nedefaultní segmentový registr může být být specifikován buď jako explicitní instrukční prefix SEGCS SEGDS SEGES SEGSS SEGFS SEGGS, anebo jako segmentový registr, který se stává součástí registrového výrazu. Segmentový registr může být ve výrazu oddělen buď dvojtečkou : (segmentovým separátorem) nebo znaménkem plus + (indexovací operátor):

|0000:268A04 |SEGES MOV AL,[SI] |0003:268A04 | MOV AL,[ES:SI] |0006:268A04 | MOV AL,[ES+SI]

Existuje drobný rozdíl mezi implicitním a explicitním předepsáním segmentu: pokud požaduje stejný segmentový registr, který je zároveň defaultní, €ASM emituje jeho prefix pouze byl-li uveden explicitně v prefixovém poli instrukce:

|0000:8B04 | MOV AX,[SI] |0002:8B04 | MOV AX,[DS:SI] |0004:3E8B04 | SEGDS: MOV AX,[SI] |0007:3E8B04 | SEGDS: MOV AX,[DS:SI]

Viz také testy t3021, t3022, t3023 pro další příklady.

V registrových výrazech, kdy není použito škálování a není tedy jasné, který ze dvou registrů je použit v roli indexregistru, €ASM považuje dříve uvedený (levostranný) registr za bázový. Takže ve výrazu [ESI+EBP] je ESI bázový registr a implicitní segment je DS, zatímco v [EBP+ESI] je bázový registr EBP a implicitní segment je SS.

Naštěstí se rolemi implicitních segmentů nemusíme trápit ve 32bitovém a 64bitovém chráněném paměťovém modelu FLAT, kdy jsou oba registry SS a DS naplněny stejným segmentovým deskriptorem.

Třebaže operátory * nebo + v registrovém výrazu vypadají jako běžné násobení či sčítání, specifikují zcela jinou operaci Scaling a Indexing, pokud jsou aplikovány na registr. Samotné násobení a sčítání se provádí až za běhu procesoru.

Operace Indexing má nižší prioritu než odpovídající Multiplication. Tudíž výraz [EBX + 5 + ESI * 2 * 2] se vyhodnotí jako [EBX + 5 + ESI * (2 * 2)] -> [EBX + 5 + ESI * 4].

↑ Datové výrazy

Datový výraz specifikuje statická data definovaná pseudoinstrukcí D nebo pomocí literálů. Formát datových výrazů je
duplikátor * typ hodnota, kde duplikátor je nezáporné celé číslo, typ je primitivní datový typ ve plné (BYTE UNICHAR WORD DWORD QWORD TBYTE OWORD YWORD ZWORD INSTR) nebo zkrácené (B U W D Q T S O Y Z I) notaci, anebo jméno struktury. Nepovinná hodnota určuje obsah datového pole, který je opakován duplikátor-krát.

Duplikace není komutativní operace; duplikátor musí být na levé straně duplikačního operátoru *. Výchozí duplikační hodnota je 1 (kdy data nejsou duplikována). Vnořené duplikace nejsou v €ASM podporovány. Priorita duplikace je velmi nízká, datový výraz 2 + 3 * B 4 se vyhodnotí jako pět bajtů, z nichž každý obsahuje hodnotu 4. Příklad:

D 3 * BYTE          ; Deklaruje tři bajty s neinicializovaným obsahem.
D W 0x5             ; Deklaruje slovo s obsahem 5.
D 2 * U "some text" ; Deklaruje řetězec v Unicode (UTF-16) obsahující "some textsome text".
D 3 * MyStruc       ; Deklaruje tři instance strukturované proměnné MyStruc.

Viz také pseudoinstrukce D a testy t2480, t2481, t2482 pro více příkladů.

↑ Speciální výrazy

Členství ↓
Rozsah ↓
Substring ↓
Sublist ↓

Následující výrazy nejsou počítány matematickým evaluátorem výrazů; vyhodnocují se již při čtení a parsování zdrojového textu.

↑ Členství

Tečka . spojující dva identifikátory z nich učiní kvalifikované jméno (FQN), které vypadá jako identifikátor jmenného prostoru následovaný lokáním jménem. FQN je nelokální, nikdy nezačíná tečkou. Je-li například lokální symbol .bar deklarovaný v proceduře nebo struktuře Foo, €ASM jej považuje za symbol s FQN názvem Foo.bar.

Jmenný prostor (namespace) může být rovněž lokální (začínat tečkou), takže se operátor členství může vnořovat.

↑ Rozsah

Rozsah (range) je definováno jako dva číselné výrazy oddělené operátorem rozsahu, což je .. (dvě tečky) a reprezentuje souvislou řadu celých čísel mezi těmito hodnotami, včetně prvé i poslední.

Operátor rozsahu má vlastnost zvanou sklon (slope), která může být negativní, nulová nebo pozitivní. Sklon je definován jako znaménko rozdílu mezi pravou a levou hodnotou rozsahu. Příklady:

0 .. 15    ; Rozsah představuje šestnáct čísel od 0 do 15; sklon je pozitivní.
-5 .. -4   ; Rozsah představuje hodnoty -5 a -4; sklon je pozitivní.
3 .. 4 - 1 ; Rozsah představuje jednu hodnotu 3; sklon je nulový.
2..-2      ; Rozsah představuje pět hodnot 2, 1, 0, -1, -2; sklon je negativní.
↑ Substring

Substring je operace vracející část vstupního textu. Operátorem substring je rozsah uzavřený v hranatých závorkách []. Text je považován za sekvenci 8bitoých znaků (bajtů) a rozsah určuje, které z nich budou použity.

%Sample1 %SET ABCDEFGH ; Preprocesní %proměnná %Sample1 nyní obsahuje 8 znaků.
 DB "%Sample1[3..5]"   ; Toto se ve skutečnosti přeloží jako  DB "CDE"
↑ Sublist

Operace Sublist se podobá operaci Substring s tím rozdílem, že se používají složené závorky {} a že považuje vstupní text za pole čárkou oddělených položek (pokud dochází k expanzi %proměnné), nebo za sekvenci fyzických řádků (v případě inkluze souboru).

 INCLUDE "MySource.asm"{1..10} ; Vlož prvních deset řádků souboru "MySource.asm".

  Společné vlastnosti suboperací Substring a Sublist:

Suboperátor musí být připojen bez mezer.
Suboperaci lze připojit ve čtyřech případech:

Při aplikaci na jméno souboru toto musí být uvedeno v dvojitých uvozovkách.

Znaky a položky se počítají počínaje číslem 1.
Číslo posledního členu je automaticky přiřazeno speciální proměnné %&.

Pořadové číslo posledního znaku|položky|řádku je přiřazeno EuroAssemblerem do automatické preprocesní %proměnné nazvané %&. Tato %proměnná je platná pouze uvnitř suboperace (uvnitř hranatých nebo složených závorek).

Taky můžete použít pseudoinstrukci %SETS k získání počtu znaků přiřazených %proměnné, a pseudoinstrukci %SETL k získání počtu položek v ní obsažených (délka pole).
Můžete použít atributový operátor FILESIZE# k získání počtu znaků v souboru v asm-time.

V operaci Substring hodnota automatické %proměnné %& určuje počet znaků přiřazených substringované %proměnné nebo (v případě suboperace souboru) určuje velikost souboru v bajtech.
V operaci Sublist reprezentuje pořadové číslo poslední neprázdné položky v %proměnné, nebo (v případě suboperace souboru) určuje počet fyzických řádků v souboru.

|4142432C4445462C2C4748492C4A4B4C |%Sample %SET ABC,DEF,,GHI,JKL |0000: | ; %& je nyní 16 v %Sample[%&] a 5 v %Sample{%&}. |0000:4B4C | DB "%Sample[15..%&]" ; DB "KL" |0002:4445462C2C4748492C4A4B4C | DB "%Sample{2..%&}" ; DB "DEF,,GHI,JKL"

Suboperovaný název souboru musí být uzavřen v uvozovkách i když jeho jméno neobsahuje mezery. Otevírací závorka musí bezprostředně následovat vstupní text (jméno %proměnné anebo ukončující závorku souborového jména). Mezi %proměnnou a levou závorkou suboperace nemohou být žádné mezery.

Suboperace jsou velmi tolerantní k hodnotám rozsahu. Bez varování akceptuje neexistující znak či položku, např. je-li některý člen rozsahu nulový nebo záporný. Rozsah s negativním sklonem prostě nevrací nic. Rozsah s nulovým sklonem vrací jediný znak|položku|řádek, pokud je index mezi 1 a %&, jinak nevrací nic.

|4142434445464748 |%Sample %SET ABCDEFGH ; %Proměnná %Sample nyní obsahuje 8 znaků. |0000:4142434445 | DB "%Sample[-3..5]" ; DB "ABCDE" |0005:434445464748 | DB "%Sample[ 3..99]" ; DB "CDEFGH" |000B:43 | DB "%Sample[ 3..3]" ; DB "C" |000C: | DB "%Sample[5..3]" ; DB "" |000C:4142434445464748205B352E2E335D | DB "%Sample [5..3]" ; DB "ABCDEFGH [5..3]" ; Toto není suboperace.

Suboperační rozsah sestává ze tří komponent:

  1. minimální index rozsahu
  2. operátor rozsahu ..
  3. maximální index rozsahu

Pokud bude některá komponenta chybět, nahradí se výchozí hodnotou. Defaultní minimální index je 1. Defaultní maximální index je %&. |4142434445464748 |%Sample %SET ABCDEFGH ; Preprocesní %proměnná %Sample nyní obsahuje 8 znaků. |0000:4142434445 | DB "%Sample[..5]" ; -> DB "%Sample[1..5]" -> DB "ABCDE" |0005:434445464748 | DB "%Sample[3..]" ; -> DB "%Sample[3..8]" -> DB "CDEFGH" |000B:4142434445464748 | DB "%Sample[..]" ; -> DB "%Sample[1..8]" -> DB "ABCDEFGH" |0013:4142434445464748 | DB "%Sample[]" ; -> DB "%Sample[1..8]" -> DB "ABCDEFGH"

Všechny následující zápisy jsou totožné co se týká expanze %variable:

%variable
%variable[1..%&]
%variable[..%&]
%variable[1..]
%variable[..]
%variable[]
%variable{1..%&}
%variable{..%&}
%variable{1..}
%variable{..}
%variable{}

Poslední řádek předchozího příkladu je užitečný, potřebujeme-li připojit nějaký text hned za %proměnnou, např. 123 k jejímu obsahu. Nemůžeme psát %proměnná123, neboť připojení číslic by změnilo jméno původní %proměnné. Řešením je použití prázdné suboperace, která nemění obsah %proměnné, ale odděluje její jméno od připojeného textu: %proměnná[]123 nebo %proměnná{}123.

Pokud rozsah uvnitř závorek obsahuje pouze jedno číslo bez operátoru rozsahu, považuje se současně za minimální i maximální index a bude expandován právě jeden znak|položka|řádek: %Sample1[3] -> %Sample[3..3] -> C.

Suboperace se mohou řetězit. Řetěz se zpracovává zleva doprava. Příklad: |4142432C4445462C2C4748492C4A4B4C |%Sample %SET ABC,DEF,,GHI,JKL ; %& je nyní 16 v %Sample[%&] a 5 v %Sample{%&}. |0000:4A4B | DB "%Sample{4..5}[2..6]{2}" ; DB "JK"

První sublist předchozího příkladu bere položky č. 4 a 5, což dává seznam dvou položek GHI,JKL. Následující substring extrahuje znaky od druhého do šestého z tohoto sublistu. což dává HI,JK. Poslední operace sublist expanduje druhou položku, což jsou znaky JK.

Suboperace se mohou vnořovat. Vnitřní rozsah je vyhodnocuje před vnějším.: |31323334353637383930 |%Sample %SET 1234567890 |0000:3233343536 | DB "%Sample[2..%Sample[6]]" ; -> DB "%Sample[2..6]" -> DB "23456"

↑ Sekce

Pro každou emitující instrukci generuje asembler data nebo strojový kód, který bude nakonec vložen do výstupního souboru. Naštěstí nemusíme psát celý program v přesném pořadí vyžadovaném výstupním formátem. Generovaná data a kód jsou rozdělovány do svých výstupních sekcí. Přepnutí do jiné sekce je prosté: stačí uvést v poli návěstí jméno sekce v hranatých závorkách [ ].

Předstvte si, že jako programátor diktujete program své sekretářce (EuroAssembleru). Nadiktovali jste několik strojových instrukcí, které sekretářka zapsala na list papíru nazvaný [TEXT]. Pak se rozhodnete diktovat jiný druh dat. Sekretářka vezmi jiný list, označí jej [DATA] a začne psát tam. Později, až budete diktovat další strojové instrukce, sekretářka vezme list označený [TEXT] a pokračuje v psaní tam, kde minule skončila.
Můžete otevírat nové listy a podle libosti mezi nimi přeskakovat. Až diktát skončí, použité listy budou secvaknuty dohromaty (slinkovány).

V EuroAssembleru se používá termín sekce pro pojmenovaný úsek segmentu charakterizovaný počáteční a koncovou adresou. Každý segment má jednu nebo více sekcí. Ve výchozím stavu má segment jen jednu sekci se shodným jménem, která vznikla při definici segmentu.

↑ Segmenty

Architektura Intelu rozděluje paměť na segmenty ovládané segmentovými registry. Segment je v €ASM definován pseudoinstrukcí SEGMENT.

Za úsvitu počítačového věku programátoři vyžadovali více paměti, než pouhých 256 bajtů nebo 64 kilobajtů adresovatelných 8bitovými a 16bitovými registry. V před32bitových časech mohli designéři u Intelu zvolit spojení dvou 16bitových registrů, jako DX:AX nebo SI:BX k získání nepředstavitelného adresového prostoru 4 GB, avšak neučinili tak. Místo toho zavedli 16bitové segmentové registry specializované podle účelu adresované paměti: registr CS pro strojový kód, DS pro data, SS pro zásobník, ES pro extra dočasné použití.
Segmentové registry jsou použity k adresování 16bajtových kusů paměti zvaných paragrafy (neboli octonary word, OWORD). Lineární adresa v reálném módu CPU je počítána jako součet Používání segmentových registrů k adresaci 16bajtových paragrafů poskytlo 1 MB paměti adresovatelné každým segmentovým registem, což se tenkrát jevilo jako dostatečné pro každého.

Obsah segmentového registru v reálném módu procesoru reprezentuje paragrafovou adresu segmentu.
Obsah segmentového registru v chráněném (protected) módu reprezentuje index do tabulky deskriptorů, která udržuje navíc přídavné informace o segmentu vedle jeho adresy a velikostního limitu: šířku a přístupová práva.

Tyto přídavné informace jsou fixní v reálném módu:

Segment v run-time je souvislý blok paměti adresovaný obsahem jednoho segmentového registru.

Segment v link-time je pojmenovaná část objektového souboru, která může být spojena se segmenty stejného jména z jiných linkovatelných souborů.

V terminologii [MS_PECOFF] je linkovatelný segment nazýván section. Myslím, že termín segment je vhodnější, neboť COFF "sekce" se rozlišují přístupovými právy definovanými různými segmentovými registry, tudíž i různými segmentovými deskriptory.
V našem přirovnání segment-dálnice jsou segmenty v protected módu jako souběžné pruhy dálnice, takže mohou sdílet tytéž kilometrovníky (ofsety), avšak každý pruh je určen pro odlišný typ vozidel.

Segment ve write-time je část zdrojového kódu začínající povelem přepnutí sekce, a který končí přepnutím na jinou sekci nebo koncem programu.

V €ASM není instrukce ENDS (end-of-segment). Nelze říci tato část zdrojového kódu nepatří žádnému segmentu. Už když začínáte psát první instrukci svého programu, tak patří výchozímu (obálkovému) programu, a každý program implicitně definuje počáteční segmenty. Nicméně pokud je definována struktura nebo numerická konstanta, není důležité, který segment je momentálně platný, neboť struktury a skalární symboly nepatří žádnému segmentu.

Segmenty a sekce nemusejí být souvislé. Ve skutečnosti je nesouvislost jejich hlavním raison d'être. Dovoluje udržovat data ve zdrojovém textu poblíž kódu, který s nimi manipuluje, což přispívá ke srozumitelnosti programu.

↑ Grupy

Nejsou-li programové segmenty příliš velké, mohou být spojeny do segmentových grup (GROUP). Celá grupa je pak adresována tímtéž segmentovým registrem. Grupa je definována pseudoinstrukcí GROUP.

Příklad definice grupy: [DGRP] GROUP [DATA],[STRINGS] definuje grupu s názvem [DGRP] do níž patří segmenty [DATA] a [STRINGS].

↑ Segmentace (více o sekcích, segmentech, grupách)

Základní sekce ↓

Životnost segmentace ↓

Implicitní segmenty ↓

Konvence pojmenování segmentů ↓

Plnění segmentových registrů ↓

Pořadí sekcí a segmentů ↓

Zobrazení mapy segmentů ↓

Mezi segmentem a jeho sekcemi je v EuroAssembleru podobný vztah jako mezi grupou a jejími segmenty.

↑ Základní sekce

Jakmile je segment definován (pseudoinstrukcí SEGMENT)), automaticky je v něm vytvořena sekce se stejným jménem. tzv. základní sekce. Případné další sekce mohou být vytvořeny později, povelem s názvem této další sekce v poli návěstí. V €ASM neexistuje direktiva SECTION.

Vlastnosti sekce (class=, purpose=, combine=, align=) jsou zděděny ze segmentu, do něhož patří. Výjimkou je zarovnání (alignment) u speciálních sekcí pro literály [@LT64] .. [@LT1], [@RT0], [@RT1]..; jejich zarovnání je odvozeno od dat, která se do nich zapisují.

↑ Životnost segmentace

Každý segment má jednu nebo více sekcí. Každá sekce patří do právě jednoho segmentu. Asembler během překladu považuje všechny segmenty za začínající na virtuální adrese 0. Na konci každého průchodu jsou sekce slinkovány do svých segmentů, takže mohou začínat na vyšší adrese, kde skončila předešlá sekce. Nicméně při prvním průchodu ještě není známa velikost sekcí, takže i zde jsou sekce považovány za začínající na virtuální adrese 0. Jakmile skončí poslední průchod, všechny sekce budou slinkovány, tj. jejich emitovaný obsah a relokace spojeny do základní sekce totožné se segmentem. Jakmile se dostane ke slovu linker, není si existence sekcí už vůbec vědom.

Proč bychom měli dělit segmenty na sekce? Ve skutečnosti nemusíme, vystačili bychom s jednou implicitní sekcí na segment. Na druhé straně může být výhodnější ve velkých programech seskupovat podobná data dohromady; můžeme chtít zvláštní sekce pro DWORD proměnné, pro čísla s pohyblivou čárkou, pro textové řetězce. Může to mimo jiné ušetřit několik bajtů výplně pro zarovnávání, které by jinak bylo nutné při mísení proměnných s různou velikostí. Takto jsou organizovány také sekce pro literály.

Další příležitostí, kdy se hodí sekce, je rychlé čtení dat z read-only "databází" definovaných staticky v datovém segmentu.
Databázi si můžeme mentálně vizualizovat jako tabulku s mnoha řádky a se sloupci obsahujícími datové položky v konstantní velikosti. K rychlému výběru určitého řádku databáze je užitečné emitovat všechny položky z jednoho sloupce sekvenčně do jejich zvláštní sekce, jednu po druhé. Data každého sloupce budou mít svou vlastní sekci. Šířka kolon by měla být doplněna na 1, 2, 4 nebo 8 bajtů, takže položky pak mohou být hledány jedinou strojovou instrukcí REPNE SCAS. Jakmile bude položka nalezena, rozdíl mezi obsahem registru rDI a začátku sekce identifikuje její databázový řádek. Další položky z téhož řádku se pak vypočtou z této identifikace.
Tato metoda byla použita u vzorového projektu EuroConvertor a také v samotném EuroAssembleru, kde přiřazuje adresy zpracovávatele instrukcí (handleru) každé ze dvou tisíc mnemonických zkratek, viz DistLookupIiSetup.

Každá grupa obsahuje jeden nebo více segmentů Každý segment patří do právě jedné grupy (i když do ní nebyl vložen explicitně programátorem, během linkování bude vytvořena grupa se shodným názvem kvůli adresaci). Kdykoli se sestavuje program ve spustitelném formátu, grupy budou fyzicky spojeny do paměťového obrazu – image. Zaváděč spustitelného programu v reálném módu si není vědom existence grup ani segmentů.

↑ Implicitní segmenty a grupy

Když €ASM začíná překládat program, vytvoří nejprve implicitní skupiny a grupy. Jejich názvy závisí na zvoleném programovém formátu:

Implicitní segmenty
FORMAT=Názvy segmentů
BIN[BIN]
BOOT[BOOT]
COM[COM]
OMF | MZ[CODE],[RODATA],[DATA],[BSS],[STACK]
COFF | PE | DLL | ELF | ELFX | ELFSO[.text],[.rodata],[.data],[.bss]

Nejste-li s implicitními názvy spokojeni, mohou být na začátku programu předefinovány anebo vytvořena sada nových segmentů s odlišnými názvy. Nepoužité segmenty (do nichž nebylo nic emitováno) nebudou zařazeny do výsledného souboru a mohou být ignorovány.

Jakmile kompilace skončí a všechny segmenty z linkovaných modulů byly zkombinovány do hlavního programu, €ASM se dívá na segmenty, které nejsou v žádné grupě a vytvoří pro ně implicitní grupu, přičemž bere do úvahy paměťový model:

Modely s jedním kódovým segmentem (TINY, SMALL, COMPACT) linkují všechen kód do jediné grupy, bez ohledu na počet kódových segmentů, které mohly být v programu definovány.

Multikódové modely (MEDIUM, LARGE) ponechávají každý kódový segment v jeho vlastní grupě, takže mezisegmentové skoky, volání a návraty by měly mít JMP|CALL|RET DIST=FAR.

Podobně jednodatové modely (TINY, SMALL, MEDIUM) předpokládají, že se inicializovaná i neinicializovaná data vejdou do jedné grupy nepřesahující 64 KB, takže linker €ASM přiřazuje všechny datové a bss segmenty této implicitní grupě a register DS není třeba měnit během přístupu k datům z různých segmentů.

↑ Konvence pojmenování segmentů

Jména grup, segmentů a sekcí jsou vždy obklopena hranatými závorkami.

Začíná-li jméno tečkou, na rozdíl od symbolů před něj není interně připojován jmenný prostor (namespace). Jména grup, segmentů a sekcí jsou vždy nelokální.

Počet znaků v jejich názvu je v principu libovolný, avšak může být omezen výstupním formátem programu. V modulech OMF délka názvu segmentu nebo grupy nesmí přesáhnout 255 znaků. Ve spustitelném formátu PE je jméno hlavičky segmentu ořezáno na 8 znaků.

€ASM považuje všechna jména segmentů za citlivá na velikost písmen. Potřebujete-li linkovat váš segment s objektovým modulem generovaným jiným kompilátorem, jenž konvertuje segmentové názvy na velká písmena nebo je mění připojováním podtržítek, měli byste tomu přizpůsobit svou konvenci pojmenovávání.

Segmentové jméno by mělo být unikátní, nemůžete definovat dva segmenty s identickým názvem v jednom programu, s výjimkou implicitních segmentů, pokud dosud nebyly použity (nic do nich nebylo emitováno). Je však možné definovat segmenty se stejným názvem v jiných programech a spojovat je v link-time. Takové segmenty pak budou spojovány v souladu s jejich vlastností COMBINE=.

Názvy sekcí nemohou být duplikovány už z principu. Když se jméno sekce vyskytne v programu podruhé, pouze přepne emitování do této sekce namísto vytváření nové.

Jména literálních sekcí začínají znaky @LT nebo @RT, raději se vyhněte vytváření sekcí začínající touto kombinací.

Se segmenty s dolarem $ v názvu se zachází poněkud odlišně: pokud souhlasí znaky na levé straně od tohoto znaku $, všechny takové segmenty budou slinkovány jeden za druhým v abecedním pořadí.

Existují konvence, jak jsou "sekce" pojmenovávány v modulech COFF, kterým byste se měli přizpůsobit, chcete-li úspěšně linkovat programy v €ASM s moduly vytvořenými jinými kompilátory.

↑ Plnění segmentových registrů

Pokud €ASM vytváří chráněné spustitelné 32bitové nebo 64bitové programy ELFX nebo PE, nemusíme se vůbec zabývat segmenty, grupami nebo zásobníkem. Všechny segmentové registry již OS Linux nebo Windows naplnil a zásobník byl nastaven automaticky.

Při spouštění programu s formátem COM operační systém DOS naplnil registry CS=DS=SS=ES paragrafovou adresou struktury PSP, nastavil IP=100h a SP na konec zásobníkového segmentu, obvykle 0FFFEh. Zde se opět nemusíme o segmentové registry starat.

Jakmile je 16bitový spustitelný program (FORMAT=MZ) připraven v paměti ke startu, jeho segmentové registry již byly nastaveny zaváděčem DOSu. CS:IP byl nastaven na vstupní bod programu (ENTRY=), SS:SP byl nastaven na vrchol zásobníku, avšak registry DS a ES byly nastaveny na PSP, což není náš datový segment. To bude třeba v kódu programu napravit.

V architektuře Intel není instrukce pro nastavení segmentového registru přímým číslem, takže se to obchází před obecný registr nebo zásobník:

; Naplnění segmentového reigstru paragrafovou adresou segmentu [DATA]
;   použitím obecného registru (což je rychlejší):
MOV AX, PARA# [DATA]
MOV DS,AX
; nebo použitím strojového zásobníku (což je kratší):
PUSH PARA# [DATA]
POP DS

Je na programátorovi, aby naplnil segmentový registr adresou jiného segmentu, kdykoli mají být data z něho použita. €ASM nedělá žádné předpoklady ohledně obsahu segmentových registrů; neeistuje v něm direktiva ASSUME, USING ani WRT.

↑ Pořadí sekcí a segmentů

Pořadí segmentů ve výstupním programu je obecně založeno na těchto parametrech:

  1. Účel segmentu, který implikuje přístupová práva Read|Write|Execute.
  2. Pořadí, v jakém byly segmenty deklarovány ve zdrojovém textu.
  3. Segmenty s dolarem $ v názvu patřící do téže grupy a jejichž znaky vlevo od $ jsou identické, jsou linkovány jako sousedící a řazeny abecedně podle názvu.

Pořadí sekcí

Na konci každého průchodu jsou sekce slinkovány do segmentů v tomto pořadí:

  1. Bázová sekce, definovaná implicitně s každým segmentem.
  2. Ostatní neliterální sekce v pořadí, jak byly deklarovány.
  3. Datově literální sekce v klesajícím pořadí jejích zarovnání, tj. ([@LT64], [@LT32],..[@LT1]).
  4. Kódově literální sekce v abecedním pořadí ([@RT0], [@RT1], [@RT2]..).

Pořadí segmentů

Segmenty se kombinují a spojují v link-time v tomto pořadí:

  1. Grupy inicializovaných segmentů v pořadí jejich definice v textu.
  2. Inicializované segmenty nepatřící do žádné grupy.
  3. Grupy neinicializovaných segmentů v pořadí jejich definice v textu.
  4. Neinicializované segmenty nepatřící do žádné grupy.

Segmenty v každé grupě jsou v pořadí, v jakém byly definovány ve zdrojovém kódu, nikoli jak byly deklarovány v instrukci GROUP.

Při linkování spustitelného programu je každý segment přiřazen některé grupě, přinejmenším své implicitní s identickým názvem.

Implicitní grupy segmentů jsou použity interně pro relokační účely. Programy v chráněném módu (MODEL=FLAT) se o segmentové registry příliš nestarají, takže v programech pro Linux a Windows se segmenty ani grupami nemusíme zabývat.
Anatomie programu založeného na formátu COFF:
NázevÚčel
segmentu
PřístupVelikost
32bit | 64bit
Zarovnání v souboru
32bit | 64bit
Poznámka
Hlavička MZ DOS RW128 | 1280) 2)
Program MZ stubRW16 | 160) 2)
Podpis PERW4 | 432 | 320) 2)
Hlavička souboru R20 | 2016 | 160)
"Volitelná" hlavička R224 | 24016 | 160) 2)
Hlavičky "sekcí" RNrOfSe*4016 | 160)
.textCODERXFiAl|SeAl
.rodataRODATARFiAl|SeAl
.dataDATARWFiAl|SeAl
.bssBSSRWFiAl|SeAl
.idataIMPORT+IATRWX16|160) 2)
.edataEXPORTRW16|160) 2) 5)
.relocBASERELOCRW16|160) 2)
.rsrcRESOURCERW16|160)
Tabulka symbolů (SYMBOLS)RNrOfSym*1816 | 160) 1) 3)
Tabulka řetězců(STRINGS)4 | 40) 1) 3)
Anatomie programu založeného na formátu ELF:
NázveÚčel
segmentu
PřístupVelikost
32bit | 64bit
Zarovnání v souboru
32bit | 64bit
Poznámka
Hlavička souboru R52 | 640)
Hlavičky "programů" RNrOfPh*(32|56)16 | 80) 2)
Hlavičky "sekcí" RNrOfSe*(40|64)8 | 16)0)
.symtabSYMBOLSNrOfSym*(16|24)16 | 8
.hashHASHR4 | 44)
.strtabSTRINGS1 | 1
.shstrtabSTRINGS1 | 1
.interpRODATAR1 | 14)
.pltPLTRXNrOfJmp*16164)
.textCODERXFiAl|SeAl
.rodataRODATARFiAl|SeAl
.dataDATARWFiAl|SeAl
.bssBSSRWFiAl|SeAl
.dynamicDYNAMICRWNrOfRec*(8|16)8 | 164)

Poznámky:
0) Speciální struktura bez vlastní hlavičky.
1) Použito pouze v objektovém modulu.
2) Použito pouze ve spustitelném programu.
3) Použito ve spustitelném programu pokud EUROASM DEBUG=ENABLED.
4) Použito ve spustitelném programu pokud je linkován s DSO.

Přístupová práva:
R Alokuj pamět a povol čtení.
W Povol zápis.
X Povol provádění instrukcí.
FiAl|SeAl maximum z hodnot FileAlignment | SegmentAlignment.

↑ Zobrazení mapy segmentů

Pseudoinstrukce %DISPLAY Sections zapisuje do listingového souboru kompletní dosud deklarovanou mapu grup, segmentů a sekcí, jeden objekt na jeden řádek, reprezentovaný ladicím oznámením D1260 (grupa), D1270 (segment), D1280 (sekce). Segment je odsazen dvěma mezerami, sekce čtyřmi mezerami.

Namísto %DISPLAY Sections bychom mohli zrovna tak použít %DISPLAY Segment nebo %DISPLAY Groups, výsledek je identický. Kterýkoli povel vždy zobrazuje celou mapu grup, segmentů a sekcí.

Podobnou mapu tiskne €ASM do listingu včetně konečných virtuálních adres, ledaže by to bylo zakázáno volbou PROGRAM LISTMAP=OFF.

↑ Distance

Termín distance specifikuje vzdálenost mezi dvěma adresami, není to ale pouhý rozdíl dvou ofsetů. V €ASM tento termín reprezentuje jednu ze tří výčtových hodnot: FAR, NEAR, SHORT.

Distance mezi dvěma adresami je FAR, pokud obě náleží do různých segmentů, jinak je NEAR nebo SHORT. Rozdíl ofsetů je SHORT, pokud se vejde do 8bitového integeru se znaménkem, tedy -128..+127.

↑ Šířka

€ASM je 64bitový assembler, může rovněž kompilovat programy pracující s 32 a 16 bitovými slovy. Počet bitů, s nimiž CPU současně pracuje, se nazývá šířka a je buď 16, 32 nebo 64.

Šířka se vždy udává v bitech.

Šířka je vlastnost segmentu. Některé 32bitové formáty dovolují používat segmenty různých šířek v jednom souboru. Šířka adresního a operačního módu může být měněna ad hoc instrukčními prefixy ATOGGLE, OTOGGLE.

Pseudoinstrukce PROGRAM má rovněž vlastnost WIDTH=. Ta stanovuje výchozí šířku všech segmentů programu, u nichž nebyla explicitně změněna. Šířka programu je rovněž použita k výběru formátu výstupního souboru, například zda má být PE generován jako 32bitový nebo 64bitový.

↑ Velikost

Velikost (size) je prosté nezáporné číslo určující počet bajtů v objektu (registru, paměťové proměnné, struktuře, segmentu, souboru apod.). Velikost řetězce je definována v bajtech, bez ohledu na to, zda je složen z ANSI nebo z WIDE znaků.

Velikost objektu může být zjištěna v asm-time pomocí atributového operátoru SIZE# nebo FILESIZE#.

Velikost preprocesní %proměnné může být načtena pseudoinstrukcí %SETS.

Velikost se vždy měří v bajtech.

Velikost a délka prvků EuroAssembleru (identifikátorů, čísel, struktur, výrazů, počtu operandů atd.) není z principu omezena, avšak velikosti jsou interně ukládány do 32bitových znaménkových integerů, takže limit je 2_147_483_647 znaků. V praxi jsme ovšem omezeni velikostí dostupné paměti.

↑ Délka

Tento termín se používá k počítání čárkou oddělených položek v seznamu (v poli), např. počtu operandů v instrukci. Kupříkladu v instrukci VPERMI2B XMM1,XMM2,XMM3,MASK=K4,ZEROING=ON je délka pole operandů 5.

Délka pole obsaženého v %proměnné může být získána pseudoinstrukcí %SETL.

↑ Jmenný prostor

Názvy symbolů a struktur vytvořených v programu musí být unikátní. U větších projektů může být udržování unikátních jmen obtížné, zvláště když více lidí pracuje souběžně na různých částech programu. Proto programátoři mohou používat lokální identifikátory, které musí být unikátní pouze v úseku zdrojového kódu zvaného jmenný prostor neboli namespace. Jmenný prostor je rozsah zdrojového souboru definovaný pomocí bloku jmenného prostoru. V €ASM máme čtyři blokové psuedoinstrukce, které vytvářejí jmenný prostor: PROGRAM, PROC, PROC1, STRUC. Název souboru je zároveň názvem jmenného prostoru. Identifikátor je lokální, když jeho jméno začíná tečkou .. Na rozdíl od standardních symbolů znak následující po této tečce může být číslice a není chyba, pokud následující znaky tvoří rezervovaný název. Příklady platných lokálních identifikátorů: .L1, .20, .AX.

Názvy lokálních identifikátorů se v €ASM udržují interně spojeny s názvem jmenného prostoru, tvoří tak kvalifikované jméno (FQN). Na lokální symboly můžeme odkazovat tímto .lokálním jménem pouze uvnitř jejich jmenného prostoru; kvalifikovaným jménem můžeme odkazovat kdekoli v programu.

Jmenný prostor začíná na poli operace příkazu začátku bloku a končí na poli operace konce bloku. Díky tomu samotný jmenný prostor (návěstí bloku) může být rovněž lokální a jmenné prostory se mohou vnořovat.

MyProg PROGRAM      ; PROGRAM zahajuje namespace MyProg.           ;
                                                                    ;
Main    PROC        ; PROC zahajuje vnitřní namespace Main.         ;
  .10:   RET        ; Lokální návěstí; jeho FQN je Main.10.        ;
        ENDP Main   ; Po ENDP jsme opět v namespace MyProg.        ;
                                                                    ;
.Local  PROC        ; Jeho FQN je MyProg.Local.                    ;
  .10:   RET        ; FQN tohoto návěstí je MyProg.Local.10.       ;
        ENDP .Local ; MyProg.Local namespace končí hned za ENDP.   ;
                                                                    ;
       ENDPROGRAM MyProg

Vedle bloku jmenného prostoru je ještě jedna příležitost, kde je jmenný prostor použit: pole operandů instrukce definující strukturovanou proměnnou dočasně přebírá jmenný prostor struktury, z níž tvoříme její instanci:

DateProg PROGRAM      ; PROGRAM zahajuje namespace DateProg.                   ;
                                                                                ;
Datum STRUC  ; Deklarace struktury Datum vytváří namespace Datum.              ;
.day   DB 0                                                                     ;
.month DB 0                                                                     ;
.year  DW 0                                                                     ;
      ENDSTRUC Datum ; Namespace Datum končí hned za polem ENDSTRUC            ;
                                                                                ;
[.data] ; Jméno segmentu není lokální, namespace se zde ignoruje.               ;
Birthday DS Datum, .day=1, .month=1, .year=1970                                 ;
                                                                                ;
; Předchozí instrukce definuje čtyřbajtovou paměťovou proměnnou                 ;
; zvanou Birthday v sekci [.data] a staticky nastavuje její členy.              ;
; Během definování proměnné "Birthday" €ASM využívá vlastnosti                  ;
; deklarované jako Datum.day, Datum.month, Datum.year (B,B,W).                  ;
; Členové mohou být odkazováni jako Birthday.day, Birthday.month, Birthday.year.;

↑ Scope

Scope je vlastnost symbolu, která určuje jeho viditelnost.

Každý symbol definovaný v programu může být odkazován svým názvem kdekoli uvnitř programu v asm-time. Náš program (objektový modul) může být také slinkován s dalšími moduly a knihovnami, které mohly rovněž využít stejná jména pro své symboly, ale to je v pořádku a žádný konflikt nenastává, neboť programy jsou kompilovány každý zvlášť. Toto je standardní chování, takové symboly mají standardní privátní viditelnost omezenou na vnitřek jejich bloku PROGRAM..ENDPROGRAM.

Začíná-li název symbolu tečkou ., viditelnost takového privátního lokálního jména je ještě užší, je limitována na nejmenší blok namespace, v němž byl symbol definován (PROC..ENDPROC, STRUC..ENDSTRUC).

Na druhé straně ale programy slinkované z několika modulů mohou potřebovat přistupovat k symbolům mimo jejich standardní privátní viditelnost, například volat vstupní bod nějaké funkce z linkované knihovny. Jména takových globálních symbolů by měla být unikátní mezi všemi linkovanými moduly.

Scope definované v €ASM
privateGlobal
Standardlocalstatické linkování dynamické linkování
PublicExterneXportImport

Vlastnost scope symbolu může být zjišťována v asm-time atributovým operátorem SCOPE#, který vrací ASCII hodnotu velkého písmene zkratky pro jeho viditelnost, např.

MySymbol EXTERN
MOV AL,SCOPE# MySymbol ; Toto je ekvivalentní k MOV AL,'E'

Odpovídající zkratky viditelností jsou uvedeny ve výše uvedené tabulce. Stejné zkratky 'G','S','P','E','X','I' jsou také použity, pokud jsou vlastnosti symbolů vypsány povelem %DISPLAY Symbols a také v listingu při LISTGLOBALS=ENABLED.

Viditelnost GLOBAL, PUBLIC, EXTERN, EXPORT a IMPORT může být explicitně deklarována pseudoinstrukcí s tímto jménem. Viditelnost GLOBAL dále může být deklarována implicitně, tím že se jméno symbolu zakončí pomocí dvou (nebo i více) dvojteček ::. Symbol deklarovaný jako GLOBAL bude viditelný jako PUBLIC (byl-li definován v programu) anebo je označen jako EXTERN (pokud není v programu definován).

Zjednodušenou deklarací pomocí dvou dvojteček může být označena pouze viditelnost při statickém linkování (PUBLIC, EXTERN). Má-li být symbol exportován (píšeme-li DLL) nebo má-li být dynamicky importován z jiné DLL, použít dvě dvojtečky nestačí a potřebujeme buď explicitní deklaraci pomocí EXPORT|IMPORT, anebo je vyžadováno LINK importní_knihovna.

Word1:  DW 1   ; Standardní privátní viditelnost.
Word2:: DW 2   ; Public scope deklarovaná implicitně (dvěma dvojtečkami).
Word3   PUBLIC ; Public scope deklarovaná explicitně.
Word4   GLOBAL ; Public nebo extern scope (podle existence definice Word4 v tomto programu).
Word5   GLOBAL ; Public nebo extern scope (podle existence definice Word5 v tomto programu).
Word6   EXTERN ; Externní scope. Symbol Word6 nesmí být v tomto programu definován.
Word4:         ; Definice symbolu Word4.
        MOV EAX,Word5 ; Reference externího symbolu Word5.
; Scope symbolu Word1 is PRIVATE.
; Scope symbolů Word2, Word3, Word4 je PUBLIC.
; Scope symbolů Word5, Word6 je EXTERN.

↑ Datové typy

Důležitou vlastností textů a čísel uložených v počítačové paměti je datový typ, což je pravidlo určující, jak se má daný objekt interpretovat. €ASM rozeznává následující typy dat:

Fundamentální datové typy
Jméno typuZkratkaVelikostAuto
alignment
Šířka Typické
úložiště
Znakový
řetězec
Celé
číslo
Číslo
s plovoucí tečkou
Spojený
vektor
BYTEB118 R8ANSI8bit
UNICHARU2216 R16WIDE
WORDW2216 R1616bit
DWORDD4432 R32,ST32bitjednoduchá přesnost
QWORDQ8864 R64,ST64bitdvojitá přesnost
TBYTET10880 STrozšířená přesnost
OWORDO1616128 XMM4×D | 2×Q
YWORDY3232256 YMM8×D | 4×Q
ZWORDZ6464512 ZMM16×D | 8×Q
Ostatní datové typy
Jméno typuZkratkaVelikostAutoalign Použití
Jméno_strukturySrůznáExplicitní zarovnání STRUC,
jinak šířka programu
structurované proměnné
INSTRIrůzná1strojové instrukce

Použití fundamentálních typů je často omezeno na jejich první písmeno. Datové typy v plné nebo zkratkové notaci se používají pro explicitní definici pseudoinstrukcí D, pro implicitní definici dat v literálech, jako specifikaci zarovnání ALIGN= a v instrukčních modifikátorech.

€ASM si je částečně vědom datových typů. Například při zpracování strojové instrukce INC [MemoryVariable] se podívá, jak byla MemoryVariable definována a podle toho vybírá příslušné zakódování (byte|word|dword).


↑ Symboly

Jména symbolů ↓

Číselné symboly ↓

Adresní symboly ↓

Symbol $ ↓

Atributy symbolu ↓

Literální symboly ↓

Symbol v asembleru je alias k číslu nebo k adrese.

Rozeznáváme dva druhy symbolů: číselný a adresní.

Číselný symbol odpovídá na otázku kolik? a adresní symbol odpovídá na dotaz kde? (na které pozici v programu).

Číselný symbol je definován pseudoinstrukcí EQU nebo jejím aliasem =, např. Dozen EQU 12 nebo Gross = 144.
Adresní symbol je definován, pokud se jeho jméno objeví v instrukčním poli pro návěstí.

Hodnota číselného symbolu je interně uchovávána v 8 bajtech (signed QWORD), avšak adresní symbol navíc vyžaduje přídavnou informaci o sekci, do níž náleží.
V €ASM nelze definovat numerický symbol jako návěstí jiné instrukce než EQU, nebo jako samostatné návěstí bez pole operace. Každá instrukce patří do nějaké sekce (buď explicitně definované nebo implicitně vytvořené při startu programu.

↑ Jméno symbolu

Jméno symbolu je identifikátor (písmeno nebo tečka volitelně následovaná dalšími písmeny, číslicemi a tečkami), které není rezervovaným jménem symbolu (bez ohledu na velikost písmen).
Název symbolu může být vždy zakončen jednou nebo více dvojtečkami :, což pomáhá jej identifikovat jako jméno symbolu. Dvojtečka není součástí jména symbolu. Symboly by měly mít sebevysvětlovací názvy.

Zakončení názvu každého symbolu dvojtečkou : je dobrý zvyk jak při definování, tak i při odkazování na symbol, třebaže mnoho jiných asemblerů toto nepodporuje. Je pak jednodušší copy&pastovat symbol, aniž bychom museli mazat dvojtečku na konci. Dvojtečka pomáhá asembleru i lidskému čtenáři rozeznat jméno jako symbol a chrání před chybou, pokud bychom zvolili jméno kolidující s některou z tisíců instrukčních mnemonik.
Názvy struktur, registrů (mimo segmentových) nebo názvy strojových instrukcí nikdy dvojtečkou nekončí.
Jméno symbolu musí být v programu unikátní.

Symboly a struktury mohou být referovány (použity v instrukci) ještě dříve, než jsou definovány. Přesto je ale dobrou praxí definovat číselné symboly a struktury na počátku programu, neboť dopředné reference vyžadují přídavné průchody a prodlužují čas kompilace.

Rezervovaná jména symbolů
KategorieRezervované jméno
Aktuální ofset v asm-time$
Názvy segmentových registrůCS, DS, ES, FS, GS, SS
Názvy prefixůATOGGLE, LOCK, OFTEN, OTOGGLE, REP, REPE, REPNE, REPNZ, REPZ, SEGCS, SEGDS, SEGES, SEGFS, SEGGS, SEGSS, SELDOM, XACQUIRE, XRELEASE

Jméno symbolu může obsahovat tečku ., která obvykle spojuje jmenný prostor s lokálním názvem symbolu. Úvodní tečka . činí symbol lokální, jelikož jeho jméno je ve skutečnosti spojeno se současným jmenným prostorem.

Tvorba jmen symbolů kolidující se jmény registrů nebo instrukcí není doporučena. Pokud opravdu potřebujete použít některé z těchto nedoporučených jmen pro svůj symbol, musí je následovat dvojtečka, např.

  Byte: DB 1    ; Definuj symbol se jménem "Byte".
  MOV AX,Byte:  ; Naplň AX ofsetem tohoto symbolu.

V ostatních případech je zakončování jména dvojtečkou : dobrovolné, ale doporučené.

Nedoporučovaná jména symbolů
KategorieNedoporučené jméno
Fundamentální datové typy B, BYTE, D, DWORD, I, INSTR, O, OWORD, Q, QWORD, S, T, TBYTE, U, UNICHAR, W, WORD, Y, YWORD, Z, ZWORD
Názvy registrů AH, AL, AX, BH, BL, BND0, BND1, BND2, BND3, BP, BPB, BPL, BX, CH, CL, CR0, CR2, CR3, CR4, CR8, CX, DH, DI, DIB, DIL, DL, DR0, DR1, DR2, DR3, DR6, DR7, DX, EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP, K0, K1, K2, K3, K4, K5, K6, K7 MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, R10, R10B, R10D, R10L, R10W, R11, R11B, R11D, R11L, R11W, R12, R12B, R12D, R12L, R12W, R13, R13B, R13D, R13L, R13W, R14, R14B, R14D, R14L, R14W, R15, R15B, R15D, R15L, R15W, R8, R8B, R8D, R8L, R8W, R9, R9B, R9D, R9L, R9W, RAX, RBP, RBX, RCX, RDI, RDX, RSI, RSP, SEGR6, SEGR7, SI, SIB, SIL, SP, SPB, SPL, ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, TR3, TR4, TR5, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM16, XMM17, XMM18, XMM19, XMM20, XMM21, XMM22, XMM23, XMM24, XMM25, XMM26, XMM27, XMM28, XMM30, XMM31 YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15, YMM16, YMM17, YMM18, YMM19, YMM20, YMM21, YMM22, YMM23, YMM24, YMM25, YMM26, YMM27, YMM28, YMM30, YMM31 ZMM0, ZMM1, ZMM2, ZMM3, ZMM4, ZMM5, ZMM6, ZMM7, ZMM8, ZMM9, ZMM10, ZMM11, ZMM12, ZMM13, ZMM14, ZMM15, ZMM16, ZMM17, ZMM18, ZMM19, ZMM20, ZMM21, ZMM22, ZMM23, ZMM24, ZMM25, ZMM26, ZMM27, ZMM28, ZMM30, ZMM31
Názvy pseudoinstrukcí ALIGN, D, DB, DD, DI, DO, DQ, DS, DU, DW, DY, DZ, ENDHEAD, ENDP, ENDP1, ENDPROC, ENDPROC1, ENDPROGRAM, ENDSTRUC, EQU, EUROASM, EXTERN, GLOBAL, GROUP, HEAD, INCLUDE, INCLUDE1, INCLUDEBIN, INCLUDEHEAD, INCLUDEHEAD1, PROC, PROC1, PROGRAM, PUBLIC, SEGMENT, STRUC
Mnemonické názvy strojových instrukcíAAA, AAD, ... XTEST, viz IiHandlers v €ASM zdroji pro kompletní seznam.

↑ Číselné symboly

Číselný symbol je definován pseudoinstrukcí EQU nebo jejím aliasem =, který specifikuje prosté číslo, číselný výraz nebo jiný numerický symbol. Příklady:

BufferSize: EQU 16K
WM_KEYDOWN = 0x0100
Total      EQU 2*BufferSize
   MOV ECX,BufferSize
Použití numerického symbolu namísto čísla má své výhody:

↑ Adresní symboly

Adresní symbol je definován, když se vyskytne jako návěstí strojové instrukce nebo prefixu, jako návěstí prázdné instrukce nebo pseudoinstrukce D*, PROC, PROC1.

Příklady:
[DATA]
SomeValue:   DD 4
[CODE]
             MOV EAX,[SomeValue:]
StartOfLoop: CALL SomeProcedure:
             DEC EAX
             JNZ  StartOfLoop:

Zatímco numerický symbol BufferSize byl zcela definován svou hodnotou, v případě adresního symbolu SomeValue to není dostačující. Instrukce MOV EAX,SomeValue plní EAX ofsetem symbolu, tj. vzdáleností jeho pozice od začátku jeho segmentu. Adresní symbol je definován dvěma vlastnostmi: jeho segmentem a jeho ofsetem. Proto se adresnímu symbolu občas říká vector nebo relativní symbol a číselný symbol je nazýván skalár nebo absolutní symbol nebo konstanta.

Symbol lze v EuroAssembleru vytvořit jednou z pěti metod:
  1. Symbol je definován, pokud se jeho jméno vyskytne v poli návěstí. Takový symbol reprezentuje adresu uvnitř segmentu a zároveň i data emitovaná touto instrukcí. Instrukce může být prázdná (pouze návěstí) nebo může deklarovat data, prefix nebo strojovou instrukci. Pseudoinstrukce PROC a PROC1 také definují symbol, avšak pseudoinstrukce PROGRAM, STRUC ani SEGMENT nikoli.
  2. Externí a importované symboly jsou vytvářeny pseudoinstrukcí EXTERN, IMPORT nebo GLOBAL, nebo pokud jsou odkazovány se dvěma dvojtečkami připojenými k jejich jménu. Externí symbol není v programu definován, nesmí se objevit v poli návěstí (s výjimkou pseudoinstrukce EXTERN, která určuje jeho viditelnost).
  3. Literální symbol je vytvořen, když se objeví v programu poprvé. Nemá explicitní jméno, ve skutečnosti je jeho název reprezentován jeho hodnotou. Například instrukční kod LEA ESI,[=D 123] vytváří literální symbol uložený v tabulce symbolů EuroAssembleru pod názvem =D 123.
  4. €ASM udržuje speciální dynamický symbol $ pro každou sekci, který reprezentuje současnou pozici asembleru v sekci.
  5. Symbol může být také definován pseudoinstrukcí EQU nebo jejím aliasem =. To je jediný způsob, jak definovat prostý numerický symbol.

↑ Symbol $

Speciální dynamický symbol $ představuje adresu příští volné pozice v emitovaném kódu na počátku překladu instrukce, v níž je zmíněn. Hodnota tohoto symbolu není konstantní, ale €ASM ji mění jakmile byla instrukce přeložena na strojový kód.

Programátor může měnit současnou hodnotu $ pseudoinstrukcí EQU, to odpovídá pseudoinstrukci ORG známé z jiných asemblerů.

V €ASM není pseudoinstrukce ORG, místo toho lze $ změnit pseudoinstrukcí EQU.
|00000100:44444444 |DataDword DD 0x44444444 |00000104: | ; Předefinování DataDword na unii dvou WORDů: |00000100: | $ EQU DataDword ; Vrať ukazatel emitování zpět. |00000100:1111 |DataLoWord DW 0x1111 ; Znovu emituje odlišná data, |00000102:2222 |DataHiWord DW 0x2222 ; která přepíší původní hodnotu DataDword. |00000104: |

Viz také test t2551 nebo vzorový projekt boot16.


↑ Atributy symbolů, registů a souborů

SIZE# ↓
TYPE# ↓
REGTYPE# ↓
SCOPE# ↓
OFFSET# ↓
SECTION# ↓
SEGMENT# ↓
GROUP# ↓
PARA# ↓
FILESIZE# ↓
FILETIME# ↓

Několik vlastností symbolu zvaných atributy je k dispozici ke zpracování za běhu asembleru. Jakmile je symbol definován, nabývá atributy automaticky. Mohou být testovány přidáním operátoru atributu před jméno symbolu. Operátor atributu je jeho definující identifikátor bezprostředně následovaný znakem #. Objekt, jehož se operátor atributu týká, může být oddělen žádnou nebo několika mezerami a může být v závorkách. Například SIZE#SymbolName nebo SIZE# SymbolName nebo SIZE#(SymbolName). Zapamatujte si, že v názvu symbolu záleží na velikosti písmen, avšak v názvu atributu nikoli.

Atributy GROUP#, SEGMENT# a SECTION# vracejí adresu, pokud jsou aplikovány na adresní symbol a vracejí skalární nulu, jsou-li aplikovány na číselný symbol. Ostatní atributy vždy vracejí skalár (prosté číslo).

↑ OFFSET#

Atribut OFFSET# vrací ofset symbolu v jeho segmentu jako prosté číslo, tj. počet bajtů mezi ním a počátkem jeho segmentu. Je-li symbol číselný, atribut vrací jeho hodnotu.

Symbol a OFFSET#Symbol jsou identické pouze pokud je Symbol skalár, jinak to první představuje jeho adresu a to druhé prosté číslo.

Výraz Symbol - SEGMENT#Symbol je totožný s OFFSET#Symbol jak pro numerický, tak i pro adresní symbol.

↑ PARA#

Atribut PARA# představuje paragrafovou adresu začátku grupy, do níž symbol patří. Je to hodnota, kterou je třeba načíst do segmentového registru použitého k adresování. Je-li PARA# aplikován na numerický symbol, vrací skalární nulu.

↑ GROUP#

Atribut GROUP# reprezentuje adresu začátku grupy, do níž symbol patří, tj. adresu prvního bajtu nejnižšího segmentu grupy. Při aplikování na numerický symbol vrací skalární nulu.

↑ SEGMENT#

Atribut SEGMENT# představuje adresu začátku segmentu, do nějž symbol patří. Při aplikování na numerický symbol vrací skalární nulu.

↑ SECTION#

Atribut SECTION# reprezentuje adresu počátku sekce, do níž symbol patří. Při aplikování na numerický symbol vrací skalární nulu. Pokud symbol leží v defaultní sekci (se jménem stejným jako její segment), jak SECTION# tak i SEGMENT# vracejí totožnou adresu.

↑ SCOPE#

Atribut SCOPE# vrací číslo odpovídající ASCII hodnotě velkého písmene odpovídajícího viditelnosti symbolu. To může být 'E' pro externí symboly, 'P' pro public (veřejné) symboly, 'X' pro exportované symboly, 'I' pro importované symboly, 'S' pro standardní privátní symboly, nebo '?' pokud symbol není deklarován.

↑ SIZE#

SIZE# představuje počet bajtů emitovaných instrukcí definující symbol. Typicky je to velikost dat definovaných pseudoinstrukcí D nebo délka strojové instrukce v bajtech. Symboly definované pseudoinstrukcí EQU nebo definované v neemitující instrukci mají atribut SIZE# rovný nule.

↑ TYPE#

Atribut TYPE# vrací číslo odpovídající ASCII hodnotě velkého písmena korespondujícího s typem objektu. Může to být jeden z fundamentálních datových typů 'B', 'U', 'W', 'D', 'Q', 'T', 'O', 'Y', 'Z', strukturovaný datový typ 'S' nebo strojová instrukce 'I', pokud byl symbol definován datovou pseudoinstrukcí D.
Numerické symboly vracejí hodnotu 'N'.
Návěstí strojové instrukce nebo strojového prefixu vracejí atribut 'I'.
Adresní symbol definovaný samotným návěstím, dále návěstí PROC a PROC1, jakož i externí symbol vrací atribut typu 'A' (jako Adresa).
Nedeklarovaný symbol vrací '?'.

Dopředná reference symbolu o něm vytváří záznam v tabulce symbolů. Nicméně při prvním průchodu je jeho typový atribut '?' (nedeklarovaný) až dokud nebude nalezena jeho definice. Na druhé straně aplikace atributu na nedefinovaný symbol jej nečiní odkazovaným, tedy nezapisuje ho do tabulky symbolů. Proto můžeme testovat přítomnost symbolu v programu pomocí %IF TYPE#Symbol = '?'.

Vedle symbolů může být atribut TYPE# aplikován i na některé jiné objekty: registr, strukturu, řetězec, výraz v závorkách () nebo [].

TYPE# registru je 'R' a jeho SIZE# se rovná šířce registru v bajtech (1,2,4,8,10,16,32,64).

TYPE# struktury je 'S' a SIZE# odpovídá její velikosti v bajtech.

|[.data] |[.data] |00000000:456E642E0D0A00 |Message D 'End.',13,10,0 ; Definováno jako DB or DU. |[.text] |[.text] |TRUE | %IF TYPE# Message = 'B' ; Pokud je UNICODE vypnut, |00000000:B907000000 | MOV ECX,SIZE# Message ; naplň ECX jeho velikostí v bajtech (7). |FALSE | %ELSE ; Jinak je UNICODE zapnut, | | MOV ECX,SIZE#Message/2 ; a SIZE# vrací 14 bajtů. | | %ENDIF ; ECX je nyní 7 (délka Message ve znacích).

Proč používat SIZE# nebo TYPE# na symbol definovaný námi (programátorem), u kterého tedy předem známe jeho velikost a typ? Pokud se později rozhodneme změnit text proměnné Message, nemusíme se obtěžovat přepočítáváním jeho délky.

Operátory atributů jsou často použity v makrech k určení, jakým druhem operandů bylo makro vyvoláno: je-li to registr, datový symbol, přímá hodnota apod. Potřebujeme-li v makru zjistit, zda poskytnutá hodnota %1 je prosté číslo, můžeme to otestovat dotazem %IF TYPE# %1 = 'N'.

Viz testy t16* pro více příkladů na atributy.

Podrobnější diferenciace typu datového symbolu, kterou atribut TYPE# poskytuje, někdy není potřebná. Můžeme například chtít vedět, zda operand makra %1 potřebuje relokaci. K tomu dochází, pokud je operandem adresní symbol nebo paměťová proměnná obsahující adresní symbol. Dotazy na TYPE# DataSymbol nebo TYPE# [DataSymbol+RSI] mohou vracet 'A', 'B','W','D','Q','T' či jakýkoli typ dat, s nímž byl DataSymbol definován. Jinak vrátí 'N', pokud bylo operandem číslo nevyžadující relokaci, jako třeba TYPE# MAX_PATH_SIZE nebo TYPE# [RBP-16]. Zde se bude hodit sjednocení všech druhů adresních a externích symbolů atributovým operátorem SEGMENT#, který vrátí relokabilní adresu počátku segmentu, nezávisle na datatypu symbolu. Atribut TYPE# aplikovaný na takový atribut SEGMENT# pak vždy vrátí hodnotu 'A'. Na druhé straně SEGMENT# ScalarSymbol a TYPE#(SEGMENT#ScalarSymbol) vrací 'N'.

%IF TYPE# (SEGMENT# %1) = 'A'
  ; %1 je adresový výraz vyžadující relokaci.
%ELSE
  ; %1 je nerelokabilní výraz.
%ENDIF
Všimněte si, že zřetězené atributy vyžadují závorky. To je kvůli tomu, že operátory atributů mají shodnou prioritu, takže jsou vyhodnocovány zleva doprava, a bez závorek by se první operátor snažil aplikovat na jiný unární operátor.
Viz test t1695 pro více příkladů.
↑ REGTYPE#

Při aplikaci atributu TYPE# na registr se vrací hodnota 'R', bez ohledu na rodinu registrů. Někdy ale může být užitečné znát přesný druh registru. Atribut REGTYPE# vrací číslo reprezentující ASCII hodnotu velkého písmene odpovídajího rodině registrů. Všeobecné registry (GPR) vracejí 'B', 'W', 'D' nebo 'Q', registry SIMD vracejí 'X', 'Y', 'Z', segmentové registry vracejí 'S' atd. Pro kompletní seznam viz tabulku Registers. Je-li tento atribut aplikován na objekt, který není registr, vrací '?'. Viz také test t1662.

↑ FILESIZE#
↑ FILETIME#

Na rozdíl od předchozích atributů, FILESIZE# a FILETIME# mohou být aplikovány pouze na soubory specifikované jejich jménem, které musí být obklopeno dvojitými uvozovkami ". Název souboru může být absolutní, relativní nebo bez cesty, vztahuje se k aktuálnímu adresáři v asm-time.

Oba atributy zjišťují vlastnosti souboru v čase překladu.

FILESIZE# "filename" vrací počet bajtů v souboru, nebo 0 pokud soubor neexistuje.
FILETIME# "filename" vrací timestamp souboru, tj. počet sekund od půlnoci UTC 1. ledna 1970 k jeho poslední modifikaci. Vrací 0 pokud soubor nebyl naleze. Viz také test t1690.

↑ Literály

Literální symboly neboli literály se podobají standardním symbolům asembleru. Rozdíl je v tom, že jim nemusíme explicitně vymýšlet unikátní jméno. Literál je definován kdykoli je použit a jeho jméno je představováno rovnítkem =, za kterým následuje datový výraz, např. =D(5) nebo =B"Some text.". Data mohou být duplikována, ale na rozdíl od pseudoinstrukce D (která může mít více operandů) zde může být pouze jeden datový výraz. Příklady instrukcí s literály:

DIV [=W(10)]   ; Vyděl číslo v DX:AX anonymní paměťovou proměnnou typu WORD s hodnotou 10.
MOV DX,=B"This is a literal message.$" ; Naplň DX ofsetem řetězce definovaného někde v rodata segmentu.
LEA ESI,[=D 0] ; Naplň ESI adresou paměťové proměnné typu DWORD obsahující hodnotu 0.
CALL =I"RET"   ; Proveď PUSH EIP a pak naplň EIP ofsetem strojové instruce RET definované někde v kódovém segmentu.
LEA EBX,[=D 0,1,2,3] ; Chyba: vícenásobná definice dat.
MOV DX,=B"This is a literal message.",13,10 ; Chyba: vícenásobná definice dat.
První příklad deklaruje proměnnou =W(10). Bez literálů bychom museli nadefinovat datovou proměnnou Ten DW 10 někde v datovém segmentu a přidělit jí explicitní unikátní jméno.

Výhodou literálů je, že jim nemusíme vymýšlet jména a explicitně je deklarovat pseudoinstrukcí D. Datový obsah je viditelný přímo v instrukci, která literál používá.

Literály jsou automaticky zarovnány.

Všechny literály jsou zarovnány podle svých typů, např. =D 5 je zarovnána DWORD bez ohledu na aktuální stav volby EUROASM AUTOALIGN=.

Řetězcové literály jsou automaticky zakončeny znakem NUL.

Řetězcové literály, jako =B"Some text" nebo =U"Some text" jsou vždy implicitně zakončeny BYTE nebo UNICHAR nulou.
€ASM dovoluje zjednodušenou deklaraci neduplikovaných literálních řetězců, kdy typový identifikátor B nebo U je vynechán, např. ="Some text". Konkrétní typ řetězce (B nebo U) je pak určen %proměnnou %^UNICODE nastavovanou pomocí EUROASM UNICODE=ON|OFF.

Definice dat pomocí literálů nedovoluje programátorovi určit přesnou lokaci, kam bude literál emitován. €ASM vytváří služební sekci pro každý typ data v závislosti na jejich přirozeném zarovnání. Sekce pro literály je vytvořena buď

  1. v posledním segmentu, který má PURPOSE=LITERAL a PURPOSE=RODATA|DATA,
  2. nebo pokud žádný segment s účelem LITERAL neexistuje, pak v posledním segmentu s účelem RODATA,
  3. nebo pokud segment s PURPOSE=RODATA neexistuje, pak v posledním segmentu s PURPOSE=DATA,
  4. nebo pokud žádný segment DATA|RODATA neexistuje, vytvoří se implicitní segment s názvem @LT a účelem RODATA+LITERAL.

Jména literálních sekcí jsou [@LT64], [@LT32], [@LT16], [@LT8], [@LT4], [@LT2], [@LT1].
Literály s datatypem INSTRUC, jako třeba =8*I"MOVSD", jsou emitovány do služební sekce [@RT0], která je obdobně vytvořena v segmentu s účelem PURPOSE=CODE+LITERAL, nebo v posledním kódovém segmentu, pokud dosud neexistoval.

Opakovaně použité literály se shodnou deklarací jsou znovupoužity, představují tutéž paměťovou proměnnou. Literály s nikoli doslovnou shodou, jako např. =W+4, =W 4 a =W(2+2) se ukládají zvlášť jako odlišné symboly, ale jejich hodnota je znovupoužita, takže zabírá méně místa v sekci literálů. Podobně literály =B"Some text", =B'Some text' a =B 'Some text' jsou tři odlišné symboly, ale za běhu programu všechny tři dohromady okupují pouhých 9+1 bajtů paměti v literální sekci [@LT1].

Literály by se měly vždy považovat za paměťové proměnné pouze ke čtení.

I když nelze bránit programátorovi v přepisování dat definovaných jako literál, měly by být vždy považovány za read-only, jinak by to mohlo poškodit jinou část programu využívající těchže literálních dat.

Srovnání standardních symbolů a literálů
VlastnostStandardní symbolLiterální symbol
DeklaraceDefinovaný explicitně pseudoinstrukcí D či jejími klony, např. Dozen: DD 12 Deklarovaný při jeho prvním využití v instrukci, např. MOV ECX,=D 12
JménoProgramátor musí symbolu určit unikátní název. Název literálu je vytvořen automaticky z jeho hodnoty.
Umístění v cílovém kóduUmístění dat symbolu je zcela v režii programátora. Programátor nemůže přímo ovlivňovat jeho umístění.
AlignmentJe-li zarovnání požadováno, musí být vyždáno explicitně pseudoinstrukcí ALIGN nebo modifikátorem ALIGN= nebo volbou EUROASM AUTOALIGN=ENABLED. Literály jsou vždy přirozeně zarovnány, jako by byla platná volba EUROASM AUTOALIGN=ENABLED.
Náplň zarovnáníKvůli minimalizaci náplně pro zarovnávání by měl být programátor opatrný při míchání proměnných s rozličnými velikostmi. Literály všech velikostí jsou spojeny dohromady v klesajícím pořadí jejich velikostí, což automaticky minimalizuje náplň mezi nimi.
Vícenásobné operandy Pseudoinstrukce D a její klony podporují vícenásobné operandy, např. Hello DB "Hello, world",13,10,'$'. Vícenásobné operandy nejsou přípustné.
Zakončování nulouPouze na explicitní žádost, např. Hello: DU "Hello, world",0. Automaticky, např. MOV ESI,=U "Hello, world".
DuplikacePodporována, např. FourDoublePrecOnes: DY 4 * Q 1.0 Podporována, např. VMOVUPD YMM7, [= 4 * Q 1.0].
Přepisování hodnotyPřípustné podle potřeby.Programátor by se ho měl vyvarovat.

↑ Struktury

Struktura je deklarována zdrojovým kódem reprezentovaným blokem STRUC..ENDSTRUC. V bloku budou deklarovány názvy, datové typy, velikosti a ofsety členů struktury. V terminologii objektového programování je struktura třídou (class) a strukturovaná paměťová proměnná objektem. Příklad:

DATUM STRUC           ; Deklarace struktury DATUM.
 .Year  D W
 .Month D B
 .Day   D B
      ENDSTRUC DATUM

Today DS DATUM        ; Definice strukturované paměťové proměnné Today.
Členové struktury by měli mít lokální jména (začínající tečkou .). Deklarace struktury definuje blok jmenného prostoru.

Ve výše uvedeném příkladu struktura DATUM tvoří symboly DATUM.Year, DATUM.Month, DATUM.Day s hodnotami 0, 2, 3. Tyto symboly jsou absolutní (skaláry) a dávají jména relativním ofsetům členů struktury.

Definice Today vytváří strukturovanou paměťovou proměnnou. Současně jsou vytvořeny symboly Today.Year, Today.Month, Today.Day. Jejich adresy jsou definovány někde v sekci [DATA] nebo [BSS], nejsou to skaláry, nýbrž relokabilní adresy.

Hodnoty členů jsou nedefinovány (pokud byla strukturovaná proměnná definovaná v segmentu [BSS]), anebo obsahuje samé nuly (pokud byla definovaná v segmentu [DATA]). Členové strukturované proměnné mohly být definovány staticky v asm-time klíčovými operandy, například Today DS Datum, .Day=31, viz též pseudoinstrukci DS. Při definování paměťové proměnné je v poli operandů dočasně platný jmenný prostor instrukce, viz zde.

Člen strukturované proměnné může být změněn přímo, pomocí

MOV [Today.Month],12

Rovněž bychom mohli použít registr ukazující na celou strukturovanou proměnnou a využít tento registr k adresaci individuálních členů s relativními ofsety specifikovanými v deklaraci struktury:

 MOV EDI,Today
 MOV [EDI+DATUM.Month],12

Více o strukturách viz zde.


↑ %Proměnné

Uživatelem definované %proměnné ↓

Formální %proměnné ↓

Automatické %proměnné ↓

Systémové %proměnné ↓

Program v €ASM může používat preprocesní proměnné neboli %proměnné k manipulaci se zdrojovým textem v asm-time. Spolu s makroinstrukcemi tvoří mocný aparát šetřící opakující se programátorskou práci. Preprocesní aparát neovlivňuje cílový kód přímo, tak jak to dělá prostý asembler. Namísto toho manipuluje se zdrojovým textem, který může být modifikován %proměnnými a opakován preprocesními %pseudoinstrukcemi.

Preprocesní proměnné považují svůje obsah za sekvenci znaků, bez zkoumání jejich syntaktického významu.

Jakmile byl nastaven, může být obsah %proměnné použit (expandován) kdykoli se %proměnná vyskytne ve zdrojovém textu (s výjimkou komentářů). K expanzi dochází dříve, než je zdrojový řádek rozebrán na pole instrukce. Ve výchozím stavu je expandován celý obsah %proměnné, avšak může být omezen operátory substring a sublist.

Viz také €ASM funkci Předzpracování.

Rodiny preprocesních %proměnných
Rodina %proměnných ►Uživatelem definované FormálníAutomatické   Systémové
EUROASMPROGRAM€ASM
forma názvu%identifikátor%identifikátor%speciální_znak %^volba%^volba%^pevný
citlivost na velikost písmen v názvuAnoAnoAnoNeNeNe
Znovupřiřaditelnostexplicitně
pomocí %SET*
nepřímo v expanzi smyčky %FOR nebo makra nepřímo expanzí makra nepřímo pomocí
parametru EUROASM
nepřímo pomocí
parametru PROGRAM
Ne

↑ Uživatelem definované %proměnné

Jméno uživatelem definované %proměnné je tvořeno znakem procenta % následovaného identifikátorem, který není rezervovaným názvem %proměnné, bez ohledu na velikost písmen. Identifikátor musí začínat písmenem a nemůže obsahovat tečku ani jiné speciální znaky.

V uživatelem definovaném jménu %proměnné záleží na velikosti písmen.
Rezervovaná jména %proměnných
KategorieRezervované jméno
Pseudoinstrukce %COMMENT, %DEBUG, %DISPLAY, %DROPMACRO, %ELSE, %ENDCOMMENT, %ENDFOR, %ENDIF, %ENDMACRO, %ENDREPEAT, %ENDWHILE, %ERROR, %EXITFOR, %EXITMACRO, %EXITREPEAT, %EXITWHILE, %FOR, %IF, %MACRO, %PROFILE, %REPEAT, %SET, %SET2 %SETA, %SETB, %SETC, %SETE, %SETL, %SETS, %SETX, %SHIFT, %UNTIL, %WHILE

Uživatelsky definované %proměnné jsou přiřazeny nebo vytvářeny programátorem pomocí jedné z rodiny pseudoinstrukcí %SET*.

%Proměnné mohou být později přiřazovány odlišnou hodnotou, nemusejí být unikátní v rámci programu.

Viditelnost uživatelem definovaných %proměnných začíná jejich prvním přiřazením a končí na konci zdrojového souboru.

%Proměnné nemusejí být přiřazeny před prvním použitím (expanzí). Nepřiřazené %proměnné expandují do ničeho (prázdný text). Jednou přiřazenou %proměnnou nelze odřadit, v €ASM neexistuje direktiva %UNSET, UNDEFINE nebo UNASSIGN. Nicméně přiřazení prázdné hodnoty (např. %SomeVar %SET) je ekvivalentní jejímu odřazení. €ASM nehlásí žádnou chybu, setká-li se s uživatelsky definovanou %proměnnou, která je prázdná, která nebyla přiřazena dříve nebo která dosud nebyla ve zdrojovém textu vůbec zmíněna.

Viz také test t7321.

Rozdíly mezi symboly a %proměnnými
SymbolyUživatelem definované %proměnné
jsou vlastností PROGRAMu jsou vlastností EuroAssembleru
jejich název nikdy nezačíná % jejich název vždy začíná %
mohou mít v názvu tečku nikdy nemají tečku v názvu
jsou deklarovány v poli návěstí jsou přiřazovány pomocí pseudoinstrukcí %SET*
mají atributy, jako TYPE# a SIZE# jsou prosté kusy textu bez atributů
mohou být zmiňovány dopředu nemohou být zmiňovány dopředu
musí být definovány právě jednou v programu mohou být mnohokrát redefinovány
nemohou být odkazovány, nebyly-li deklarovány mohou být zmiňovány bez deklarace
nemohou být předmětem operací sublist nebo substring mohou být sublistovány a substringovány

↑ Formální %proměnné

Formální %proměnná expanduje na hodnotu řídicího parametru smyčky %FOR anebo na hodnotu operandu v invokaci %MACRO. Je reprezentována identifikátorem stojícím v poli návěstí příkazu %FOR, nebo stojícím jako operand v prototypu %MACRO.

Viditelnost formální %proměnné je omezena na expandovaný blok.

Count %FOR 1..8
        DB %Count
      %ENDFOR Count

Předchozí příklad generuje osm instrukcí DB, které definují bajtové hodnoty 1 až 8. Identifikátor Count použitý v příkazech %FOR a %ENDFOR je řídicí %proměnná, a je dostupná uvnitř %FOR..%ENDFOR bloku jako formální %proměnná %Count.

Formální %proměnné se rovněž používají k přístupu k pojmenovaným operandům makra během jejich expanze. V dalším příkladu máme dvě formální %proměnné makroinstrukce definované v definici %MACRO jako identifikátory Where a Stuff. V těle makra jsou jejich hodnoty dostupné jako formální %proměnné %Where a %Stuff.

Fill %MACRO Where, Stuff=0   ; Definice makra Fill.
       MOV %Where,%Stuff
     %ENDMACRO Fill

; Volání (expanze) makra Fill:
   Fill [Counter], Stuff=255 ; Bude přeloženo jako MOV [Counter],255
   Fill EBX                  ; Bude přeloženo jako MOV EBX,0

Všimněte si, že formální %proměnné se píší bez znaménka procent když jsou deklarovány, avšak % musí být předřazeno jejich jménu když jsou referovány v těle příkazů %FOR nebo %MACRO. Toto je důležité pro dědění argumentů ve vnořených a rekurzivně volaných makroinstrukcích, viz např. t7233.

Viditelnost formálních proměnných má uvnitř bloku vyšší prioritu než uživatelem definované %proměnné téhož jména, bez ohledu, zda byly přiřazeny vně nebo uvnitř bloku %FOR..%ENDFOR či %MACRO..%ENDMACRO. Přiřazení nové hodnoty %proměnné s formálním jménem uvnitř makrobloku sice přiřadí tuto novou hodnotu uživatelem definované proměnné, avšak uvnitř makrobloku formální %proměnná převáží, viz test t7347 nebo t7362. Po odchodu z makra bude přiřazená %proměnná opět viditelná.


↑ Automatické %proměnné

Automatické preprocesní %proměnné jsou tvořeny a udržovány EuroAssemblerem v čase překladu, jejich názvy obsahují speciální znaky a na rozdíl od uživatelsky definovaných %proměnných jejich hodnota nemůže být měněna pomocí pseudoinstrukcí %SET.

Mají rovněž omezené Scope, jejich použití mimo svou viditelnost vede k chybě.

%&

Suboperace velikost a suboperace délka (procento následované ampersandem) %& reprezentuje počet znaků nebo počet položek v seznamu nebo počet fyzických řádků v suboperovaném objektu.
Jeho viditelnost – scope je omezena na suboperační závorky [ ] nebo { }.

Automatická suboperační proměnná %& se tvoří, když expanze vkládaného souboru nebo jiné %proměnné používá suboperace.

Jakmile je k %proměnné nebo ke jménu souboru připojen substring operátor [ ], automatická %proměnná %& může být použita uvnitř hranatých závorek, např. [1..%&], a představuje počet bajtů v expandované proměnné nebo ve vkládaném souboru.
Pokud jsme například přidělili %proměnné pět písmen pseudoinstrukcí %Proměnná %SET ABCDE, pak její velkost je 5 a povel DB "%Proměnná[4..%&]" bude expandovat na DB "DE".

Je-li k názvu proměnné připojen operátor sublist (pomocí složených závorek { }), obsah této %proměnné se považuje za pole čárkou oddělených položek a %& reprezentuje jejich počet, tj. pořadové číslo poslední neprázdné položky.
Například pokud bylo nastaveno %Reglist %SET ax,cx,dx,bx,bp, jeho délka je 5 operandů (položek) a instrukce MOV %Reglist{3},%aReglist{%&} se přeloží jako MOV dx,bp.

Pokud je tentýž operátor { } připojen k názvu vkládaného (INCLUDE) souboru, obsah souboru je považován za seznam fyzických řádků a %& reprezentuje počet řádků v souboru. Například INCLUDE "file.inc"{%&-10 .. %&} vloží do zdrojového textu posledních deset řádků z "file.inc".

Použití %proměnné %& mimo závorky by vedlo k chybě.

Indexy suboperací sahají od 1 do %&.
%.

Počitadlo expanzí (procento následované tečkou) %. udržuje dekadické číslo inkrementované EuroAssemblerem při každé expanzi preprocesního bloku a může být využito ke tvorbě unikátních návěstí v opakovaných blocích.
Jeho viditelnost – scope je omezena na tělo preprocesního bloku %MACRO, %FOR, %WHILE, %REPEAT. Pokud je použito mimo tyto bloky, expanduje na 0, viz test t7362.

Je-li v makru nebo bloku %FOR, %WHILE, %REPEAT použito standardní nebo lokální návěstí, a pokud je makro či blok expandováno více než jednou, symbol z návěstí by byl definován více než jednou, což asembler považuje za chybu. Unikátnosti takového symbolu lze dosáhnout začleněním počitadla expanzí do jeho názvu.

Viz příklad makra AbortIf níže. Návěstí Skip je následováno %., což dává symbol Skip%. expandující na Skip1 a v budoucnu expandující na Skip2 při dalším vyvolání makra AbortIf.

|00000008: | | |AbortIf %MACRO Condition=, Errorlevel=1 ; Definice makra AbortIf. | | J%!Condition Skip%.: ; Použij invertovaný kód k přeskočení aborce. | | PUSH %Errorlevel ; Připrav operand pro invokaci API. | | CALL ExitProcess:: ; Windows API pro ukončení programu. | |Skip%.: ; Návěstí, kde program pokračuje. | | %ENDMACRO AbortIf |00000008: | |00000008: | ; Příklad podmíněného zrušení: | | EUROASM ListMacro=Yes, ListVar=Yes ; Zobrazuj expandované instrukce. |00000008:833D[04000000]00 | CMP [Something],0 ; Otestuj podmínku a pak vyvolej makro. |0000000F: | AbortIf Condition=E, Errorlevel=8 ; Program skončí, pokud Something je nulové. | +AbortIf %MACRO Condition=, Errorlevel=1 ; Definice makra AbortIf. |0000000F:7507 + J%!Condition Skip%.: ; Použij invertovaný kód k přeskočení aborce. | !JNE Skip1: |00000011:6A08 + PUSH %Errorlevel ; Připrav operand pro invokaci API. | !PUSH 8 |00000013:E8(00000000) + CALL ExitProcess:: ; Windows API pro ukončení programu. |00000018: +Skip%.: ; Návěstí, kde program pokračuje. | !Skip1: | + %ENDMACRO AbortIf |00000018: | ; Pokračování programu, nebyl-li ukončen.
Automatická %proměnná %. pomáhá vytvářet unikátní jména symbolů.

Všechny následující automatické %makroproměnné mají viditelnost – scope omezenu na tělo bloku %MACRO..%ENDMACRO. Odkazují na operandy použité, když bylo makro vyvoláno (expandováno).

%:

Je-li při vyvolání makra použito návěstí (label), je ve výchozím stavu umístěno k první expandované instrukci. Toto chování lze přepsat použitím automatické %makroproměnné %: (procento následované dvojtečkou) deklarované někde uvnitř definice makra. Pouze jedno takové návěstí může být deklarováno v makru. Přemístění návěstí makra k tomuto návěstí může ušetřit několik taktů při skoku přes instrukce kódu, který by musel být přeskočen, viz tento příklad:

SaveCursor %MACRO Videopage=BH
   %IF TYPE#CursorSave != 'W' ; Pokud paměťová proměnná CursorSave dosud nebyla definována.
     JMP %:                   ; Přeskoč na +4 (pod DW 0) pokud bylo makro vloženo do toku instrukcí.
     CursorSave DW 0          ; Prostor k uložení kurzoru.
   %ENDIF
%: MOV AH,3                   ; Vstupní bod makra, kam by se jinak skákalo.
   MOV BH,%Videopage
   INT 10h                    ; Načti tvar kurzoru pomocí BIOS API.
   MOV [CursorSave],CX
 %ENDMACRO SaveCursor
  ...
Save: SaveCursor Videopage=0  ; Použij makro v programu.
  ...
  JMP Save:                   ; Skočí na instrukci MOV AH,3.
Automatická %proměnná %: reprezentuje "vstupní bod" makra.

Viz také test t7215.

%1

Pořadový operand makra může být odkazován číslem. Na rozdíl od dávkových souborů pro DOS a Windows jejich počet není omezen na 9, ale může být libovolné pozitivní číslo, např. %11. Samozřejmě, pokud jedenáctý operand není specifikován při volání makra, %11 expanduje do prázdna.
Viz také pseudoinstrukci %SHIFT.

Automatická %proměnná %0 expanduje jméno samotného makra.

%Formal

Další metoda, jak odkazovat na operand makra (pořadový i klíčový) je předřazení znaku procenta formálnímu názvu operandu.

%!1 nebo %!Formal

Pokud je pořadovému číslu operandu nebo názvu formálního operandu předřazen znak pro logický operátor NOT (vykřičník !), expanduje na invertovaný podmínkový kód ordinálního operandu. To vyžaduje, aby referovaný operand skutečně obsahoval zkratku podmínkového kódu (nezávisle na velikosti písmen) jako např. E, NE, C atd. Obsah operandu bude nahrazen odpovídajícím invertovaným kódem. €ASM ohlásí chybu, pokud by operand neobsahoval platný podmínkový kód.

NASM používá ke stejné funkcionalitě operátor unary-minus -. Věřím, že operátor logical-not ! je vhodnější k inverzi logické hodnoty.

Viz makroAbortIf výše jako příklad.

%*

Seznam pořadových operandů %* (procento následované hvězdičkou) je naplněn všemi pořadovými operandy z volání makra. Operandy jsou odděleny čárkou. Klíčové operandy jsou z listu vyřazeny.

Operandy makra mohou být referovány více metodami. Následující příklad demonstruje tři z nich:

CopyStr %MACRO FirstOp, SecondOp, ThirdOp ; Prototyp makra.
          MOV ESI,%FirstOp ; Použij formální název operandu.
          MOV EDI,%2       ; Použij pořadové číslo operandu.
          MOV ECX,%*{3}    ; Použij třetí položku seznamu operandů.
          REP MOVSB
        %ENDMACRO CopyStr
          ...
        CopyStr Source, Dest, SIZE# Dest ; Vyvolání makra.
%#

Délka seznamu pořadových operandů (pořadové číslo posledního neprázdného operandu) je nastaveno do automatické %proměnné počtu ordinálů %# (procento následované znakem #) a představuje počet pořadových operandů při volání makra (ne počtu deklarovaného v prototypu makra).

Stejná hodnota by také mohla být získána pomocí %NrOfOrdinals %SETL %*.
%=*

Seznam klíčových operandů %=* se podobá automatické %proměnné %*, avšak obsahuje pouze čárkou oddělené operandy klíč=hodnota aktuálně použité v invokaci makra.

Obě %proměnné %* a %=* mohou být použity k výrobě klonů maker s odlišnými názvy:

copystr %MACRO
          CopyStr %*, %=*
        %ENDMACRO copystr

Toto vytváří kopii předtím definovaného makra CopyStr avšak s odlišným názvem copystr. Všechny operandy použité při invokaci makra copystr budou předány doslova původnímu makru CopyStr.

%=#

Délka seznamu klíčových operandů %=# reprezentuje počet klíčových operandů aktuálně použitých v invokaci makra (nikoli počtu deklarovanému v prototypu makra).
Viz též t7364.

Stejná hodnota by také mohla být získána pomocí %NrOfKeys %SETL %=*.

↑ Systémové %proměnné

EUROASM systémové %^proměnné ↓
PROGRAM systémové %^proměnné ↓
€ASM systémové %^proměnné ↓

EuroAssembler udržuje sbírku preprocesních %^proměnných s hodnotami konfiguračních parametrů. Jejich hodnoty mohou být zjišťovány v asm-time.

Název systémové proměnné sestává z %^ (procento a caret) následovaný jedním z výčtových identifikátorů.

U systémových %^proměnných nezáleží na velikosti písmen.

Hodnota systémové %^proměnné nemůže být přiřazena pseudoinstrukcemi %SET*; je dynamicky udržována EuroAssemblerem a odpovídá současné platné hodnotě konfiguračního parametru.

%^DumpWidth %SETA 32 ; Použijte EUROASM DumpWidth=32.
Systémové %^variables jsou pouze ke čtení.

Programátor je může ovlivňovat pouze nepřímo, pomocí volby specifikované v konfiguračním souboru euroasm.ini nebo pomocí pseudoinstrukcí EUROASM a PROGRAM.

Systémové preprocesní %^proměnné
KategorieNázvy %^proměnných (case insensitive)
EUROASM %^AES, %^AMD, %^AutoAlign, %^AutoSegment, %^CET, %^CodePage, %^CPU, %^CYRIX, %^D3NOW, %^Debug, %^DisplayEnc, %^DisplayStm, %^Dump, %^DumpAll, %^DumpWidth, %^EVEX, %^FPU, %^ImportPath, %^IncludePath, %^Interpreter, %^Linkpath, %^List, %^ListFile, %^ListInclude, %^ListMacro, %^ListRepeat, %^ListVar, %^LWP, %^MaxInclusions, %^MaxLinks, %^MMX, %^MPX, %^MVEX, %^NoWarn, %^Profile, %^Prot, %^Prov, %^RunPath, %^RTF, %^RTM, %^SHA, %^SIMD, %^Spec, %^SVM, %^TBM, %^TimeStamp, %^TSX, %^Undoc, %^Unicode, %^VIA, %^VMX, %^Warn, %^XOP,
PROGRAM %^DllCharacteristics, %^Entry, %^FileAlign, %^Format, %^IconFile, %^ImageBase, %^ListGlobals, %^ListLiterals, %^ListMap, %^MajorImageVersion, %^MajorLinkerVersion, %^MajorOSVersion, %^MajorSubsystemVersion, %^MaxExpansions, %^MaxPasses, %^MinorImageVersion, %^MinorLinkerVersion, %^MinorOSVersion, %^MinorSubsystemVersion, %^Model, %^OutFile, %^SectionAlign, %^SizeOfHeapCommit %^SizeOfHeapReserve, %^SizeOfStackCommit, %^SizeOfStackReserve, %^StubFile, %^Subsystem, %^TimeStamp, %^Width, %^Win32VersionValue,
€ASM %^Date, %^EuroasmOs, %^Pass, %^Proc, %^Program, %^Section, %^Segment, %^SourceExt, %^SourceFile, %^SourceLine, %^SourceName, %^Time, %^Version,
↑ EUROASM systémové %^proměnné

jsou přiřazeny hodnotami specifikovanými v sekci [EUROASM] souboru euroasm.ini nebo pseudoinstrukcí EUROASM.

Pro popis %^proměnných této kategorie viz příslušný klíč pseudoinstrukce EUROASM.

↑ PROGRAM systémové %^proměnné

jsou přiřazeny hodnotami specifikovanými v sekci [PROGRAM] souboru euroasm.ini nebo pseudoinstrukcí PROGRAM.

Pro popis %^proměnných této kategorie viz příslušný klíč pseudoinstrukce PROGRAM.

↑ €ASM systémové %^proměnné

Hodnota těchto %^proměnných je udržována samotným €ASM a programátor je nemůže přímo měnit. Jsou popsány zde:

%^Version
Osm dekadických číslic identifikuje verzi EuroAssembleru. Číslo verze lze dešifrovat jako datum vydání euro;ASM ve formátu YYYYMMDD.
%^Date, %^Time
Aktuální datum a čas překladu ve formátu YYYYMMDD, HHMMSS. Tyto dvě proměnné jsou nastaveny pouze jednou když €ASM startuje. Všechny zdrojové soubory přeložené jedním povelem euroasm source*.asm budou sdílet stejnou hodnotu %^Date a %^Time nastavené z lokálního času počítače, když byl euroasm.exe spuštěn.
%^EuroasmOs
identifikuje operační systém, na kterém EuroAssembler běží. Obsahuje zkratku OS jako Win nebo Lin.
To nemusí nezbytně být operační systém, na němž by měl běžet výstupní program.
%^SourceFile, %^SourceName, %^SourceExt
Tyto tři %^proměnné obsahují plné jméno zdrojového souboru včetně cesty , samotné jméno souboru bez cesty a přípony, a konečně příponu (včetně vedoucí tečky .) aktuálně překládaného souboru. €ASM aktualizuje obsah těchto %^proměnných na začátku překladu a vždy když je vkládán (INCLUDE) nějaký soubor.
Jsou-li tyto %^proměnné užity v makru, namísto pozice uvnitř definice těla makra určují pozici v jeho invokaci.
%^SourceLine
obsahuje číslo fyzického řádku v rámci aktuálního zdrojového souboru.
V mnohořádkových instrukcích (s pokračovacími řádky \) je to poslední fyzický řádek.
Je-li použita %^SourceLine v makru, namísto pozice uvnitř definice makra určuje pozici v jeho invokaci.
%^Pass
expanduje na číslo průchodu (1, 2, 3,,,) aktuálním programem.
%^Program
obsahuje název současného bloku PROGRAM..ENDPROGRAM.
%^Proc
je jméno aktuální procedury. Tato %^proměnná je prázdná mimo bloky PROC..ENDPROC nebo PROC1..ENDPROC1.
%^Segment
je název aktuálního segmentu (bez hranatých závorek).
%^Section
je název aktuální sekce (bez složených závorek).

Kombinace €ASM systémových %^proměnných je interně použita k identifikaci pozice instrukce v chybových oznámeních: "%^SourceName%^SourceExt"{%^SourceLine}, např. "HelloWorld.asm"{3}

€ASM %^proměnná %^Section může být použita k úschově a obnově aktuální sekce a segmentu v makrech. Spolu s instrukcí EUROASM PUSH zaručuje, že prostředí EuroAssembleru nebude modifikováno expanzí makra, ani když je makro požadovalo změnit.

aMacro %MACRO              ; Deklarace makra potřebujícího emitovat do své privátní sekce.
         EUROASM PUSH      ; Ulož všechny volby EUROASM na jeho vlastní zásobník.
%BackupSec %SET %^Section  ; Ulož aktuální jméno sekce do uživatelsky definované proměnné.
[.MacroPrivateSection]     ; Přepni do makrem požadované sekce.
               ...         ; Deklaruj tělo makra.
[%BackupSec]               ; Přepni zpět do origináoní sekce, ať už byla jakákoli.
         EUROASM POP       ; Obnov volby EUROASM.
        %ENDMACRO aMacro

Jiný příklad použití €ASM %^proměnných:

%MonthList %SET Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
%Day %SETA %^DATE[7..8] ; Použití %SETA místo %SET plní %Day dekadickou hodnotou, aby se zbavila vedoucí nepodstatné nuly.
InfoMsg DB "This program was assembled with €ASM %^EuroasmOs ver.%^Version",13,10
        DB "on %MonthList{%^Date[5..6]} %Day-th, %^Date[1..4] at %^Time[1..2]:%^Time[3..4].",13,10,0
; InfoMsg nyní obsahuje něco jako
;           This program was assembled with €ASM Win ver.20081231
;           on Feb 8-th, 2009 at 22:05.

Výčtovým volbám, jako %^CPU, %^FORMAT, %^MODEL atd. bude přiřazen text s velkými písmeny. Mohou být testovány v asm-time pomocí operací pro porovnávání řetězců.

Číselným volbám jsou přiřazovány hodnoty v desítkovém zápisu. Pozitivní znaménko + se vynechává. Mohou být testovány pomocí operací porovnávání čísel.

Booleovské volby, např. AutoSegment=, Priv= atd., jsou přiřazovány odpovídajícícm systémovým %^proměnným %^Autosegment, %^Priv jako 0 (nepravda) nebo -1 (pravda), bez ohledu na to, zda byly specifikovány pomocí výčtových hodnot ON/OFF, YES/NO, TRUE/FALSE nebo logickým výrazem. Mohou být testovány pomocí logických výrazů anebo přímo jako operand %IF, např. %IF %^UNDOC.

Rozsahové volby EUROASM WARN= and NOWARN= jsou přiřazeny systémovým %^proměnným %^Warn, %^NoWarn jako řetězy 3999 číslic 0 (nepravda) nebo 1 (pravda). První číslice odpovídá momentálnímu stavu oznámení č. I0001, druhá č. I0002, poslední č. W3999.
Příklad: %IF %^WARN[2820] bude překládat následnou instrukci pouze pokud je oznámení W2820 povoleno.

Systémové %^proměnné mohou být využity v makrech k varování, že prostředí EuroAssembleru není nastaveno tak, jak je potřeba. Příklady:

 %IF "%^MODEL" !== "FLAT"
    %ERROR Macro "%0" is intended for flat memory model only.
 %ENDIF
 %IF %^SizeOfStackCommit < 16K
    %ERROR This recursive macro requires stack size at least 16 KB.
 %ENDIF
 %IF %^Width = 64 && ! %^AMD
    %ERROR This 64-bit program for MS-Windows should have AMD=Enabled.
 %ENDIF
 %IF %^NoWarn[2101]
    %ERROR You shouldn't suppress W2101. Move unused symbols to an included file instead.
 %ENDIF

↑ Instrukce

Strojové instrukce ↓

Pseudoinstrukce ↓

Makroinstrukce ↓

Instrukce je identifikátor specifikovaný v poli operace asemblovaného řádku.

V asembleru rozeznáváme tři rody instrukcí:
strojové instrukce vytvořené výrobcem CPU,
pseudoinstrukce vytvořené výrobcem asembleru,
makroinstrukce vytvořené programátorem.


↑ Strojové instrukce

Instrukční přípony ↓

Instruční modifikátory ↓

Vylepšení instrukcí ↓

Nedokumentované instrukce ↓

Strojová instrukce je nejelementárnější příkaz procesoru, aby provedl nějakou kalkulaci nebo jinou manipulaci s daty za běhu programu.

EuroAssembler používá Intelskou syntaxi, kde první operand určuje cíl (což je často zároveň jeden ze zdrojových operandů), za nímž může následovat druhý operand – zdroj.

Tato syntaxe se používá v dokumentaci výrobců CPU a je použita i u většiny asemblerů, s výjimkou v Unixu používaného gas, který preferuje alternativní paradigma představovaného syntaxí AT&T s přehozeným pořadím operandů. Více rozdílů mezi syntaxí AT&T a Intel je popsáno v [ATTsyntax].

EuroAssembler implementuje mnemoniku strojových instrukcí jak byly definovány výrobci procesorů. Rovněž implementuje několik nedokumentovaných instrukcí a rozšíření, které budou popsány níže.

Strojové instrukce a jejich přípony jsou nezávislé na velikosti písmen.

Některé strojové instrukce dovolují alternativní kódování stejné mnemoniky, €ASM preferuje to kratší, nebyl-li instruován jinak.
€ASM respektuje menmoniku zvolenou programátorem, proto nikdy nekóduje třeba LEA ESI,[MemoryVariable] jako MOV ESI,MemoryVariable, i když je druhý zápis o jeden bajt kratší. Jsou pouze dvě výjimky, kdy není mnemonika dodržena:

Instrukční přípony ↓

Strojová instrukce může manipulovat s registry a paměťovými proměnnými různé šířky, obvykle s operandy typu BYTE, WORD nebo DWORD. Avšak výrobce CPU definoval pro instrukce stejnou mnemoniku bez ohledu na šířku dat. Tak například SUB [MemoryVariable],4 říká CPU, aby odečetl číslo 4 od obsahu MemoryVariable, které mohlo být definováno jako DB, DW, DD nebo DQ. €ASM se podívá na typ MemoryVariable a vybere odpovídající zakódování odpovídající tomuto typu. Ovšem ofset mohl být rovněž vyjádřen jako obsah registru nebo jako prosté číslo, např. SUB [ESI],4, a typ proměnné je pak neznámý. Jednou z metod jak sdělit EuroAssembleru, jaká šířka dat je žádoucí, je použití instrukční přípony, což je jedno z písmen B W D Q S N F připojené k mnemonickému názvu instrukce.

€ASM dovoluje rozšiřovat mnemonickou příponou B, W, D, Q mnoho instrukcí se všeobecným účelem.

Instrukce pro předávání zpracování CALL, JMP, RET mohou být modifikovány příponou N nebo F oznamující asembleru, zda je vzdálenost cíle NEAR nebo FAR, tj. zda cíl patří do téhož segmentu nebo zda se jeho deskriptor má také měnit. Instrukce pro nepodmíněný skok JMP může být rovněž doplněna příponou S, je-li vzdálenost cíle zakódovatelná v 8 bitech (-128..+127).

Instrukce €ASM akceptující příponuPřípona
ADC, ADD, AND, CMP, CMPS, CRC32, DEC, DIV, IDIV, IMUL, INC, LODS, MOV, MOVS, MUL, NEG, NOT, OR, RCL, RCR, ROL, ROR, SAL, SAL2, SAR, SBB, SCAS, SHL, SHR, STOS, SUB, TEST, TEST2, XOR B, W, D, Q
BT, BTC, BTS, BTR, ENTER, HINT_NOP, IRET, LEAVE, POP, POPF, PUSH, PUSHF W, D, Q
PUSHA, POPAW, D
INS, MOVSX, MOVZX, OUTSB, W, D
XLATB
CALL, RETN, F
JMPS, N, F

Použití přípony je v mnoha případech zbytečné, neboť šířka paměťové proměnné může být odvozena z jeho atributu pro typ anebo je šířka určena šířkou registru použitého jako jeden z operandů. Pokud je šířka registru v konfliktu s příponou, ohlásí se chyba, např. v MOVW AL,[ESI].

Přípona je sporadicky použita i v jiných asemblerech, viz např. STOSB/W/D, OUTSB/W/D, RETN/F apod. €ASM pouze důsledně rozšiřuje toto vylepšení.

Mnemoniky mnoha instrukcí pro SIMD končí písmeny ~SS, ~SD, ~PS, ~PD rovněž specifikujícími typy operandů (Scalar/Packed Single/Double-precision). €ASM však toto nepovažuje za přípony instrukcí.

Existuje několik konfliktů mnemoniky s příponou s jinou instrukcí, jsou však řešitelné pomocí typu a počtu operandů:

|00000000: | ; Standardní MOV versus MMX Move Doubleword: |00000000:C7450800000000 | MOVD [EBP+8],0 ; Ulož číslo do paměťové proměnné typu DWORD (přípona ~D). |00000007:0F7E4508 | MOVD [EBP+8],MM0 ; Ulož DWORD z registru MMX do paměti. |0000000B: | |0000000B: | ; Posun SHL versus Double Precision Shift: |0000000B:C1650804 | SHLD [EBP+8],4 ; Posuň DWORD v paměti logicky vlevo o 4 bity (přípona ~D). |0000000F:0FA4450804 | SHLD [EBP+8],EAX,4 ; Vysuň 4 bity z registru EAX doleva do pamětové proměnné. |00000014: | |00000014: | ; Porovnej řetězce versus Porovnej skalární FP číslo s dvojitou přesností: |00000014:A7 | CMPSD ; Porovnej DWORDy na [DS:ESI] a [ES:EDI] (přípona ~D). |00000015:A7 | CMPSD [ESI],[EDI] ; Totéž, dokumentováno explicitními operandy. |00000016:F20FC2CA00 | CMPSD XMM1,XMM2,0 ; Porovnej dvě skalární FP čísla s dvojitou přesností na rovnost.

↑ Instrukční modifikátory

CODE= ↓
DATA= ↓
IMM= ↓
DISP= ↓
SCALE= ↓
DIST= ↓
ADDR= ↓
PREFIX= ↓
MASK= ↓
ZEROING= ↓
EH= ↓
SAE= ↓
ROUND= ↓
BCST= ↓
OPER= ↓
ALIGN= ↓
NESTINGCHECK= ↓

Strojové instrukce se shodnou mnemonikou a funkčností mohou být někdy zakódovány do různých strojových kódů. Například okamžitá hodnota operandu může být zakódována v jednom bajtu, pokud nepřekračuje rozsah -128..+127, anebo může být zakódována jako celé slovo či dvojslovo. Podobné pravidlo platí pro hodnotu displacementu v adresních výrazech. Škálovaný adresní výraz, jako [1*ESI+EBX] může být kódován bez SIB jako [ESI+EBX] nebo s využitím SIB a s explicitním škálovacím faktorem 1.

€ASM preferuje kratší variantu, ale lze to změnit přídavným klíčovým operandem zvaným instrukční modifikátor.

Jiné asemblery dekorují operandy speciálními direktivami byte, word, dword, qword, short, strict, near, far, ptr k dosažení požadovaného kódu, např. add word ptr [StringOfBytes + 4], 0x20 nebo jmp short SomeLabel. Namísto těchto direktiv používá €ASM buď příponu mnemoniky, nebo instrukční modifikátor.

Modifikátory pro AVX MASK=, ZEROING=, SAE=, ROUND=, BCST= jsou v €ASM využívány namísto nekonzistních a bídně dokumentovaných dekorátorů typu {k} {z} {ru-sae} {4to16} {uint16} {cdab} navrhovaných v dokumentaci [IntelAVX512] a [IntelMVEX].

Typickou hodnotou modifikátoru je výčtová hodnota BYTE, WORD, DWORD. Většinu modifikátorů lze zkrátit na jejich první písmeno. U názvů ani hodnot instrukčních modifikátorů nezáleží na velikosti písmen.

Některé modifikátory jsou booleovské, jejich hodnota může být TRUE, YES, ON, ENABLE, ENABLED pokud pravda, a FALSE, NO, OFF, DISABLE, DISABLED v ostatních případech. Logickým modifikátorem může být také výraz vyhodnocený jako nula (nepravda) nebo ne-nula (pravda), viz boolovská rozšíření.

Pokud €ASM nemůže vyhovět požadovanému modifikátoru, ohlásí varování a ignoruje ho.

Volbou EUROASM DISPLAYENC=ON můžeme zapnout zobrazování aktuálně použitých modifikátorů. V tom případě €ASM doprovodí každou strojovou instrukci diagnostickým oznámením D1080 explicitně dokumentujícím modifikátory použité při kódování instrukce.:

| | EUROASM DISPLAYENC=ON |00000000:694D10C8000000 | IMUL ECX,[EBP+16],200 |# D1080 Emitted size=7,DATA=DWORD,DISP=BYTE,SCALE=SMART,IMM=DWORD. |00000007: | |00000007:62F1ED2CF44D02<5 | VPMULUDQ YMM1,YMM2,[EBP+40h],MASK=K4 |# D1080 Emitted size=7,PREFIX=EVEX,MASK=K4,ZEROING=OFF,DATA=YWORD,BCST=OFF,OPER=2,DISP=BYTE,SCALE=SMART.
↑ CODE=

Jako dědictví po starších procesorech některé strojové instrukce mají více než jedno kódování. Například instrukce POP rAX může být zakódována jako 0x58 nebo jako 0x8FC0, přičemž oba způsoby jsou funkčně ekvivalentní. Modifikátor CODE= vybírá kódování, které má €ASM použít.

Modifikátor může být SHORT nebo LONG alias S nebo L. Jako výchozí se bere ten, který poskytuje kratší kód, obvykle CODE=SHORT.

Mají-li dvě kódování stejnou velikost, CODE=SHORT vybírá variantu s numericky nižším operačním kódem.

|00000000:43 | INC EBX |00000001:43 | INC EBX,CODE=SHORT ; Zděděné kódování Intel 8080, není dostupné v 64bitovém módu. |00000002:FFC3 | INC EBX,CODE=LONG |00000004: | |00000004:50 | PUSH EAX |00000005:50 | PUSH EAX,CODE=SHORT ; Zděděné kódování Intel 8080, není dostupné v 64bitovém módu. |00000006:FFF0 | PUSH EAX,CODE=LONG |00000008: | |00000008:87CA | XCHG ECX,EDX |0000000A:87D1 | XCHG ECX,EDX,CODE=LONG ; Modifikátor zaměňuje operandy v komutativních operacích XCHG, TEST. |0000000C:87D1 | XCHG EDX,ECX |0000000E:87CA | XCHG EDX,ECX,CODE=LONG |00000010: | |00000010:C3 | RET |00000011:C3 | RET CODE=LONG |00000012:C20000 | RET CODE=SHORT ; Byl požadován numericky nižší operační kód 0xC2, který ale vyžaduje imm16. |00000015: | |00000015:83C07F | ADD EAX,127 |00000018:83C07F | ADD EAX,127,CODE=LONG |0000001B:057F000000 | ADD EAX,127,CODE=SHORT ; Byl požadován kratší operační kód 0x05, který ale neumí znaménkově roztáhnout imm8.
V některých případech volba numericky nižšího operačního kódu pomocí modifikátoru CODE=SHORT může vést k delšímu zakódování, viz výše v příkladu ADD r32,imm8.
↑ DATA=

Tento modifikátor ovlivňuje velikost operandu, tedy šířku dat, se kterými instrukce pracuje. Může to být jedna z výčtových hodnot BYTE, WORD, DWORD, QWORD, TBYTE, OWORD, YWORD, ZWORD neboli B, W, D, Q, T, O, Y, Z. Výchozí hodnota není specifikována.

Modifikátor DATA= má stejnou funkci jako přípona mnemoniky, jsou pouze dva rozdíly:

Existují další možnosti, jak řídit velikost operandu. Je-li jedním z operandů registr, jeho šířka převládne a nelze to přepsat příponou ani modifikátorem. Není-li šířka specifikována registrem, €ASM se dívá na atribut TYPE# paměťového operandu.

Priorita specifikací velikosti dat:

  1. Šířka registrového operandu.
  2. Přípona mnemoniky.
  3. Modifikátor DATA=.
  4. Typ paměťového operandu.

Viz následující příklady:

|00000000:00000000 |MemoryVariable DB 0,0,0,0 |00000004:0107 | ADD [EDI],EAX ; Šířka je určena registrem (32 bitů). |00000006:830701 | ADDD [EDI],1 ; Šířka je určena příponou (32 bitů). |00000009:66830701 | ADD [EDI],1,DATA=W ; Šířka je určena modifikátorem (16 bitů). |0000000D:800701 | ADDB [EDI],1,DATA=W ; Šířka je určena příponou (8 bitů). Varování: modifikátor byl ignorován. |## W2401 Modifier "DATA=WORD" could not be obeyed in this instruction. |00000010:660107 | ADDB [EDI],AX ; Šířka je určena registrem (16 bitů). Chyba: přípona byla ignorována. |### E6740 Impracticable operand-size requested with mnemonic suffix. |00000013:8387[00000000]01 | ADDD [EDI+MemoryVariable],1 ; Šířka je určena příponou (32 bitů). |0000001A:668387[00000000]01 | ADD [EDI+MemoryVariable],1,DATA=W ; Šířka je určena modifikátorem (16 bitů). |00000022:8087[00000000]01 | ADD [EDI+MemoryVariable],1 ; %Sířka je určena atributem TYPE# MemoryVariable = 'B' (8 bitů). |00000029:800701 | ADD [EDI],1 ; Chyba: Šířka nebyla určena. |### E6730 Operand size could not be determined, please use DATA= modifier.
↑ IMM=

Některé instrukce kódují malou okamžitou hodnotu jako jeden bajt, třebaže operují s celým slovem. Hodnota bajtu je znaménkově rozšířena procesorem za běhu programu.

Modifikátor IMM= může nabývat hodnnot BYTE, WORD, DWORD, QWORD alias B, W, D, Q a specifikuje, jak by měla být hodnota operandu zakódována v instrukci.

|00000000:83D001 | ADC EAX,1 |00000003:83D001 | ADC EAX,1,IMM=BYTE |00000006:81D001000000 | ADC EAX,1,IMM=DWORD
↑ DISP=

Hodnota displacementu v adresním výrazu může být zakódována v jednom bajtu, pokud se vejde do rozsahu -128..+127. Tato hodnota bude procesorem za běhu znaménkově roztažena. Hodnoty mimo tento rozsah jsou zakódovány v plné velikosti, tj. jako 16tibitové nebo 32bitové slovo v souladu s šířkou segmentu (která mohla být dočasně změněna prefixem ATOGGLE). Toto je defaultní chování €ASM. Modifikátor DISP= může mít stejné hodnoty jako modifikátor IMM= a určuje, zda má být displacement zakódován v plné velikosti nebo jako bajt.

|00000000:2945FC | SUB [EBP-4],EAX |00000003:2945FC | SUB [EBP-4],EAX,DISP=BYTE |00000006:2985FCFFFFFF | SUB [EBP-4],EAX,DISP=DWORD
↑ SCALE=

Škálováním se rozumí vynásobení obsahu indexregistru v registrovém adresním výrazu hodnotou 0, 1, 2, 4 or 8 za běhu programu. Modifikátor SCALE= může být buď SMART nebo VERBATIM (případně zkráceně S, V). Výchozí hodnota je SCALE=SMART.
V módu verbatim se neprovádějí žádné optimalizace s indexovým a bázovým registrem; škálování je zakódováno s bajtem SIB i v případech, kdy je škálovací faktor 1 nebo 0. Kódování s SCALE=VERBATIM používá pokud možno bajt SIB.
Ve smart módu (default) €ASM zkouší rearanžovat registry a nepoužívat SIB, není-li to nezbytně nutné.
Optimalizační "smart" pravidla: (IR je indexregister, BR je baseregister, disp je displacement):

|00000000:A011000000 | MOV AL,[0x11] ; Speciální kódování bez ModR/M. |00000005:A011000000 | MOV AL,[0*ESI+0x11] ; Speciální kódování bez ModR/M. |0000000A:8A042511000000 | MOV AL,[0*ESI+0x11],SCALE=VERBATIM ; ModR/M a SIB. ESI není použito. |00000011: | |00000011:8A4611 | MOV AL,[ESI+0x11] ; ModR/M bez SIB. ESI je báze |00000014:8A4611 | MOV AL,[ESI+0x11],SCALE=SMART ; ModR/M bez SIB. ESI je báze. |00000017:8A442611 | MOV AL,[ESI+0x11],SCALE=VERBATIM ; ModR/M bez SIB, ESI je báze. |0000001B:8A4611 | MOV AL,[1*ESI+0x11] ; ModR/M bez SIB. ESI je báze. |0000001E:8A4611 | MOV AL,[1*ESI+0x11],SCALE=SMART ; ModR/M bez SIB. ESI je báze. |00000021:8A043511000000 | MOV AL,[1*ESI+0x11],SCALE=VERBATIM ; ModR/M plus SIB, ESI je index. |00000028: | |00000028:8A443611 | MOV AL,[ESI+ESI+0x11] ; ModR/M plus SIB. ESI je báze a index. |0000002C:8A443611 | MOV AL,[2*ESI+0x11] ; ModR/M plus SIB. ESI je báze a index. |00000030:8A047511000000 | MOV AL,[2*ESI+0x11],SCALE=VERBATIM ; ModR/M plus SIB. ESI je index. |00000037: | |00000037:8A442D11 | MOV AL,[EBP+EBP+0x11] ; ModR/M plus SIB, EBP je báze a index. |0000003B:8A442D11 | MOV AL,[2*EBP+0x11] ; ModR/M plus SIB, EBP je báze a index. |0000003F:8A046D11000000 | MOV AL,[2*EBP+0x11],SCALE=VERBATIM ; ModR/M plus SIB, EBP je index.
Všimněte si, že optimalizace pomocí SCALE=SMART může změnit roli registrů (báze|index) a tudíž i defaultní segmentový registr (SS|DS) použitý k adresaci. V paměťovém modelu FLAT je to obvykle jedno, jinak použijte SCALE=VERBATIM.

Je-li zobrazování zakódování instrukcí povoleno pomocí EUROASM DisplayEnc=Yes, modifikátor SCALE=VERBATIM říká, že bajt SIB byl emitován, jinak SCALE=SMART signalizuje, že SIB chybí.

↑ DIST=

Tento modifikátor určuje distanci cíle v instrukcích pro předání zpracování. Hodnotou modifikátoru je jedna z možností FAR, NEAR, SHORT alias F, N, S.

DIST=FAR se použije, pokud je cíl v odlišném segmentu a musí se změnit obsah registrů jak rIP, tak i CS.

Ve výchozím stavu €ASM při přechodech uvnitř segmentu automaticky vybírá mezi vzdáleností SHORT a NEAR v závislosti na rozdílu ofsetů.

Modifikátor DIST= plní stejnou funkci jako instrukční přípona, jsou jen dva rozdíly:

Modifikátor DIST=NEAR nebo DIST=FAR může být také aplikován na pseudoinstrukce PROC, PROC1. Důsledkem nastavení procedury na DIST=FAR je to, že instrukce CALL a JMP na takovou proceduru budou defaultně FAR a že instrukce RET uvnitř takové procedury také bude defaultně DIST=FAR.

|[CODE1] |[CODE1] SEGMENT |0000:EB2A | JMP CloseLabel: ; Zakódováno jako DIST=SHORT. |0002:E92701 | JMP DistantLabel: ; Zakódováno jako DIST=NEAR. |0005:EA[0000]{0000} | JMP FarLabel: ; Zakódováno jako DIST=FAR. |000A:EB20 | JMP CloseLabel:,DIST=SHORT ; Zakódováno jako DIST=SHORT. |000C:E91D01 | JMP DistantLabel:,DIST=SHORT ; Zakódováno jako DIST=NEAR. |## W2401 Modifier "DIST=SHORT" could not be obeyed in this instruction. |000F:EA[0000]{0000} | JMP FarLabel:,DIST=SHORT ; Zakódováno jako DIST=FAR. |## W2401 Modifier "DIST=SHORT" could not be obeyed in this instruction. |0014:E91500 | JMP CloseLabel:,DIST=NEAR ; Zakódováno jako DIST=NEAR. |0017:E91201 | JMP DistantLabel:,DIST=NEAR ; Zakódováno jako DIST=NEAR. |001A:E9(0000) | JMP FarLabel:,DIST=NEAR ; Zakódováno jako DIST=NEAR. |001D:EA[2C00]{0000} | JMP CloseLabel:,DIST=FAR ; Zakódováno jako DIST=FAR. |0022:EA[2C01]{0000} | JMP DistantLabel:,DIST=FAR ; Zakódováno jako DIST=FAR. |0027:EA[0000]{0000} | JMP FarLabel:,DIST=FAR ; Zakódováno jako DIST=FAR. |002C: |CloseLabel: |002C:90909090909090~~| DB 256 * B 0x90 ; Kód pro oddálení návěstí DistantLabel. |012C: |DistantLabel: |[CODE2] |[CODE2] SEGMENT |0000: |FarLabel:
↑ ADDR=

Tento modifikátor vybírá referenční rámec při adresaci paměti v 64bitovém módu. Dovolené hodnoty jsou ABS, REL nebo zkráceně A, R. Ofset zakódovaný v instrukci s absolutní adresaci je vztažen k začátku segmentu, který je v asm-time vždy 0.
Při relativní adresaci je ofset vztažen k pozici příští instrukce, tedy k obsahu registru RIP.
V historických módech (16 a 32bitovém) je referenční rámec napevno ADDR=REL v instrukcích pro předání zpracování (přímý JMP, CALL, LOOP, Jcc), a jako ADDR=ABS ve všech ostatních instrukcích.

Adresování vztažené k RIP je o jeden bajt kratší a nepotřebuje relokaci. Proto je adresování s ADDR=REL preferováno jako výchozí v 64bitovém módu.
Explicitní výběr absolutní a RIP-relativní adresace má význam pouze v 64bitovém módu pokud by absolutní adresa vyžadovala relokaci v link-time. K tomu dochází, je-li paměťová proměnná specifikována jako adresní symbol (nikoli prosté číslo), a pokud v adresaci není zapojen bázový ani indexový registr.

|00000000:00000000 | MemDword DD 0 |00000004: | |00000004:0305F6FFFFFF | ADD EAX,[MemDword] ; Zakódováno jako relativní adresace. |0000000A:0305F0FFFFFF | ADD EAX,[MemDword],ADDR=REL ; Zakódováno jako relativní adresace. |00000010:030425[00000000] | ADD EAX,[MemDword],ADDR=ABS ; Zakódováno jako absolutní adresace. |00000017: | |00000017:034540 | ADD EAX,[RBP+0x40] ; Zakódováno jako absolutní adresace. |0000001A:034540 | ADD EAX,[RBP+0x40],ADDR=ABS ; Zakódováno jako absolutní adresace. |0000001D:034540 | ADD EAX,[RBP+0x40],ADDR=REL ; Zakódováno jako absolutní adresace. |## W2401 Modifier "ADDR=REL" could not be obeyed in this instruction.
↑ PREFIX=

Všechny následující modifikátory se vztahují pouze k instrukcím používajícím kódování Advanced Vector eXtensions (AVX). Možné hodnoty prefixu jsou XOP, VEX, VEX2, VEX3, MVEX, EVEX (zkratky nejsou k dispozici).

Většina instrukcí AVX má mnemoniku prefixovánu písmenem V~. Některé instrukce jsou definovány pouze jedním druhem AVX prefixů, ty pak nepotřebují explicitní modifikátor. Pokud instrukce může být zakódována více různými prefixy, €ASM defaultně vybírá ten nejkratší.

Prefix VEX existuje ve dvou variantách: VEX2 a VEX3. Delší kódování (VEX3) je automaticky vybráno, pokud instrukce používá indexregistr nebo bázový registr R8..R15, případně pokud používá mapu operačních kódů 0F38 nebo 0F3A.

Prefix EVEX nebo MVEX bude použit namísto VEX pokud instrukce používá registr XMM16..XMM31, YMM16..YMM31, ZMM0..ZMM31, K0..K7, nebo modifikátor EH=, SAE=, ROUND=, MASK=, ZEROING=, OPER=.

Instrukce kódovatelné jak pomocí EVEX, tak i MVEX používají jako default PREFIX=EVEX. Software napsaný pro CPU Intel® Xeon Phi musí explicitně žádat PREFIX=MVEX pro každou takovou obojživelnou instrukci. V tom případě je užitečné disablovat EVEX EUROASM EVEX=DISABLED a být tudíž varován, pokud některá instrukce MVEX bude nedopatřením zakódována jako EVEX. Explicitní specifikace modifikátoru EH= (který je použitelný pouze u MVEX) rovněž vybírá prefix MVEX, psát PREFIX=MVEX v takovém případě není nutné.

Vlastnosti CPU vyžadované použitím prefixů AVX
PrefixPožadovaná volba EUROASM
XOPSIMD=AVX, AMD=ENABLED, XOP=ENABLED
VEXSIMD=AVX
MVEXSIMD=AVX512, MVEX=ENABLED
EVEXSIMD=AVX512, EVEX=ENABLED
|00000000:8FE868CCCB04 | VPCOMB XMM1,XMM2,XMM3,4 ; VPCOMB je definováno pouze s XOP. |00000006:62F1FA082917 | VMOVNRAPD [RDI],ZMM2 ; VMOVNRAPD je definováno pouze s MVEX. |0000000C:C5E958CB | VADDPD XMM1,XMM2,XMM3 ; VADDPD je definováno s VEX,MVEX,EVEX. |00000010:C5E958CB | VADDPD XMM1,XMM2,XMM3,PREFIX=VEX |00000014:C5E958CB | VADDPD XMM1,XMM2,XMM3,PREFIX=VEX2 |00000018:C4E16958CB | VADDPD XMM1,XMM2,XMM3,PREFIX=VEX3 |0000001D:62F1ED0858CB | VADDPD XMM1,XMM2,XMM3,PREFIX=EVEX |00000023:62F1ED4858CB | VADDPD ZMM1,ZMM2,ZMM3,PREFIX=EVEX |00000029:62F1E90858CB | VADDPD ZMM1,ZMM2,ZMM3,PREFIX=MVEX
↑ MASK=

Modifikátor MASK= (podobně jako ZEROING=, EH=, SAE=, ROUND=, BCST=, OPER=) je aplikovatelný pouze s Enhanced Advanced Vector eXtensions (EVEX nebo MVEX). MASK specifikuje, který maskovací registr je použit k řízení toho, které elementy (celá čísla nebo čísla s plovoucí tečkou) mají být zapisována do cílového registru. Pouze ty elementy, jež mají nastaven odpovídající bit v maskovacím registru, budou zapsány. Ostatní elementy jsou buď nulovány (pokud modifikátor ZEROING=ON) nebo zůstávají nezměněny (ZEROING=OFF).

Možné hodnoty parametru MASK= jsou K0, K1, K2, K2, K3, K4, K5, K6, K7 nebo výraz vyhodnocený na číslo 0..7. Výchozí hodnota je MASK=0. Registr K0 je speciální, všechny jeho bity se berou jako nastavené, takže maskování se neuplatňuje.

↑ ZEROING=

Booleovský modifikátor ZEROING= určuje, zda elementy maskované obsahem maskovacího registru by měly být vynulovány nebo ponechány beze změny, čemuž se říká merging. Nemá význam, pokud je MASK=K0 nebo pokud registr masky není vůbec specifikován. Default je ZEROING=OFF (merging). Modifikátor lze aplikovat pouze s kódováním prefixu EVEX.

|00000000:C5E958CB | VADDPD XMM1,XMM2,XMM3 ; VADDPD je definován s VEX,MVEX,EVEX. |00000004:62F1ED0C58CB | VADDPD XMM1,XMM2,XMM3,MASK=4 ; Použití MASK= vynutí kódování prefixu EVEX. |0000000A:62F1ED0C58CB | VADDPD XMM1,XMM2,XMM3,MASK=K4,ZEROING=NO |00000010:62F1ED8C58CB | VADDPD XMM1,XMM2,XMM3,MASK=K4,ZEROING=YES
↑ EH=

Booleovský modifikátor EH= (Eviction Hint) lze aplikovat pouze na instrukce zakódované s prefixem MVEX. EH=1 informuje CPU, že data jsou non-temporal a že patrně nebudou brzy znovu použita, takže nemá význam je držet ve vyrovnávací paměti CPU. Týká se to pouze instrukcí typu registr-do paměti.

Hodnota EH je rovněž konzultována v instrukcích typu registr-do-registru, kde vybírá mezi operacemi swizzle a statickým zaokrouhlováním.

↑ SAE=

Pokud je booleovský modifikátor SAE= (Suppress All Exceptions) zapnut, instrukce nebude vyvolávat žádnou výjimku (přerušení) při operacích s plovoucí tečkou, například když operovala s hodnotou not-a-number. Instrukce s nastaveným SAE=ON se chová, jako by všechny bity registru MXCSR byly nastaveny.

V kódování EVEX je ve výchozím stavu SAE povoleno kdykoli je použito statické zaokrouhlování. Toto chování nelze vypnout.

↑ ROUND=

Modifikátor ROUND= určuje statický zaokrouhlovací mód, lze jej aplikovat na instrukce s prefixem EVEX nebo MVEX se zaokrouhlovací sémantikou, například pro konverzi z dvojité na jednoduchou přesnost čísel s plovoucí tečkou. Má čtyři možné hodnoty: NEAR, UP, DOWN, ZERO alias N, U, D, Z.

Statické zaokrouhlování je dostupné pouze v operacích typu registerZMM-do-registru ZMM, ne pokud je některý operand v paměti nebo pokud jsou použity registry XMM nebo YMM. Default je bez zaokrouhlování, v tom případě platí obecné zaokrouhlování řízené bity RM registru MXCSR.

↑ BCST=

Booleovský modifikátor BCST= lze použít k povolení data broadcasting (vysílání) v operacích, které čtou data z paměti. Pokud je BCST=ENABLED, zdrojový paměťový operand čte z paměti pouze jeden element a jeho obsah je pak zkopírován (vyslán) do všech pozic cílového registru.

Výchozí stav je BCST=OFF. Broadcasting nelze použít u operací typu registr-do-registru.

|00000000:62F16C48590E | VMULPS ZMM1,ZMM2,[RSI] ; Vynásob 16 DWORD FP čísel v ZMM2 a 16 DWORD FP čísel na [RSI], ulož 16 součinů do ZMM1. |00000006:62F16C58590E | VMULPS ZMM1,ZMM2,[RSI],BCST=ON ; Vynásob 16 DWORD FP čísel v ZMM2 jedním FP číslem na [RSI], ulož 16 součinů do ZMM1. |0000000C:62F16C4859CB | VMULPS ZMM1,ZMM2,ZMM3 ; Vynásob 16 DWORD FP čísel v ZMM2 a 16 DWORD FP čísel v ZMM3, ulož 16 součinů do ZMM1. |00000012:62F16C7859CB | VMULPS ZMM1,ZMM2,ZMM3,ROUND=ZERO ; Totéž, zaokrouhli každý součin směrem k nule.
↑ OPER=

Modifikátor OPER= kóduje druh operace prováděné za běhu se zdrojovým operandem. Možné operace jsou broadcasting, rounding, conversion, swizzling. Možnou hodnotou modifikátoru je číselný výraz vyhodnocený na číslo 0..7.

Tato hodnota bude zakódována v bitech 6, 5, 4 32bitového prefixu EVEX nebo MVEX. Bity jsou pojmenovány S2, S1, S0 ve specifikaci MVEX [IntelMVEX], a L', L, b ve specifikaci EVEX [IntelAVX512]. Tytéž bity jsou rovněž ovlivněny modifikátory BCST=, ROUND=, SAE= a šířkou registrů SIMD, avšak přímé uvedení modifikátoru OPER= má vyšší prioritu, pokud by došlo ke konfliktu.

Modifikátor OPER= je jediný způsob, jak požadovat speciální konverzní nebo swizzle (míchací) operace pro instrukce kódované pomocí MVEX a dostupné na Intel® Xeon Phi procesoru. Ne všechny operace z níže uvedené tabulky jsou dostupné u všech MVEX instrukcí, dokumentace na [IntelMVEX] by měla být prohlédnuta před použitím modifikátoru.

Operace kódované s MVEX
OPER=register-do-registru, EH=0registr-do-registru, EH=1paměť-do-registruregistr-do-paměti
0no swizzle {dcba}ROUND=NEAR,SAE=NOno operationno conversion
1swap (inner) pairs {cdab}ROUND=DOWN,SAE=NObcst 1 element {1to16} or {1to8}not available
2swap with two-away {badc}ROUND=UP,SAE=NObcst 4 elements {4to16} or {4to8}not available
3cross-product swizzle {dacb}ROUND=ZERO,SAE=NOconvert from {float16}convert to {float16}
4bcst a element across 4 {aaaa}ROUND=NEAR,SAE=YESconvert from {uint8}convert to {uint8}
5bcst b element across 4 {bbbb}ROUND=DOWN,SAE=YESconvert from {sint8}convert to {sint8}
6bcst c element across 4 {cccc}ROUND=UP,SAE=YESconvert from {uint16}convert to {uint16}
7bcst d element across 4 {dddd}ROUND=ZERO,SAE=YESconvert from {sint16}convert to {sint16}
Operace kódované s EVEX
OPER=registr-do-registrupaměť-do-registru
0DATA=OWORD,SAE=NODATA=OWORD,BCST=OFF
1DATA=ZWORD,SAE=YES,ROUND=NEARDATA=OWORD,BCST=ON
2DATA=YWORD,SAE=NODATA=YWORD,BCST=OFF
3DATA=ZWORD,SAE=YES,ROUND=DOWNDATA=YWORD,BCST=ON
4DATA=ZWORD,SAE=NODATA=ZWORD,BCST=OFF
5DATA=ZWORD,SAE=YES,ROUND=UPDATA=ZWORD,BCST=ON
6reservedreserved
7DATA=ZWORD,SAE=YES,ROUND=ZEROreserved
|00000000:62F16908DB4D01<6 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=0 ; No broadcast {16to16}. |00000007:62F16918DB4D10<2 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=1 ; Vysílej jeden element {1to16}. |0000000E:62F16928DB4D04<4 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=2 ; Vysílej čtyři elementy {4to16}. |00000015:62F16948DB4D04<4 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=4 ; Konvertuj z {uint8}. |0000001C:62F16958DB4D04<4 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=5 ; Konvertuj z {sint8}. |00000023:62F16968DB4D02<5 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=6 ; Konvertuj z {uint16}. |0000002A:62F16978DB4D02<5 | VPANDD ZMM1,ZMM2,[RBP+40h],PREFIX=MVEX,OPER=7 ; Konvertuj z {sint16}. |00000031: | |00000031:62F1F9085A4D01<6 | VCVTPD2PS ZMM1,[RBP+40h],PREFIX=MVEX,OPER=0 ; Bez vysílání {8to8}. |00000038:62F1F9185A4D08<3 | VCVTPD2PS ZMM1,[RBP+40h],PREFIX=MVEX,OPER=1 ; Vysílej jeden element {1to8}. |0000003F:62F1F9285A4D02<5 | VCVTPD2PS ZMM1,[RBP+40h],PREFIX=MVEX,OPER=2 ; Vysílej čtyři elementy {4to8}. |00000046: | |00000046:62F1F9085ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=0 ; Bez míchání {dcba}. |0000004C:62F1F9185ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=1 ; Přehoď vnitřní páry {cdab}. |00000052:62F1F9285ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=2 ; Přehoď dva-pruč {badc}. |00000058:62F1F9385ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=3 ; Zamíchej křížový produkt {dacb}. |0000005E:62F1F9485ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=4 ; Vysílej element a do 4 {aaaa}. |00000064:62F1F9585ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=5 ; Vysílej element b do 4 {bbbb}. |0000006A:62F1F9685ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=6 ; Vysílej element c do 4 {cccc}. |00000070:62F1F9785ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=0,OPER=7 ; Vysílej element d do 4 {dddd}. |00000076: | |00000076:62F1F9885ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=0 ; ROUND=NEAR,SAE=OFF {rn}. |0000007C:62F1F9985ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=1 ; ROUND=DOWN,SAE=OFF {rd}. |00000082:62F1F9A85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=2 ; ROUND=UP, SAE=OFF {ru}. |00000088:62F1F9B85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=3 ; ROUND=ZERO,SAE=OFF (rz). |0000008E:62F1F9C85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=4 ; ROUND=NEAR,SAE=ON {rn-sae}. |00000094:62F1F9D85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=5 ; ROUND=DOWN,SAE=ON {rd-sae}. |0000009A:62F1F9E85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=6 ; ROUND=UP, SAE=ON {ru-sae}. |000000A0:62F1F9F85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,EH=1,OPER=7 ; ROUND=ZERO,SAE=ON {rz-sae}. |000000A6:62F1F9F85ACA | VCVTPD2PS ZMM1,ZMM2,PREFIX=MVEX,ROUND=ZERO,SAE=ON |000000AC:62F1F9F85ACA | VCVTPD2PS ZMM1,ZMM2,EH=1,ROUND=ZERO,SAE=ON
↑ ALIGN=

Požadavek na zarovnání může být přidán ke kterékoli strojové instrukci a také k pseudoinstrukcím D, PROC, PROC1, STRUC. V kapitole alignment jsou uvedeny přípustné hodnoty. Tento instrukční modifikátor má stejný efekt, jako by před instrukcí byla explicitní pseudoinstrukce ALIGN.

↑ NESTINGCHECK=

Tento modifikátor může být připojen pouze k pseudoinstrukcím PROC, ENDPROC, PROC1, ENDPROC1. Jeho hodnota je logická, default je NESTINGCHECK=ON. Vypnutí kontroly vnoření vypíná chybové oznámení při nesouhlasu identifikátorů na začátku a konci bloku, což je potřebné k zavedení vazeb mezi některými pseudoinstrukcemi. Viz definici maker Procedure a EndProcedure jako příklad.

↑ Vylepšení instrukcí

Defaultní registry FPU ↓
Operandy řetězcových instrukcí ↓
XLAT s odlišnou bází ↓
LOOP s odlišným čítačem ↓
NEAR a FAR LOOP a JrCXZ ↓
NEAR a FAR Jcc ↓
Vícenásobné operandy PUSH, POP, INC, DEC ↓
Operandy AAD, AAM ↓
TEST registru sám sebou ↓
Druhý operand posuvů a rotací ↓
No-operation ↓
Zdrojový registr PINSR ↓
Třetí operand BLENDVPD, BLENDVPS, PBLENDVB ↓
První operand MASKMOVQ, MASKMOVDQU ↓
VERR, VERQ, LAR, LSL ↓

Některé instrukce architektury IA-64 pracují s pevně stanovenými registry. €ASM akceptuje dobrovolnou explicitní specifikaci takových registrů; což poslouží jako dokumentace pro lidského čtenáře a může být také využito ke specifikaci šířky adresy nebo k určení nedefaultního segmentového registru.

↑ Defaultní registry FPU

Unární instrukce FPU (jednotky s pohyblivou tečkou) s implicitní destinací ST0 mohou tento registr explicitně uvádět na místě prvního operandu, nebo jej mohou vynechat. V mnoha dalších instrukcích FPU je defaultní cílový registr ST0 a defaultní zdrojový registr ST1, v tom případě jeden nebo oba operandy mohou být vynechány. Viz ovladače instrukcí FNOP, FCMOVB, FADD, FIADD, FADDP, FXCH, FCOM.

|00000000:000000000000F03F |Mem DQ 1.0 |00000008: | |00000008:DAC1 | FCMOVB ; ST0 = ST1 if Below. |0000000A:DAC1 | FCMOVB ST0,ST1 ; ST0 = ST1 if Below. |0000000C: | |0000000C:DAC7 | FCMOVB ST0,ST7 ; ST0 = ST7 if Below. |0000000E:DAC7 | FCMOVB ST7 ; ST0 = ST7 if Below. |00000010: | |00000010:D8C1 | FADD ; ST0 += ST1. |00000012:D8C1 | FADD ST0,ST1 ; ST0 += ST1. |00000014: | |00000014:DC05[00000000] | FADD ST0,[Mem] ; ST0 += [Mem]. |0000001A:DC05[00000000] | FADD [Mem] ; ST0 += [Mem]. |00000020: | |00000020:DCC7 | FADD ST7,ST0 ; ST7 += ST0. |00000022:DCC7 | FADD ST7 ; ST7 += ST0. |00000024: | |00000024:D9E9 | FLDL2T ; ST0 = log210. |00000026:D9E9 | FLDL2T ST0 ; ST0 = log210.
↑ Operandy řetězcových instrukcí

Řetězcové instrukce implicitně adresují zdroj jako paměť [DS:rSI] nebo port DX, a cíl jako paměť [ES:rDI] nebo port DX. Vedle jejich bezoperandové verze €ASM toleruje operandy explicitně určující tento zdroj a cíl s možným přepsáním segmentu a změnou adresní šířky.

|00000000:AC | LODSB |00000001:AC | LODSB [DS:ESI] ; Defaultní segment je DS, addresní šířka je 32. |00000002:2EAC | LODSB [CS:ESI] ; Přepsání segmentu. |00000004:67AC | LODSB [SI] ; Změna adresní šířky. |00000006: | |00000006:AA | STOSB |00000007:AA | STOSB [EDI] |00000008: | |00000008:AE | SCASB |00000009:AE | SCASB [EDI] |0000000A: | |0000000A:A5 | MOVSD |0000000B:A5 | MOVSD [EDI],[ESI] |0000000C:2667A5 | MOVSD [DI],[ES:SI] ; Změna adresní šířky a cílového segmentu. |0000000F: | |0000000F:666D | INSW |00000011:666D | INSW [ES:EDI],DX |00000013: | |00000013:6E | OUTSB |00000014:6E | OUTSB DX,[DS:ESI] |00000015:2E6E | OUTSB DX,[CS:ESI] ; Změna zdrojového segmentu.
↑ XLAT s odlišnou bází

Výchozí překladová tabulka je implicitně adresována jako [DS:rBX]. €ASM akceptuje volitelný paměťový operand, který může specifikovat přepsání segmentu a odlišnou šířku bázového registru.

↑ LOOP s odlišným čítačem

Registr smyčky LOOP může být specifikován jako nepovinný druhý operand.

|00000000:D7 | XLAT |00000001:D7 | XLATB ; XLAT a XLATB jsou identické. |00000002:D7 | XLATB [DS:EBX] ; Segment DS je default, přepis není potřeba. |00000003:26D7 | XLATB [ES:EBX] ; Přepsání segmentu. |00000005:67D7 | XLATB [BX] ; Změna adresní šířky z 32 na 16 bitů. |00000007: | |00000007:E2F6 | LOOP $-8 |00000009:E2F6 | LOOP $-8,ECX ; Výchozí čítač ve 32bitovém módu je ECX. |0000000B:67E2F5 | LOOP $-8,CX ; Registr čítače (jeho adresní šířka) změněna na 16 bitů.
↑ NEAR a FAR LOOP a JrCXZ

Smyčky nejsou v €ASM omezeny na krátkou vzdálenost -128..127. Pokud je cíl skoku instrukcí LOOP, LOOPcc, JCXZ, JECXZ, JRCXZ FAR nebo NEAR, €ASM místo něj přeloží tři instrukce:

LOOP $+2+2 ; Skoč na proxy-skok místo na originální cíl. JMPS $+JMPSsize+JMPsize ; Přeskoč proxy-skok, jakmile smyčka skončila (rCX je nula). JMP target ; NEAR nebo FAR nepodmíněný proxy-skok na původní cíl. |[CODE1] |[CODE1] SEGMENT |00000000:E366 | JECXZ CloseLabel: |00000002:E364 | JECXZ CloseLabel:,DIST=SHORT |00000004:E302EB05E95B000000 | JECXZ CloseLabel:,DIST=NEAR |0000000D:E302EB07EA[68000000]{0000}| JECXZ CloseLabel:,DIST=FAR |00000018: | |00000018:E302EB05E947010000 | JECXZ DistantLabel: |00000021:E302EB05E93E010000 | JECXZ DistantLabel:,DIST=SHORT |## W2401 Modifier "DIST=SHORT" could not be obeyed in this instruction. |0000002A:E302EB05E935010000 | JECXZ DistantLabel:,DIST=NEAR |00000033:E302EB07EA[68010000]{0000}| JECXZ DistantLabel:,DIST=FAR |0000003E: | |0000003E:E302EB07EA[00000000]{0000}| JECXZ FarLabel: |00000049:E302EB07EA(00000000){0000}| JECXZ FarLabel:,DIST=SHORT |## W2401 Modifier "DIST=SHORT" could not be obeyed in this instruction. |00000054:E302EB05E9(00000000) | JECXZ FarLabel:,DIST=NEAR |0000005D:E302EB07EA[00000000]{0000}| JECXZ FarLabel:,DIST=FAR |00000068: |CloseLabel: |00000068:909090909090909090909090~~| DB 256 * B 0x90 ; Kód k oddálení DistantLabel. |00000168: |DistantLabel: |[CODE2] |[CODE2] SEGMENT |00000000: |FarLabel:
↑ NEAR a FAR Jcc

Podmíněný skok na vzdálenost překračující bajtový limit -128..127 byl zaveden s generací procesoru 386. Pokud má náš program běžet také na starších CPU, NEAR a FAR podmíněný skok bude EuroAssemblerem přeložen jako dvě instrukce:

J!cc $+J!ccsize+JMPsize ; Přeskoč proxy-skok, pokud platí invertovaná podmínka JMP target ; NEAR nebo FAR nepodmíněný skok na původní cíl.

Proxy-skok namísto standardního NEAR podmíněného skoku existujícího v CPU=386 bude přeložen, jsou-li splněny tři podmínky:

  1. Vzdálenost do cíle přesahuje bajtový rozsah,
  2. šířka segmentu je 16 bitů,
  3. volba EUROASM CPU= je 286 nebo nižší.
|[CODE1] |[CODE1] SEGMENT WIDTH=16 | | EUROASM CPU=386 |0000:7419 | JE CloseLabel: ; Standardní SHORT podmíněný skok. |0002:0F841501 | JE DistantLabel: ; Standardní NEAR podmíněný skok, dostupný na CPU=386 a novějších. |0006:7505EA[0000]{0000}| JE FarLabel: ; FAR nepodmíněný proxy-skok přeskočený invertovaným J!cc. | | EUROASM CPU=086 ; Následující instrukce by měly běhat i na starých strojích typu PC/XT. |000D:740C | JE CloseLabel: ; Standardní SHORT podmíněný skok. |000F:7503E90701 | JE DistantLabel: ; NEAR nepodmíněný proxy-skok přeskočený invertovaným J!cc. |0014:7505EA[0000]{0000}| JE FarLabel: ; FAR nepodmíněný proxy-skok přeskočený invertovaným J!cc. |001B: |CloseLabel: |001B:9090909090909090~~| DB 256 * B 0x90 ; Kód k oddálení DistantLabel. |011B: |DistantLabel: |[CODE2] |[CODE2] SEGMENT |0000: |FarLabel:
↑ Vícenásobné operandy PUSH, POP, INC, DEC

Ve většině asemblerů mohou mít instrukce PUSH, POP, INC, DEC právě jeden operand. €ASM neomezuje počet operandů, jsou prováděny jeden za druhým ve specifikovaném pořadí. Je-li použit instrukční modifikátor nebo přípona, bude aplikována na všechny operandy. |00000000:57FF370FA06A04 | PUSH EDI,[EDI],FS,4 |00000007:590FA18F0658 | POP ECX,FS,[ESI],EAX |0000000D:40FF07 | INC EAX,[EDI],DATA=DWORD |00000010:48664AFEC9 | DEC EAX,DX,CL

↑ Operandy AAD, AAM

Instrukce AAD a AAM používají jako výchozí radix číslo 10 pro adjustování AL před dělením nebo po násobení čísel uložených ve formátu BCD. V €ASM tyto operace akceptují volitelný 8bitový operand, např. AAD 16. |00000000:D40A | AAM |00000002:D40A | AAM 10 |00000004:D410 | AAM 16 |00000006:D50A | AAD |00000008:D50A | AAD 10 |0000000A:D510 | AAD 16

↑ TEST registru sám sebou

Pokud oba operandy instrukce TEST určují tentýž registr, druhý operand může být vynechán.

↑ Druhý operand posuvů a rotací

Je-li počet bitů, o který se má rotovat nebo posouvat v instrukcích RCL, ROL, SAL, SHL, RCR, ROR, SAR, SHR roven jedné, druhý operand může být vynechán.

|00000000:85D2 | TEST EDX,EDX |00000002:85D2 | TEST EDX ; Druhý operand TEST je defaultně identický s prvním. |00000004: | |00000004:D1D0 | RCL EAX,1 |00000006:D1D0 | RCL EAX ; Vynechaný počet bitů je roven jedné. |00000008:D165F8 | SHL [EBP-8],1,DATA=DWORD |0000000B:D165F8 | SHL [EBP-8],DATA=DWORD
↑ No-operation

Instrukce, která nedělá nic (no-operation) kromě zabírání určitého času a zvětšování IP registru je ve všech x86 procesorech implementována jako jednobajtový NOP, konkrétně XCHG rAX,rAX (operační kód 0x90). Počínaje Pentium II (CPU=686) Intel zavedl dedikované mnohobajtové NOP instrukce s kódy 0x18..0x1F prefixované 0x0F. Mnohobajtový NOP je k zarovnávání vhodnější než série jednobajtových NOPů, neboť se z paměti načítá jako jeden celek najednou. Na starších CPU tento NOP musí být emulován staršími instrukcemi, jako XCHG reg,reg nebo LEA reg,[reg].

[Sandpile] a [NasmInsns] definují jejich mnemoniky jako nedokumentované instrukce HINT_NOP0, HINT_NOP1, HINT_NOP2..63. s jedním operandem požadované délky. Namísto zahlcení seznamu instrukcí 64 novými mnemonikami zavádí €ASM pouze jednu mnemoniku HINT_NOP (s možnými příponami HINT_NOPW, HINT_NOPD, HINT_NOPQ) s ordinálním číslem definovaným v prvním operandu a specifikací paměti odsunutou na místo druhého operandu.

|00000000:0F18D9 | HINT_NOP 03q,ECX |00000003:660F18E1 | HINT_NOP 04q,CX |00000007:66670F182C | HINT_NOPW 05q,[SI] |0000000C:66670F187400 | HINT_NOPW 06q,[SI],DISP=BYTE |00000012:0F18BE00000000 | HINT_NOPD 07q,[ESI],DISP=DWORD |00000019:0F19043500000000 | HINT_NOPD 10q,[1*ESI],DISP=DWORD,SCALE=VERBATIM |00000021: | |00000021:90 | NOP1 |00000022:6690 | NOP2 |00000024:0F1F00 | NOP3 |00000027:0F1F4000 | NOP4 |0000002B:0F1F442000 | NOP5 |00000030:660F1F442000 | NOP6 |00000036:0F1F8000000000 | NOP7 |0000003D:0F1F842000000000 | NOP8 |00000045:660F1F842000000000 | NOP9

Kromě toho €ASM implementuje ještě bezoperandové instrukce NOP1, NOP2, NOP3, NOP4, NOP5, NOP6, NOP7, NOP8, NOP9 zabírající specifikovaný počet bajtů a respektující aktuální úroveň a mód CPU.

No-operation encoding
MnemonikaOperační kód (hexa)Ekvivalentní instrukce v syntaxi €ASM
16bit mode, CPU=086
NOP190XCHG AX,AX
NOP287C9XCHG CX,CX
NOP39087C9XCHG AX,AX ; XCHG CX,CX
NOP487C987D2XCHG CX,CX ; XCHG DX,DX
NOP59087C987D2XCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX
NOP687C987D287DBXCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX
NOP79087C987D287DBXCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX
NOP887C987D287DB87E4XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX ; XCHG SP,SP
NOP99087C987D287DB87E4XCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX ; XCHG SP,SP
16bit mode, CPU=686
NOP190NOP DATA=WORD
NOP26690OTOGGLE NOP
NOP3666790OTOGGLE ATOGGLE NOP
NOP4670F1F00NOP [EAX],DATA=WORD
NOP5670F1F4000NOP [EAX],DATA=WORD,DISP=BYTE
NOP6670F1F442000NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP766670F1F442000NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP8670F1F8000000000NOP [EAX],DATA=WORD,DISP=DWORD
NOP9670F1F842000000000NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
32bit mode, CPU=386
NOP190XCHG EAX,EAX,DATA=DWORD
NOP26690XCHG AX,AX,DATA=WORD
NOP38D4000LEA EAX,[EAX],DATA=DWORD
NOP48D442000LEA EAX,[EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP53E8D442000LEA EAX,[DS:EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP68D8000000000LEA EAX,[EAX],DATA=DWORD,DISP=DWORD
NOP78D842000000000LEA EAX,[EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP83E8D842000000000LEA EAX,[DS:EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9663E8D842000000000LEA AX,[DS:EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
32bit mode, CPU=686
NOP190NOP DATA=DWORD
NOP26690NOP DATA=WORD
NOP30F1F00NOP [EAX],DATA=DWORD
NOP40F1F4000NOP [EAX],DATA=DWORD,DISP=BYTE
NOP50F1F442000NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP6660F1F442000NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP70F1F8000000000NOP [EAX],DATA=DWORD,DISP=DWORD
NOP80F1F842000000000NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9660F1F842000000000NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
64bit mode, CPU=X64
NOP190NOP DATA=DWORD
NOP26690NOP DATA=WORD
NOP30F1F00NOP [RAX],DATA=DWORD
NOP40F1F4000NOP [RAX],DATA=DWORD,DISP=BYTE
NOP50F1F442000NOP [RAX+0*RAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP6660F1F442000NOP [RAX+0*RAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP70F1F8000000000NOP [RAX],DATA=DWORD,DISP=DWORD
NOP80F1F842000000000NOP [RAX+0*RAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9660F1F842000000000NOP [RAX+0*RAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
MnemonikaOperační kód (hexa)Ekvivalentní instrukce v syntaxi €ASM

↑ Zdrojový registr PINSR

Instrukce PINSRB, PINSRW, PINSRD (vlož Byte/Word/Dword do cílového registru XMM) akceptují jako zdrojový operand č.2 ne pouze obecný registr (GPR) odpovídající šířky, ale i širší registr. Bude z něj použit pouze nejnižší BYTE|WORD|DWORD.

|00000000:660F3A20C902 | PINSRB XMM1,CL,2 |00000006:660F3A20C902 | PINSRB XMM1,CX,2 |0000000C:660F3A20C902 | PINSRB XMM1,ECX,2 |00000012: | |00000012:660FC4C902 | PINSRW XMM1,CX,2 |00000017:660FC4C902 | PINSRW XMM1,ECX,2
↑ Třetí operand BLENDVPS, BLENDVPD, PBLENDVB

Instrukce proměnného mísení používá pevně implikovaný registr XMM0 jako maskovací registr. €ASM dovoluje explicitní specifikaci tohoto registru jako třetí operand.

|00000000:660F3815CA | BLENDVPD XMM1,XMM2 |00000005:660F3815CA | BLENDVPD XMM1,XMM2,XMM0 |0000000A: | |0000000A:660F3814CA | BLENDVPS XMM1,XMM2 |0000000F:660F3814CA | BLENDVPS XMM1,XMM2,XMM0 |00000014: | |00000014:660F3810CA | PBLENDVB XMM1,XMM2 |00000019:660F3810CA | PBLENDVB XMM1,XMM2,XMM0
↑ První operand MASKMOVQ, MASKMOVDQU

Maskovatelné kopírování do paměti používá jako pevný cíl destinaci [DS:rDI]. €ASM dovoluje explicitní specifikaci cílové paměti jako volitelný první operand.

|00000000:0FF7CA | MASKMOVQ MM1,MM2 |00000003:0FF7CA | MASKMOVQ [DS:EDI],MM1,MM2 ; Defaultní destinace je [DS:EDI]. |00000006:260FF7CA | MASKMOVQ [ES:EDI],MM1,MM2 ; Přepis segmentu. |0000000A: | |0000000A:660FF7CA | MASKMOVDQU XMM1,XMM2 |0000000E:660FF7CA | MASKMOVDQU [DS:EDI],XMM1,XMM2 ; Defaultní destinace je [DS:EDI]. |00000012:26660FF7CA | MASKMOVDQU [ES:EDI],XMM1,XMM2 ; Přepis segmentu.
↑ VERR, VERW, LAR, LSL

Segmentový deskriptor u systémových instrukcí VERR, VERW (operand 1) a LAR, LSL (operand 2) může být specifikován jako 16bitová paměťová proměnná anebo 16, 32 nebo 64bitový obecný registr GPR (bude použito jen dolních 16 bitů).

|00000000:0F00E6 | VERR SI |00000003:0F00E6 | VERR ESI |00000006: | |00000006:0F00EE | VERW SI |00000009:0F00EE | VERW ESI |0000000C: | |0000000C:660F02C6 | LAR AX,SI |00000010:660F02C6 | LAR AX,ESI |00000014:0F02C6 | LAR EAX,SI |00000017:0F02C6 | LAR EAX,ESI |0000001A: | |0000001A:660F03C6 | LSL AX,SI |0000001E:660F03C6 | LSL AX,ESI |00000022:0F03C6 | LSL EAX,SI |00000025:0F03C6 | LSL EAX,ESI

Nedokumentované instrukce ↓

€ASM implementuje několik instrukcí, které nejsou dokumentovány v oficiálních specifikacích výrobců CPU. Nemusejí fungovat se všemi generacemi procesorů a vyžadují explicitní volbu EUROASM UNDOC=ENABLED.

Pro informaci viz jejich obslužné procedury (handlery) BB0_RESET, CMPXCHG486, F4X4, FCOM2, FCOMP5, FFREEP, FMUL4X4, FNSETPM, FRSTPM, FSBP1, FSBP2, FSBP3, FSTDW, FSTP1, FSTP8, FSTP9, FSTSG, FXCH4, FXCH7, HCF, HINT_NOP, IBTS, ICEBP, INT1, JMPE, LOADALL, LOADALL286, PREFETCHWT1, PSRAQ, SAL2, SALC, SETALC, SMINTOLD, TEST2, UD0, UD1, UD2A, UMOV, XBTS, VLDQQU.

↑ Pseudoinstrukce

ALIGN ↓

D, DB, DU, DW, DD, DQ, DT, DO, DY, DZ, DI, DS ↓

ENDHEAD ↓

ENDP ↓

ENDP1 ↓

ENDPROC ↓

ENDPROC1 ↓

ENDPROGRAM ↓

ENDSTRUC ↓

EQU ↓

= ↓

EUROASM ↓

EXTERN ↓

EXPORT ↓

GLOBAL ↓

GROUP ↓

HEAD ↓

IMPORT↓

INCLUDE ↓

INCLUDE1 ↓

INCLUDEBIN ↓

INCLUDEHEAD ↓

INCLUDEHEAD1 ↓

LINK ↓

PROC ↓

PROC1 ↓

PROGRAM ↓

PUBLIC ↓

SEGMENT ↓

STRUC ↓

%COMMENT ↓

%DEBUG ↓

%DISPLAY ↓

%DROPMACRO ↓

%ELSE ↓

%ENDCOMMENT ↓

%ENDFOR ↓

%ENDIF ↓

%ENDMACRO ↓

%ENDREPEAT ↓

%ENDWHILE

%ERROR ↓

%EXITFOR ↓

%EXITMACRO ↓

%EXITREPEAT ↓

%EXITWHILE

%FOR ↓

%IF ↓

%MACRO ↓

%PROFILE ↓

%REPEAT ↓

%SET ↓

%SETA ↓

%SETB ↓

%SETC ↓

%SETE ↓

%SETL ↓

%SETS ↓

%SETX ↓

%SET2 ↓

%SHIFT ↓

%UNTIL ↓

%WHILE

Pseudoinstrukce (také se jim říká direktivy) jsou příkazy asembleru formálně podobné běžným strojovým instrukcím — mnoho z nich může mít pole návěstí a operandy. Některé pseudoinstrukce (ALIGN a D) mohou dokonce emitovat data a kód.

U jmen pseudoinstrukcí a jejich klíčových operandů nezáleží na velikosti písmen.

↑ EUROASM

AUTOALIGN= ↓
AUTOSEGMENT= ↓
CODEPAGE= ↓
CPU= ↓
Rozšíření CPU ABM=, AES=, AMD=, AVX=, AVX512=, CET=, CYRIX=, D3NOW=, EVEX=, FMA=, FPU=, LWP=, MMX=, MPX=, MVEX=, PRIV=, PROT=, RTM=, SGX=, SHA=, SPEC=, SVM=, TSX=, UNDOC=, VIA=, VMX=, XOP= ↓
DEBUG= ↓
DISPLAYENC= ↓
DISPLAYSTM= ↓
DUMPALL= ↓
DUMP= ↓
DUMPWIDTH= ↓
INCLUDEPATH= ↓
LINKPATH= ↓
LIST= ↓
LISTFILE= ↓
LISTINCLUDE= ↓
LISTMACRO= ↓
LISTREPEAT= ↓
LISTVAR= ↓
MAXINCLUSIONS= ↓
MAXLINKS= ↓
NOWARN= ↓
PROFILE= ↓
RUNPATH= ↓
SIMD= ↓
UNICODE= ↓
WARN= ↓

Pseuodinstrukcí EUROASM programátor ovlivňuje různá nastavení EuroAssembleru samotného - volby EUROASM. Příslušná volba je určena klíčovým operandem. Stejné klíče jsou použity také v sekci [EUROASM] konfiguračního souboru euroasm.ini.

Volby specifikované touto pseudoinstrukcí přepisují defaultní volby z konfiguračního souboru. Jména voleb nezávisí na velikosti písmen.

Aktuální hodnota každé volby může být získána pomocí EUROASM systémových %^proměnných se shodným jménem, například InfoMsg DB "This program uses code page %^CODEPAGE.",13,10,0

Volbám očekávajícím booleovskou hodnotu může být předloženo výčtové slovo TRUE, YES, ON, ENABLE, ENABLED nebo FALSE, NO, OFF, DISABLE, DISABLED nebo mohou obsahovat logický výraz.

Vedle klíčových operandů pseudoinstrukce EUROASM rozeznává ještě dva pořadové operandy s výčtovou hodnotou PUSH nebo POP. €ASM udržuje speciální zásobník voleb a tyto dvě direktivy dovolují uschovat a obnovit celý soubor voleb EuroAssembleru na tento zásobník. To se hodí u maker, které dočasně vyžadují nějakou neobvyklou volbu. Slepé nastavení takové volby by mělo vedlejší efekt na instrukce následující po vyvolání makra (EUROASM je přepínací instrukce). Proto je lepší uložit aktuální volby na jejich zásobník na počátku makra a obnovit je na jeho konci. Příklad:

SomeMacro %MACRO  ; Definice makra.
            EUROASM PUSH, NOWARN=2102 ; Ulož všechny volby a pak potlač varování W2102.
             ; Tady budou instrukce, které mohou vyvolat W2102.
             ...
            EUROASM POP ; Obnov zásobník voleb, W2102 již není potlačena.
          %ENDMACRO SomeMacro
↑ AUTOALIGN=

Booleovská volba s výchozí hodnotou AUTOALIGN=ON. Paměťové proměnné definované nebo rezervované pseudoinstrukcí D budou implicitně zarovnány v souladu se svým typem (TYPE#).

K zarovnaným proměnným může CPU přistupovat rychleji, na druhé straně tato volba může nafouknout velikost programu, pokud jsou data různých typů často mísena. Je proto lepší manuálně seskupovat datové položky stejných velikostí.

Proměnné definované jako literály jsou automaticky zarovnány nezávisle na stavu EUROASM AUTOALIGN=.

Strukturované datové proměnné (definované pomocí DS structure_name) se nezarovnávají podle svého největšího členu, jsou zarovnány na šířku segmentu (WORD, DWORD or QWORD) pokud je AUTOALIGN=ENABLED.

Autoalignment nefunguje uvnitř definice struktury.

Programátor by měl definovat strukturu s ohledem na přirozené zarovnání jejich členů. To je zvláště důležité v 64bitovém módu, kde API vyžaduje zarovnaná data. Během konverze špatně navržených 32bitových struktur se musely uměle vkládat výplňové členy typu DWORD zarovnávající délky na QWORD a zaokrouhlující délku struktury na násobek osmi. Viz například WinAPI strukturu MSG.

Autoalignment se neaplikuje na strojové instrukce. Chcete-li proceduru zarovnanou na počátek stránky vyrovnávací paměti (kvůli lepší výkonnosti), měla by být zarovnána explicitně, např.Rapid PROC ALIGN=OWORD.

↑ AUTOSEGMENT=

Booleovská volba s výchozí hodnotou AUTOSEGMENT=ON. Sekce, do níž €ASM emituje, je automaticky změněna, aby byla v souladu s účelem (PURPOSE=) segmentu.

Jedná-li se o strojovou instrukci nebo strojový prefix nebo PROC, €ASM přepne do naposledy definované sekce s účelem PURPOSE=CODE.
Podobně, pokud pseudoinstrukce D a její klony včetně DI definuje nebo rezervuje data, současná sekce je přepnuta na poslední sekci typu DATA nebo BSS.

Pseudoinstrukce ALIGN, makra a všechny neemitující operace, jako např. EQU nebo samotné návěstí, nemění současnou sekci.

Spoléháte-li na autosegmentaci, vyvarujte se případu, kdy nová sekce začíná voláním makra, pseudoinstrukcí ALIGN nebo samotným návěstím. Takové povely nepřepnou současnou sekci. Možná budete chtít vložit NOP nebo PROC k přepnutí do kódové sekce, DB 0 k přepnutí na data, anebo DB k přepnutí na BSS sekci. Příklad:
      EUROASM AUTOSEGMENT=ON
Hello PROGRAM FORMAT=PE, ENTRY=Main:
       INCLUDE winapi.htm; Základní makra.
Title  DB "World!",0     ; Korektně automaticky přepla do [.data].
Main:  StdOutput Title   ; Makro nepřeplo do [.text], jak bylo asi očekáváno.
       TerminateProgram
      ENDPROGRAM Hello   ; Hello.exe zde nefunguje, neboť ENTRY je v sekci [.data]. 

Návěstí Main: chybně zůstalo v předchozí sekci [.data]. Náorava je prostá:

      EUROASM AUTOSEGMENT=ON
Hello PROGRAM FORMAT=PE, ENTRY=Main:
       INCLUDE winapi.htm; Základní makra.
Title  DB "World!",0     ; Korektně automaticky přepla do [.data].
Main:  PROC              ; Korektně automaticky přepla do [.text].
        StdOutput Title
        TerminateProgram
       ENDPROC Main:
      ENDPROGRAM Hello   ; Hello.exe works as expected.
Každé explicitní přepnutí sekce zneplatní jako vedlejší efekt volbu AUTOSEGMENT.

AUTOSEGMENT= je slabá volba, je automaticky vypínána, když programátor změní aktuální sekci uvedením [jména_sekce] v poli návěstí.

Potřebujete-li udržet AUTOSEGMENT zapnutý po ruční změně sekce, musíte pak tuto volbu explicitně znovu zapnout pomocí EUROASM AUTOSEGMENT=ON, anebo uložit její stav pomocí EUROASM PUSH a pak jej obnovit pomocí EUROASM POP.
↑ CODEPAGE=

€ASM umí používat řetězce v Unicode za běhu programu, ale definice dat ve zdrojovém kódu je i tak definována v bajtech. Volba CODEPAGE= říká EuroAssembleru. která kódová stránka by měla být aktuálně použita k převodu bajtů zdrojového kódu na Unicode v asm-time.

Kódová stránka může být určena přímou 16bitovou celočíselnou hodnotou podle [CodePageMS], např. CODEPAGE=1253 pro řeckou abecedu.

Hodnoty CODEPAGE= mohou být rovněž určeny jako výčtové slovo, např. CODEPAGE=CP852, CODEPAGE=WINDOWS-1252, CODEPAGE=ISO-8859-2 atd. Pro kompletní seznam viz DictCodePages U jmen těchto specifikací nezáleží na velikosti písmen.

Přestože některé tyto konstanty mohou vypadat jako aritmetické rozdíly, jsou rozeznávány doslova a nejsou vyhodnocovány jako čísla.

Výchozí a zároveň doporučená hodnota je CODEPAGE=UTF-8. Viz též kódování znaků výše.

↑ INCLUDEPATH=

Jestliže je v pseudoinstrukci z rodiny INCLUDE* specifikován soubor bez cesty, €ASM jej bude hledat v adresářích definovaných ve volbě EUROASM INCLUDEPATH=. Cesty zde mohou být odděleny středníkem ; nebo čárkou , a celý seznam cest by měl být v uvozovkách. Jako oddělovač složek lze použít zpětné \ i dopředné / lomítko. Poslední lomítko může být vynecháno. Výchozí hodnotou je INCLUDEPATH="./,./maclib,../maclib,".

Tato syntaxe nepovoluje názvy složek začínající či končící mezerou, ovšem takových jmen byste se měli vyvarovat i z jiných důvodů.
↑ LINKPATH=

Je-li linkovaný soubor specifikován bez cesty, €ASM jej bude hledat v adresářích definovaných ve volbě EUROASM LINKPATH=. Cesty zde mohou být odděleny středníkem ; nebo čárkou , a celý seznam cest by měl být v uvozovkách. Jako oddělovač složek lze použít zpětné \ i dopředné / lomítko. Poslední lomítko může být vynecháno. Výchozí hodnotou je LINKPATH="./,./objlib,../objlib,".

↑ RUNPATH=

Je-li dynamicky sdílený objekt (DSO neboli objekt ELFSO) specifikován bez cesty, Linuxový dynamický linker jej bude hledat v adresářích definovaných touto volbou EUROASM RUNPATH=. Výchozí hodnotou je RUNPATH="./,./objlib,../objlib,".

↑ MAXINCLUSIONS=

Parametr MAXINCLUSIONS omezuje maximální povolený počet úspěšných provedení příkazů INCLUDE*. Brání to ve vyčerpání prostředků, pokud bychom omylem zadali rekurzivní smyčku INCLUDE.

Výchozí hodnota je EUROASM MAXINCLUSIONS=64.

↑ MAXLINKS=

Tento parametr omezuje maximální povolený počet linkování souborů. Opět to chrání před rekurzivní smyčkou příkazů LINK.

Výchozí hodnotou je EUROASM MAXLINKS=64.

↑ CPU=

Ne všechny strojové instrukce architektury IA-32 jsou dostupné na všech typech procesorů. Tato volba EUROASM určuje minimální (nejstarší) model CPU, na kterém má program běžet. Možnosti jsou
086 alias 8086,
186,
286,
386,
486,
586 alias PENTIUM,
686 alias P6,
X64.
Výchozí hodnota je EUROASM CPU=586. 64bitové programy potřebují povolit EUROASM CPU=X64.

EuroAssembler se chová, jako když vyšší verze CPU podporuje všechny instrukce předchozích verzí.
↑ Rozšíření CPU

Následující skupina booleovských voleb říká EuroAssembleru, která rozšíření procesoru jsou vyžadována na cílovém počítači. Ve výchozím stavu jsou všechny volby vypnuty, musíte explicitně povolit každé rozšíření, pro něž budete programovat.

ABM=: instrukce Advanced Bit Manipulation.

AES= instrukce Advance Encryption Standard (AESNI).

AMD= instrukce specifické pro výrobce CPU AMD.

CET= instrukce Control-flow Enforcement Technology.

CYRIX= instrukce specifické pro výrobce CPU CYRIX.

D3NOW= instrukce 3DNow! od AMD.

EVEX= instrukce AVX-512 kódované s prefixem EVEX.

FMA=: instrukce Fused Multiply-Add.

FPU= instrukce pro Floating-Point Unit (matematický koprocesor).

LWP= instrukce pro LightWeight Profiling od AMD.

MMX=: instrukce pro MultiMedia Extensions.

MPX=: instrukce pro Memory Protection Extensions.

MVEX= instrukce AVX-512 kódované s prefixem MVEX.

PRIV=: instrukce v privilegovaném módu.

PROT=: instrukce v chráněném módu.

SGX=: instrukce pro Software Guard Extensions.

SHA= instrukce pro Secure Hash Algorithm od Intelu.

SPEC= ostatní speciální instrukce.

SVM=: instrukce pro Shared Virtual Memory.

TSX=: instrukce pro Transactional Synchronization Extensions od Intelu.

UNDOC= nedokumentované instrukce.

VIA= instrukce specifické pro výrobce CPU VIA Geode.

VMX= instrukce pro Virtual Machine Extensions.

XOP= instrukce AVX kódované s prefixem XOP od AMD.

↑ SIMD=

Tato volba definuje, která generace instrukcí Single Instruction Multiple Data (SIMD) je vyžadována k překladu následných instrukcí. Možné výčtové hodnoty jsou
SSE1 alias SSE alias booleovské pravda,
SSE2,
SSE3,
SSSE3,
SSE4,
SSE4.1,
SSE4.2,
AVX,
AVX2,
AVX512. Výchozí hodnotou je SIMD=DISABLED (neočekávají se žádné instrukce SIMD).

Volby generace CPU, rozšíření CPU, generace SIMD neomezují €ASM v překladu instrukcí pro vyšší procesor, avšak pokud strojová instrukce vyžaduje generaci momentálně nepovolenou volbami EUROASM, bude vydáno varování. To by mělo upozornit, že program nepoběží na každém PC, případně že jste se dopustili překlepu v menmonice.
↑ DISPLAYSTM=
↑ DISPLAYENC=

Tyto dvě booleovské volby jsou určeny k ladění samotného procesu překladu, viz také pseudoinstrukci %DISPLAY. Jsou-li volby povoleny, €ASM vkládá pod každou asemblovanou instrukci diagnostické oznámení zobrazující, jak byla instrukce rozdělena do polí a jaké instrukční modifikátory byly použity při jejím zakódování.Příklad:

    EUROASM DISPLAYSTM=ON
.L: MOV EAX,[ESI+16],ALIGN=DWORD
    EUROASM DISPLAYSTM=OFF, DISPLAYENC=ON
    LEA EDX,[ESI+16]
    ADD EAX,EDX

Listing předchozího příkladu:

| | EUROASM DISPLAYSTM=ON |00000000:8B4610 |.L: MOV EAX,[ESI+16],ALIGN=DWORD |# D1010 **** DISPLAYSTM ".L: MOV EAX,[~~ALIGN=DWORD " |# D1020 label=".L" |# D1040 machine operation="MOV" |# D1050 ordinal operand number=1,value="EAX" |# D1050 ordinal operand number=2,value="[ESI+16]" |# D1060 keyword operand,name="ALIGN",value="DWORD" | | EUROASM DISPLAYSTM=OFF, DISPLAYENC=ON |# D1010 **** DISPLAYSTM "EUROASM DISPL~~SPLAYENC=ON " |# D1040 pseudo operation="EUROASM" |# D1060 keyword operand,name="DISPLAYSTM",value="OFF" |# D1060 keyword operand,name="DISPLAYENC",value="ON" |00000003:8D5610 | LEA EDX,[ESI+16] |# D1080 Emitted size=3,DATA=DWORD,DISP=BYTE,SCALE=SMART,ADDR=ABS. |00000006:01D0 | ADD EAX,EDX |# D1080 Emitted size=2,CODE=SHORT,DATA=DWORD.
↑ DUMP=
↑ DUMPWIDTH=
↑ DUMPALL=

Volby DUMP=, DUMPWIDTH= and DUMPALL= ovlivňují vzhled sloupce s emitovaným kódem v souboru listingu.

Booleovská volba DUMP= kompletně vypíná tento sloupec; listing pak kopíruje zdrojový text takřka doslovně. Výchozí hodnota je DUMP=ON.

DUMPWIDTH= nastavuje šířku levého sloupce v listingu, neboli určuje počet znaků, které se vejdou mezi počáteční | a koncovou svislou čáru | (včetně těchto dvou znaků). Výchozí hodnota je DUMPWIDTH=27, což vyhovuje pro instrukce dlouhé až 8 bajtů.

Povolená hodnota tohoto parametru je mezi 16 a 128 znaky.

Vypisovaná data sestávají z ofsetu (4 nebo 8 hexadecimálních číslic), separátoru : a dvou hexadecimálních číslic na každý bajt generovaného kódu.

Je-li generovaný kód delší, než se vejde do sloupce dumpu, booleovská volba DUMPALL= rozhoduje, zda zbytek kódu bude zahozen (vypuštění je indikováno tildou ~ místo posledního znaku), nebo zda do listingu budou vkládány přídavné řádky, dokud nebude všechen generovaný kód vypsán. Výchozí volba je DUMPALL=OFF.

Viz také popis souboru listingu.

Opatrně s povolováním DUMPALL=ON s dlouhými definicemi dat, jako DB 2048 * B 0, které mohou zahltit listing mnoha řádky bezcenného výpisu.
↑ LISTFILE=

Volba určuje název souboru s listingem. Jako výchozí volba se používá LISTFILE="%^SourceName%^SourceExt.lst", tedy kopie jména a přípony zdrojového souboru, ke které se připojí .lst.
Není-li určeno jinak, listing se vytváří ve stejném adresáři jako jeho zdrojový soubor. Ke každému zdrojovému souboru se generuje jeho listing.

↑ LIST=
↑ LISTINCLUDE=
↑ LISTMACRO=
↑ LISTREPEAT=
↑ LISTVAR=

Rodina booleovských voleb EUROASM LIST* určuje, co se bude zapisovat do souboru listingu. LIST=OFF zcela potlačí generování listingu, dokud není opět zapnut pomocí LIST=ON. Výchozí volba je LIST=ON.
Vypnutí byť jen malé části listingu způsobí, že již nebude znovupoužitelný jako zdrojový soubor,

Obsah souboru importovaného pomocí INCLUDE* je ve výchozím stavu vynechán z listingu (LISTINCLUDE=OFF). Pokud je tato volba zapnuta (LISTINCLUDE=ON), z pseudoinstrukce INCLUDE se stane komentář a pod ní budou uvedeny všechny instrukce ze souboru.

LISTMACRO= určuje, zda instrukce z expanze makra budou zobrazeny v listingu. Výchozí stav je LISTMACRO=OFF, kdy je zobrazena pouze invokace (volání) makra.

Volba LISTREPEAT= se podobá LISTMACRO= až na to, že řídí vypisování obsahu bloků %FOR, %WHILE a %REPEAT.
Ve výchozím stavu (LISTREPEAT=OFF) se vypisuje pouze první iterace bloku.

Pokud se v instrukci vyskytuje preprocesní %proměnná a pokud je volba EUROASM LISTVAR=ON, instrukce je v listingu duplikována pod původní instrukcí jako její komentář, avšak %proměnné jsou přitom nahrazeny expandovaným textem. Výchozí volba je LISTVAR=OFF.

Viz také popis listingového souboru výše.

↑ UNICODE=

Booleovská volba UNICODE= určuje šířku znaků. Jsou-li neurčité řetězce definovány bez typového určení B nebo U pomocí D "neurčitý řetězec" nebo ="literální neurčitý řetězec", tato volba určuje, zda se mají považovat za řetězce bajtů (8bitových znaků) nebo unichar (16bitových znaků).

Hodnota UNICODE signalizovaná %^proměnnou %^UNICODE je rovněž konzultována v makrech a definicích struktur, které mají odlišné verze pro ANSI (8bitové) nebo WIDE (16bitové) kódování.
Dále je konzultována v makrech WinAPI (32 bitů) a WinABI (64 bitů) k určení verze Windows API funkce (ANSI nebo WIDE), jež má být volána.

Mnoho funkcí ve WinAPI očekává specifikaci délky řetězců ve znacích namísto v bajtech. Atributový operátor SIZE# vrací velikost řetězce vždy v bajtech. Tento rozpor se dá vyřešit pomocí systémové %^proměnné %^UNICODE:

aString D "String" ; Symbol aString definuje 6 bajtů, pokud UNICODE=OFF anebo 12 bajtů, pokud UNICODE=ON.
  %IF %^UNICODE  ; Symbol je ve WIDE verzi.
     MOV ECX, SIZE# aString / 2
  %ELSE          ; Symbol je v ANSI verzi.
     MOV ECX,SIZE# aString
  %ENDIF         ; ECX je nyní naplněn počtem znaků v aString.

Vychytralejší řešení využívá faktu, že %^UNICODE (a všechny další booleovské %^proměnné) expanduje buď do 0 nebo do -1, a že posun vlevo o negativní hodnotu je kalkulován jako posun vpravo o negovanou hodnotu. Je-li %^UNICODE=-1, velikost v bajtech bude posunuta doprava o 1 bit, což odpovídá dělění dvěma:

aString D "String" ; Symbol aString definuje 6 bajtů, pokud UNICODE=OFF anebo 12 bajtů, pokud UNICODE=ON.
  MOV ECX, SIZE# aString << %^UNICODE  ; ECX je nyní naplněn počtem znaků v aString.
↑ DEBUG=

Tato booleovská volba specifikuje, zda má být přeložena ladicí verze programu. Když je EUROASM DEBUG=ENABLED, linker zařazuje tabulku symbolů nebo další ladicí informace do výstupního programu (formátu PE). Makra mohou měnit své chování v závislosti na podmínce %IF %^DEBUG.

Konečné vydání vašeho programu by mělo být přeloženo s touto vobou vypnutou.

↑ PROFILE=

Tato booleovská volba specifikuje, zda má být přeložena profilovatelná verze programu. Profilování zatím v této verzi €ASM není implementováno.

Konečné vydání vašeho programu by mělo být přeloženo s touto vobou vypnutou.

↑ WARN=
↑ NOWARN=

Volby WARN= a NOWARN= určují, která informační a varovná oznámení mají být vydávána během činnosti asembleru. Pomocí NOWARN= lze potlačit oznámení s identifikátorem pod 4000. Potlačená oznámení nemají vliv na konečnou hodnotu ERRORLEVEL. Uživatelem definovaná oznámení (U5000..U5999) a chyby s vyšší závažností potlačit nelze.

Hodnotou volby je buď číslo, nebo rozsah čísel (range), která by neměla přesáhnout 3999. Operandy WARN= a NOWARN= se mohou v pseudoinstrukci EUROASM opakovat, budou zpracovány zleva doprava. Například EUROASM NOWARN=0600..0999, WARN=705 potlačí informativní oznámení I0600 až I0999 s výjimkou oznámení I0705, které zůstává povoleno.

Výchozí hodnota je WARN=0..3999 (všechna oznámení povolena}.


↑ PROGRAM

↑ ENDPROGRAM

DLLCHARACTERISTICS= ↓
ENTRY= ↓
FILEALIGN= ↓
FORMAT= ↓
ICONFILE= ↓
IMAGEBASE= ↓
LISTLITERALS= ↓
LISTGLOBALS= ↓
LISTMAP= ↓
MAJORIMAGEVERSION= ↓
MAJORLINKERVERSION= ↓
MAJOROSVERSION= ↓
MAJORSUBSYSTEMVERSION= ↓
MAXEXPANSIONS= ↓
MAXPASSES= ↓
MINORIMAGEVERSION= ↓
MINORIMAGEVERSION= ↓
MINORLINKERVERSION= ↓
MINOROSVERSION= ↓
MINORSUBSYSTEMVERSION= ↓
MODEL= ↓
OUTFILE= ↓
SECTIONALIGN= ↓
SIZEOFHEAPCOMMIT= ↓
SIZEOFHEAPRESERVED= ↓
SIZEOFSTACKCOMMIT= ↓
SIZEOFSTACKRESERVED= ↓
STUBFILE= ↓
SUBSYSTEM= ↓
TIMESTAMP= ↓
WIDTH= ↓
WIN32VERSIONVALUE= ↓

Pseudoinstrukce PROGRAM a ENDPROGRAM definují blok zdrojového kódu, který generuje samostatný výstupní soubor. V mnoha jiných asemblerech je to celý zdrojový soubor, který vytváří výstupní soubor, někdy zvaný modul nebo jednotka kompilace. Například povel nasm -f win32 HelloWorld.asm -o HelloWorld.obj instruuje NetWide Assembler, aby z celého zdrojového souboru HelloWorld.asm vygeneroval soubor ve formátu COFF HelloWorld.obj. V €ASM může být z jednoho zdrojového souboru generován více než jeden výstupní soubor povelem euroasm HelloWorld.asm, pokud zdrojový soubor obsahuje více než jeden blok PROGRAM..ENDPROGRAM.

Návěstí pseudoinstrukce PROGRAM reprezentuje název výstupního programu. I když nedefinuje symbol, jméno musí dodržovat pravidla pro názvy symbolů, tj. písmeno následované dalšími písmeny a číslicemi. Tentýž identifikátor může být použit jako první a jediný operand odpovídající pseudoinstrukce ENDPROGRAM.

Jeden zdrojový soubor může obsahovat více programových bloků a tyto se mohou vnořovat. Každý blok PROGRAM..ENDPROGRAM se překládá do jiného výstupního souboru.

Symboly definované v programu nejsou viditelné mimo svůj blok PROGRAM.ENDPROGRAM. Chce-li program volat návěstí z jiného programu, musí být označeno jako EXTERN a PUBLIC, i kdyby oba programy ležely v jednom zdrojovém souboru nebo kdyby byl jeden vnořen ve druhém.

Na druhé straně preprocesní %proměnné, definice maker a volby EUROASM jsou viditelné v celém zdrojovém souboru a mohou tak přenášet informace mezi programy v asm-time. Viz vzorový program LockTest jako příklad.

Pseudoinstrukce PROGRAM má spoustu klíčových parametrů specifikujících vlastnosti výstupního souboru. Stejné klíče jsou použity v oddílu [PROGRAM] konfiguračního souboru euroasm.ini

Hodnoty všech voleb programu mohou být zjišťovány v asm-time pomocí systémových %^proměnných. Například v oznámení InfoMsg DB "This is a %^WIDTH-bit program.",13,10,0 bude systémová %^proměnná %^WIDTH nahrazena aktuální šířkou programu (16, 32 nebo 64).

Na rozdíl od klíčových parametrů EUROASM, které ovlivňovaly pouze část souboru, volby u pseudoinstrukce PROGRAM ovlivňují celý program en bloc. Nemůžeme mít půlku programu s grafickým subsystémem a zbytek s konzolovým. Proto jsou volby LISTMAP=, LISTGLOBALS=, LISTLITERALS= vlastnostmi pseudoinstrukce PROGRAM, ale LISTINCLUDE=, LISTMACRO=, LISTREPEAT=, LISTVAR= jsou vlastnostmi EUROASM.
↑ FORMAT=

Formát a souborová přípona výstupního souboru je určena tímto parametrem programu.

Výchozí vlastnosti formátů
FORMAT=Přípona
výstupního souboru
Šířka
programu
Paměťový
model
Popis formátu
BIN.bin16bitsTINYBinární soubor
BOOT.sec16bitsTINYBootovatelný soubor
COM.com16bitsTINYSpustitelný soubor DOS/CPM
ELF.o32bitsFLATLinkovatelný objektový modul
ELFX.x32bitsFLATSpustitelný soubor pro Linux
ELFSO.so32bitsFLATDynamicky sdílený soubor pro Linux
OMF.obj16bitsSMALLLinkovatelný objektový modul
LIBOMF.lib16bitsSMALLObjektová knihovna ve formátu OMF
MZ.exe16bitsSMALLSpustitelný program pro DOS
COFF.obj32bitsFLATLinkovatelný objektový modul
LIBCOF.lib32bitsFLATObjektová knihovna ve formátu COFF
PE.exe32bitsFLATSpustitelný program pro MS-Windows
DLL.dll32bitsFLATDynamická knihovna pro MS-Windows

Výchozí formát (při vynechání PROGRAM FORMAT=) je BIN. Viz také programové formáty níže pro více podrobností.

↑ WIDTH=

Tento parametr určuje šířku a mód programu:

Programová šířka zároveň představuje výchozí šířku všech jeho segmentů. Její hodnotou je číselný výraz vyhodnocený jako 16, 32, 64, nebo 0. Prázdná nebo nulová hodnota (výchozí stav) určuje, že šířku programu má stanovit interně €ASM v souladu s výchozími šířkami v tabulce FORMAT=. Nicméně pokud je segment definován, můžeme mu předepsat odlišnou šířku. €ASM neprotestuje proti mísení 16bitových a 32bitových segmentů v jednom programu.

↑ MODEL=

Paměťový model určuje velikosti a distance kódu a dat. Jeho hlavní funkcí je nastavit výchozí hodnotu vzdáleností (DIST) pro segmenty a procedury v programu.

Programová volba MODEL= se bere v úvahu v procedurách (PROC, PROC1) a v instrukcích předávání zpracování (JMP, CALL, RET) bez explicitně stanovené distance.
V monokódových modelech (TINY,SMALL,COMPACT,FLAT) je výchozí vzdálenost DIST=NEAR.
V mnohokódových modelech (MEDIUM,LARGE,HUGE) je výchozí vzdálenost DIST=FAR.
V monodatových modelech (TINY,SMALL,MEDIUM,FLAT) jsou všechna data adresována relativně k začátku datové grupy.
V mnohodatových modelech (COMPACT,LARGE,HUGE) je na programátorovi, aby naplnil segmentový registr paragrafovou adresou dat, než k nim bude přistupováno.

Vlastnosti implikované paměťovým modelem
MODEL=Výchozí vlastnosti segmentu Vlastnosti při linkováníObvyklé využití
Distance
CODE
Distance
DATA
Šířka
segmentu
Mnoho-
kódový
Mnoho-
datový
Překrývání
segmentů
Mód
CPU
Použito ve formátech
TINYNEARNEAR16neneanorealCOM
SMALLNEARNEAR16nenenerealMZ, OMF
MEDIUMFARNEAR16anonenerealMZ, OMF
COMPACTNEARFAR16neanonerealMZ, OMF
LARGEFARFAR16anoanonerealMZ, OMF
HUGEFARFAR32anoanonerealMZ, OMF
FLATNEARNEAR32,64neneanoprotectedELF, PE, DLL, COFF

Prázdná hodnota (výchozí stav) určuje, že paměťový model má stanovit interně €ASM v souladu s hodnotou v tabulce FORMAT=.

↑ SUBSYSTEM=

Subsystém je číselný identifikátor v hlavičce souboru Portable Executable, který specifikuje, zda MS-Windows má vytvářet novou konzolu když PE program startuje. Hodnotou subsystému je číslo nebo jedno ze slov vyjmenovaných v této tabulce:

Tabulka subsystémů
SUBSYSTEM=HodnotaPoznámka
00Neznámý subsystém.
1NATIVESubsystém není použit (ovladač zařízení).
2GUIGrafický subsystém MS-Windows.
3CONKonzolový (znakový) subsystém MS-Windows.
5OS2Znakový subsystém OS/2.
7POSIXZnakový subsystém Posix.
8WXDNativní ovladač MS-Windows 95/98.
9WCEGrafický subsystém MS-Windows CE.

Výchozí hodnota je SUBSYSTEM=CON. Změňte ji na SUBSYSTEM=GUI, pokud váš spustitelný program vytváří grafická okna, místo aby se spokojil se standardním textovým vstupem a výstupem.

↑ ENTRY=

Tento parametr určuje adresu, od které začíná běžet spustitelný program. Obvykle je to návěstí, jehož adresa bude vložena do CS:rIP když zaváděč předává zpracování programu při jeho spuštění.

Výchozí hodnota parametru je prázdná, v tom případě ji €ASM nastaví na 0 pokud PROGRAM FORMAT=BIN nebo na 256 pokud PROGRAM FORMAT=COM nebo na 0x7C00 pokud PROGRAM FORMAT=BOOT. U ostatních spustitelných programů €ASM ohlásí chybu, když ENTRY= nebylo zadáno.

↑ MAXPASSES=

Tento parametr omezuje počet průchodů zdrojovým kódem od pseudoinstrukce PROGRAM až po ENDPROGRAM. O počtu průchodů rozhoduje €ASM, tento parametr pouze určuje horní limit.

EuroAssembler opakuje průchody, dokud se mění ofsety symbolů. Jakmile jsou všechny stabilní, provede poslední (finální) průchod.

Za určitých (vzácných) okolností to může vést k oscilacím délky emitovaného kódu kvůli optimalizacím délky SHORT a NEAR skoků. V tom případě by €ASM vyžadoval další a další průchody. Jakmile se číslo průchodu přiblíží k %^MAXPASSES-1, tento předposlední průchod se označí jako fixing pass. V tomto průchodu mohou ofsety pouze růst ke vyšším hodnotám; nadbytečné místo se zaplňuje bajty prázdné operace NOP. Viz test t7181 coby příklad oscilujícího programu s fixing průchodem.

Výchozí hodnotou je MAXPASSES=32. Asi ji budete potřebovat zvýšit jen v extrémních případech programů se spoustou maker a podmíněných konstruktů. Ve svých programech jsem dosáhl maxima 44 průchodů spotřebovaných během překladu modulu iiz.htm.
↑ MAXEXPANSIONS=

Parametr MAXEXPANSIONS= omezuje počet expanzí bloků typu %FOR, %WHILE, %REPEAT nebo %MACRO. €ASM deklaruje číselnou vlastnost programu zvanou %. a zvyšuje její hodnotu při expanzi bloku. Jakmile hodnota přesáhne volbu MAXEXPANSIONS, €ASM vydá oznámení o chybě a další expanze zastaví.
Výchozí hodnota je MAXEXPANSIONS=65536.

Tento mechanismus chrání €ASM před vyčerpáním paměťových prostředků, pokud některá špatně napsaná preprocesní smyčka včas neskončí.

Totéž počitadlo expanzí se využívá k udržování hodnoty automatické %proměnné %..

↑ OUTFILE=

Volba OUTFILE= specifikuje jméno spustitelného nebo linkovatelného výstupního souboru. Jméne je vztaženo k aktuálnímu adresáři, není-li specifikováno jinak. Výchozí hodnotou je OUTFILE="%^PROGRAM" následovaný příponou určenou volbou FORMAT=.
Kupříkladu Hello PROGRAM FORMAT=MZ generuje výstupní soubor "Hello.exe".

Na jméno výstupního souboru lze aplikovat operátor(y) suboperace, například OutFile="MyData.bin"[1..256] zkompiluje celý modul v paměti, avšak pouze prvních 256 bajtů bude zapsáno do výstupního souboru MyData.bin. Viz také vzorový program binboot.htm jako praktický příklad využití suboperace substring.

↑ STUBFILE=

Volba STUBFILE= má význam pouze u spustitelných souborů ve formátu PE nebo DLL. Stub je 16bitový program formátu MZ, který se dostane ke slovu, když je soubor určený pro Windows nedopatřením spuštěn v 16bitovém operačním systému (DOS). Obvykle je jeho úlohou pouze informovat uživatele, že this program requires MS-Windows.

Je-li volba STUBFILE prázdná (default), €ASM použije svůj vlastní vestavěný soubor stub. Jinak zde očekává předem zkompilovaný spustitelný MZ program. Byl-li STUBFILE= specifikován bez cesty, €ASM jej hledá v cestách určených volbou EUROASM LINKPATH=.

Předepsaný 16bitový program stub může mít stejnou funkcionalitu jako hlavní aplikace pro 32bitové Windows. Takový spustitelný program pak pracuje stejně v DOSu i v MS-Windows. Jako ukázku viz vzorový projekt LockTest.
↑ ICONFILE=

Volba ICONFILE= by měla definovat existující soubor obsahující pouze ikonu pro Windows, která pak bude vestavěna do segmentu zdrojů [.rsrc] našeho programu ve formátu PE nebo DLL. Tato ikona bude graficky reprezentovat výstupní program v prostředí Windows (Plocha, Průzkumník atd.).
Byl-li soubor ikony specifikován bez cesty, bude se hledat v některém adresáři určeném volbou EUROASM LINKPATH=.

Výchozí hodnotou je EUROASM ICONFILE="euroasm.ico", což představuje ikonu Icon dodávanou s EuroAssemblerem ve složce objlib.

Volba ICONFILE= se uplatní pouze pokud žádný soubor resources není linkován do výstupního programu, jinak se ignoruje a bude místo něj použita první ikona ze souboru resources.

Je-li parametr ICONFILE= prázdný, ikona není použita a €ASM sekci resources vůbec nevytváří.

↑ LISTMAP=
↑ LISTGLOBALS=
↑ LISTLITERALS=

Tyto tři volby určují, která přídavná informace bude vypisována na konec listingového souboru. Viz test t8302 jako příklad formátu ListMap a ListGlobals.

Je-li LISTLITERALS=ON, obsah datové a kódové literální sekce @LT16, @LT8, @LT4, @LT2, @LT1, @RT0 bude vypsán do listingu. Viz test t1711 jako příklad formátu ListLiterals.

↑ TIMESTAMP=

Tato volba specifikuje nominální čas poskytovaný systémovým %^proměnným EuroAssembleru %^DATE a %^TIME, a který bude také zabudován do některých struktur COFF formátu: PFCOFF_FILE_HEADER.TimeDateStamp, PFLIBCOF_IMPORT_OBJECT_HEADER.TimeDateStamp, PFRSRC_RESOURCE_DIRECTORY.TimeDateStamp.

Hodnota tohoto parametru představuje počet sekund, které uběhly od půlnoci 1. ledna 1970, UTC. Pokud je nastavena na -1 nebo nechána prázdnou (výchozí stav), bude nastavena podle systémového časovače při startu euroasm.exe.
TIMESTAMP= lze využít ke zfalšování času, kdy byl cílový program vytvořen.

↑ DLLCHARACTERISTICS=
↑ FILEALIGN=
↑ IMAGEBASE=
↑ MAJORIMAGEVERSION=
↑ MAJORLINKERVERSION=
↑ MAJOROSVERSION=
↑ MAJORSUBSYSTEMVERSION=
↑ MINORIMAGEVERSION=
↑ MINORLINKERVERSION=
↑ MINOROSVERSION=
↑ MINORSUBSYSTEMVERSION=
↑ SECTIONALIGN=
↑ SIZEOFHEAPCOMMIT=
↑ SIZEOFHEAPRESERVED=
↑ SIZEOFSTACKCOMMIT=
↑ SIZEOFSTACKRESERVED=
↑ WIN32VERSIONVALUE=

Ostatní parametry pseudoinstrukce PROGRAM jsou obvykle důležité pouze v souborech rodiny COFF (PE, DLL, COFF), kde tvoří PE header. Pro jejich podrobnější popis viz [MS PECOFF]. Neměňte jejich výchozí hodnoty, pokud nevíte, co děláte.

↑ SEGMENT

PURPOSE= ↓
WIDTH= ↓
ALIGN= ↓
COMBINE= ↓
CLASS= ↓

Pseudoinstrukce SEGMENT deklaruje paměťový segment a určuje jeho vlastnosti. Každá deklarace segmentu zároveň deklaruje sekci stejného jména. Další sekce tohoto segmentu mohou být deklarovány později, instrukcí s názvem sekce v poli návěstí, např.
[Strings] ; Deklaruj sekci [Strings] v aktuálním segmentu. .

Jméno segmentu je zadáno v poli návěstí a vypadá jako identifikátor v hranatých závorkách. Vlastnosti segmentu se zadávají pomocí klíčových operandů.

€ASM automaticky deklaruje několik výchozích segmentů když začíná překládat program. Ve většině případů to stačí a není třeba explicitně deklarovat další segmenty. Počet a účel výchozích segmentů záleží na programovém formátu. Pokud tyto výchozí segmenty nebyly v programu použity (nic do nich nebylo emitováno), budou zahozeny a vůbec se neobjeví v cílovém souboru. Dochází k tomu, pokud jsme nebyli spokojeni s výchozími segmenty a deklarovali své vlastní s odlišnými názvy a vlastnostmi.

↑ PURPOSE=

Klíčový operand SEGMENT PURPOSE= určuje, pro jaký druh informací je segment určen. Parametr je důležitý v chráněném módu (formáty ELFX, PE, DLL), kdy přístupové bity deskriptoru řídí operávnění číst, zapisovat a provádět obsah segmentu.

Tabulka účelů segmentu
PURPOSE=AliasPřístupVýchozí jménoObsahuje
CODETEXTread, execute[.text]|[CODE]Programový kód (instrukce) (1)
RODATARDATAread[.rodata]|[RODATA]Inicializovaná data pouze ke čtení (1)
DATAIDATAread, write[.data]|[DATA]Inicializovaná data (1)
BSSUDATAread, write[.bss]|[BSS]Neinicializovaná data (1)
STACKread, write[STACK]Strojový zásobník (1)
LITERALSLITERALread parazituje na jiných data/code segmentechLiterální sekce (2)
DRECTVEdiscarded[.drectve]Direktivy pro linker (3)
PHDRHlavičky programu (4)
INTERPDynamický interpreter (4)
SYMBOLS[.symtab] | [.dynsym]Symboly (4)
HASH[.hash]Kontrolní součty jmen symbolů (4)
STRINGS[.strtab] | [.dynstr] | [.shstrtab]Jména symbolů nebo sekcí (4)
DYNAMIC[.dynamic]Dynamické záznamy (4)
RELOC[.rel(a)*]Relokace (4)
GOT[.got]GOT - tabulka ofsetů (4)
PLT[.plt]PLT - tabulka procedur (4)
EXPORT[.edata]Dynamické exporty (4)
IMPORT[.idata]Dynamické importy (4)
RESOURCE[.rsrc]Resources (4)
EXCEPTION[.pdata]Run-time přerušení (5)
SECURITYCertifikáty (5)
BASERELOCdiscarded[.reloc]Load-time relokace (4)
DEBUG[.debug]Data pro debuger (5)
COPYRIGHTARCHITECTUREArchitektura (5)
GLOBALPTRRVA globálního pointeru (5)
TLS[.tls]Paměť vlákna (5)
LOAD_CONFIGNačtení konfigurace (5)
BOUND_IMPORTBound import (5)
IAT[.idata]Importní adresní tabulka (4)
DELAY_IMPORTZpožděný import (5)
CLR[.cormeta]Metadata CLR (5)
RESERVEDReservováno (5)
Poznámky:
(1) Základní účely používané ve všech programových formátech.
(2) Programátor může určit, který rodata|data|code segment by měl hostovat literální symboly.
(3) Umělá sekce pro přenos informací ve formátu COFF.
(4) Speciální sekce přímo používané EuroAssmeblerem. Neměly by být nikdy definovány explicitně.
(5) Speciální sekce, jejich obsah není podporován v €ASM. Programátor může zahrnout takové sekce do PE souboru, ale obsah pak musí být explicitně určen (pomocí D nebo INCLUDEBIN), viz program format PE.

Segmenty se speciálními jmény (4),(5) budou označeny na odpovídající pozici v tabulce DataDirectory ve "volitelné" hlavičce souboru PE nebo DLL.

Ačkoli operand PURPOSE= akceptuje pouze výčtové hodnoty vyjmenované ve výše uvedené tabulce, mohou být kombinovány použitím operátoru Addition + nebo Bitwise OR |, např.
[TINY] SEGMENT PURPOSE=CODE|DATA|BSS|STACK nebo
[.rodata] SEGMENT PURPOSE=DATA+LITERALS.

Není-li prametr PURPOSE= uveden, €ASM jej odhadne podle jeho třídy (class) nebo [názvu] za použití těchto pravidel:

  1. Pokud se jméno přesně shoduje s některým účelem vyjmenovaným v tabulce nahoře, bude použit tento účel.
  2. Obsahuje-li jméno řetěz STACK, bude použit PURPOSE=STACK.
  3. Obsahuje-li jméno řetěz BSS nebo UDATA, bude použit PURPOSE=BSS.
  4. Obsahuje-li jméno řetěz DATA, bude použit PURPOSE=DATA.
  5. Jinak bude použit PURPOSE=CODE.

PURPOSE=LITERALS je použit spolu s CODE nebo DATA a pouze navrhuje, že by tento segment měl hostovat literální sekce. Neby-li žádný segment explicitně označen s PURPOSE=LITERAL, €ASM vybere poslední datový nebo kódový segment, jakmile narazí na literální symbol.

Odhad účelu se nejprve dívá na vlastnost SEGMENT CLASS=, a pouze pokud je prázdná, dívá se na jméno segmentu.Tento mechanismus je použit se segmenty definovanými ve formátu OMF k předání jejich účelu do linkovaného spustitelného souboru.
↑ WIDTH=

Šířkou segmentu může být numerický výraz vyhodnocený jako 16, 32 nebo 64. Jako výchozí hodnota (při vynechání) je šířka segmentu určena šířkou programu.

↑ ALIGN=

Tento parametr požaduje zarovnání segmentu v paměti za běhu. Výchozí hodnotou je ALIGN=OWORD (16 bajtů).

Speciální ELF a PE segmenty, jako [.symtab], [.strtab], [.reloc] atd. mohou mít odlišné zarovnání.

↑ COMBINE=

Tento parametr specifikuje, jak budou segmenty z jiných programových modulů kombinovány při linkování. Je to důležité u programů typu MZ (16bitový pro DOS) sestavovaného z více modulů. Možné hodnoty:

PUBLIC
Všechny segmenty se shodným názvem budou spojeny dohromady. Celková velikost je součtem jejich velikostí, s příhlédnutím k jejich zarovnání. Toto je výchozí volba.
PRIVATE
Privátní segmenty nebudou spojovány s ostatními, ať již mají shodný název nebo ne.
COMMON
Všechny COMMON segmenty se stejným jménem budou linkovány na tutéž adresu, takže se navzájem překrývají. Jejich celková velikost odpovídá délce nejdelšího segmentu. Datové proměnné deklarované v COMMON segmentech budou sdíleny mezi samostatně překládanými moduly.
STACK
Metoda STACK je stejná jako PUBLIC, navíc ukazatel SS:SP v cílovém EXE souboru bude nastaven na konec segmentu.
↑ CLASS=

Hodnotou parametru CLASS= je nepovinný identifikátor. Může být použit linkerem k odhadnutí účelu segmentu (CODE|DATA|BSS) v objektových formátech, které nepřenášejí informaci o účelu segmentů (OMF).

↑ GROUP

Tato pseudoinstrukce určuje adresní rámec a vyjmenovává segmenty adresovatelné jedním segmentovým registrem.

Grupy segmentů se uplatní ve velkých 16bitových programech v reálném módu. Pouze 16bitový segment může být členem grupy.

Jméno grupy je definováno v poli návěstí pseudoinstrukce GROUP. Jména jejich segmentů jsou v poli operandů. všechna jména jsou v hranatých závorkách [ ]. Jméno grupy se může shodovat se jménem prvního segmentu. Příklad:
[DGROUP] GROUP [DATA],[STRINGS].
Segmenty patřící do grupy mohou být definovány před nebo po instrukci GROUP. Tato pseudoinstrukce nemá žádné klíčové operandy.

Vztah mezi grupou a jejími segmenty v době linkování se podobá vztahu mezi segmentem a jeho sekcemi v době překladu.


↑ PROC

↑ ENDPROC neboli ↑ ENDP

DIST= ↓
ALIGN= ↓
NESTINGCHECK= ↓

Pseudoinstrukce PROC a ENDPROC deklarují blok procedury a její jmenný prostor. Procedura často končí strojovou instrukcí RET, takže blok může být volán pomocí CALL. Po vykonání se vrací zpět za instrukci CALL.

Povinné návěstí pseudoinstrukce PROC deklaruje symbol, který je zároveň názvem procedury. Stejný identifikátor může být použit jako první a zároveň jediný operand odpovídající pseudoinstrukce ENDPROC.
Místo ENDPROC lze také používat její variantu ENDP.

Pseudoinstrukce ENDPROC může rovněž definovat své vlastní návěstí. To však nereprezentuje adresu návratu ze subprogramu, nýbrž ukazuje na kód následující po bloku PROC..ENDPROC. Návěstí ENDPROC je užitečné pouze, pokud je PROC..ENDP blok využit k definování jmenného prostoru a ne jako volatelný blok podprogramu. Příklady:

SubPgm:PROC ; Definuj PROC jako volatelný podprogram.
          ; Instrukce procedury jsou zde.
          TEST JakásiPodmínka
          JC .Abort:  ; Jdi k návratu a pak pod instrukci CALL SubPgm:.
          TEST JináPodmínka
          JC .End:    ; Jdi pod pseudoinstrukci .End: ENDP. Patrně ne to, co  programátor chtěl..
          ; Další instrukce procedury.
.Abort:   RET         ; Návrat pod instrukci CALL SubPgm:.
.End:  ENDP SubPgm:
NameSp:PROC ; Definuj PROC jako průchozí blok.
          ; Instrukce procedury jsou zde.
          TEST JakásiPodmínka
          JC .End:  ; Jdi pod pseudoinstrukci .End:  ENDP NameSp:.
          ; Další instrukce procedury. Chybí zde RET.
.End:  ENDP NameSp: ; Pokračuj pod touto instrukcí.

Pseudoinstrukce PROC, ENDPROC, PROC1, ENDPROC1 neemitují žádný strojový kód.

Skok na ENDPROC se liší od skoku na makroinstrukci EndProcedure definovanou v makroknihovně volacích konvencí.

K čemu vlastně jsou procedury dobré? Mohli bychom se bez nich snadno obejít, avšak zabalení kusu kódu do PROC..ENDPROC má svoje výhody:

↑ DIST=

Pseudoinstrukce PROC a PROC1 akceptují klíčové operandy DIST= and ALIGN=. DIST= nastavuje vzdálenost procedury (NEAR nebo FAR). Když je DIST=FAR, všechna volání této procedury jsou FAR, a všechny instrukce RET uvnitř této procedury jsou jako výchozí rovněž FAR. (lze to ovšem změnit přípomou instrukce, tedy CALLN/CALLF, RETN/RETF). Výchozí hodnota tohoto parametru zavísí na paměťovém modelu.

↑ ALIGN=

Výchozí zarovnání procedury je ALIGN=BYTE. Pro lepší výkonnost může být užitečné doplnit často volané procedury parametrem PROC ALIGN=OWORD, pokud není nárůst délky programu problém.

↑ NESTINGCHECK=

Tato booleovská volba dovoluje vypnout kontrolu párování návěstí v bloku PROC..ENDPROC. Má to jen vyjímečné uplatnění v makrech simulujících vestavěné pseudoinstrukce, které potřebují ošálit kontext, jako je Procedure a EndProcedure.

Viz také instrukční modifikátor NESTINGCHECK=.

Pseudoinstrukce PROC neakceptuje pořadové parametry proceduře předávané. Místo toho mohou být operandy předávány v registrech nebo na zásobníku. Makroknihovny volacích konvencí dodávané s EuroAssemblereme ale definují makra Procedure a EndProcedure s podobnou funkcí jako PROC a ENDPROC, které naopak dovolují předávání libovolného počtu operandů jako parametru maker, když je Procedura volána.

↑ PROC1

↑ ENDPROC1 neboli ↑ ENDP1

Pseudoinstrukce PROC1 a ENDPROC1 se podobají na PROC a ENDPROC, avšak jsou tu dva rozdíly:

  1. Procedura deklarovaná blokem PROC1..ENDPROC1 se může vyskytnout v programu více než jednou. Opakované deklarace PROC1..ENDPROC1 se stejným návěstím jsou ignorovány a emitovány pouze jednou.

    Předurčuje to použití PROC1 k definici napůl-inline maker, které obsahují jak volání procedury, tak i proceduru samotnou. Když je procedura definována v makru pomocí PROC1..ENDPROC1, takové makro může být voláno mnohokrát, ale volaná procedura bude přeložena a emitována pouze jednou, během první expanze makra.

  2. Blok definovaný pomocí PROC1..ENDPROC1 není emitován do aktuální sekce. €ASM místo toho automaticky přepne do odlišné kódové sekce a k původní sekci se vrátí až po zpracování ENDPROC1. Sekce, do níž €ASM přepíná, se jmenuje [@RT1] a je automaticky zřízena v segmentu s účelem PURPOSE=CODE+LITERAL nebo v naposledy definovaném kódovém segmentu. V některých případech může €ASM použít také sekce [@RT2], [@RT3] atd. K tomu dochází, pokud kód uvnitř bloku PROC1..ENDPROC1 obsahuje další napůl-inline makra, takže aktuální sekce již je [@RT1] a €ASM musí zvolit odlišnou sekci.

    Emitování procedur do odlišné sekce než hlavní program má také výhodu, že taková procedura nemusí být přeskakována pomocí JMP. Často to vede ke kratšímu programu, neboť skok přes napůl-inline makro nemusí přeskakovat celé tělo procedury, což by jinak mohlo překročit 128 bajtovou hranici a vyžadovat delší variantu skokové instrukce.

↑ ENDHEAD

Blok deklarovaný pseudoinstrukcemi HEAD a ENDHEAD pouze vymezuje oddíl zdrojového kódu. Tento oddíl může být vložen do jiného zdrojového souboru pseudoinstrukcí INCLUDEHEAD nebo INCLUDEHEAD1. Blok obvykle obsahuje interface programovacího objektu (definice struktur, maker, konstant), které potřebujeme vložit do jiných, separátně překládaných modulů.

Návěstí pseudoinstrukce HEAD může být použito jako identifikátor bloku, avšak nevytváří symbol. V jednom zdrojovém souboru může být definováno více než jeden blok HEAD..ENDHEAD. Pokud jsou tyto bloky vnořeny jeden do druhého, bude vložen celý vnější (delší) blok.

Jazyky bez takového mechanismu musejí ukládat interface do separátních hlavičkových souborů. S pomocí HEAD.ENDHEAD je můžeme udržovat spolu s implementačním tělem v jednom kompaktním souboru.

↑ INCLUDE

Tato pseudoinstrukce začleňuje zdrojový soubor s názvem specifikovaným jako její operand do hlavního zdrojového textu. Příkaz INCLUDE je virtuálně nahrazen obsahem inkludovaného souboru.

Inkluze mohou být vnořeny, tj. vložený soubor může obsahovat další povely INCLUDE.

Dvojité uvozovky mohou být vynechány, pokud jméno souboru obsahuje pouze alfanumerické znaky bez mezer a punktuace.

Každá pseudoinstrukce INCLUDE může mít neomezený počet operandů, např. INCLUDE "Win*.htm", ./MyConstants.asm, C:\MyLib\*.inc.

Je-li soubor specifikován bez cesty, bude hledán ve složkách definovaných volbou EUROASM INCLUDEPATH=. Obsahuje-li jméno souboru aspoň jedno lomítko nebo dvojtečku / \ : , znamená to, že bylo specifikováno s vlastní cestou a INCLUDEPATH= se v takovém případě ignoruje.

Název souboru může obsahovat žolíkové znaky * ?, v tom případě €ASM začlení všechny soubory odpovídající masce. Pořadí inkluze záleží na operačním systému.

Chování INCLUDE je popsáno v této tabulce:

CestaŽolíkPříklad Pokud je nalezen aspoň jeden souborPokud nebyl nalezen žádný soubor
NeNefile.incHotovo, nehledej dále v INCLUDEPATH.Error E6914.
AnoNe./file.incHotovo.Error E6914.
NeAnofile*.incProhledávej další soubory v INCLUDEPATH.Nic nebylo vloženo, nehlas žádnou chybu.
AnoAno./file*.incPokračuj v hledání v dané cestě.Nic nebylo vloženo, nehlas žádnou chybu.

Pokud byl bezprostředně za jméno souboru přidán operátor substring nebo sublist, bude vložena pouze část takového souboru. Příklad: INCLUDE "file.inc"{%&-20..%&} začlení posledních dvacet řádků file.inc (automatická %proměnná %& reprezentuje počet řádků v souboru). Jméno souboru musí být v uvozovkách, pokud je použita suboperace. Pokud název souboru obsahuje žolíkové znaky * ?, suboperace se bude vztahovat na všechny soubory vyhovující masce.

↑ INCLUDE1

Pseudoinstrukce include jednou se chová stejně jako INCLUDE, ale nejprve se podívá, zda už nebyl vložen stejný soubor (se stejnou velikostí a obsahem, bez ohledu na jméno). V takovém případě jej přeskočí.

Používání INCLUDE1 namísto INCLUDE dovoluje vyřešit vzájemné závislosti zdrojových knihoven. Pokud některá knihovna používá makra, struktury a konstanty definované v jiné knihovně, můžeme volat INCLUDE1 jiná.knihovna.

↑ INCLUDEHEAD

Pseudoinstrukce INCLUDEHEAD začleňuje ze jmenovaného souboru pouze obsah bloků HEAD..ENDHEAD. Viz test t2420. Neexistuje-li ani jeden blok HEAD..ENDHEAD, nebo pokud je nekompletní (chybí ENDHEAD), €ASM ohlásí chybu.

Pokud je použita suboperace, je nejprve aplikována na celý soubor a bloky HEAD..ENDHEAD jsou hledány až v takto ořezaném zdroji.

↑ INCLUDEHEAD1

INCLUDEHEAD1 a INCLUDE1 se ignorují, pokud soubor nebo jen část z něho již byly vloženy do hlavního programu pomocí INCLUDE, INCLUDE1, INCLUDEHEAD nebo INCLUDEHEAD1.

Knihovna se považuje za již vloženou, pokud byla inkludována jako celek pomocí INCLUDE nebo INCLUDE1, pokud její interface byl inkludován pomocí INCLUDEHEAD nebo INCLUDEHEAD1, nebo pokud byla inkludována pouze její suboperovaná část.

↑ INCLUDEBIN

Na rozdíl od INCLUDE a INCLUDEHEAD nechápe tato pseudoinstrukce obsah souboru jako zdrojový kód k přeložení, ale emituje jeho obsah tak jak je na pozici určenou aktuálním ukazatelem $ aktuální sekce.

Vložení binárních dat by nemělo být zaměňováno s linkováním; neaktualizuje relokabilní adresy ani nespojuje externí symboly. Například povel INCLUDEBIN "C:\WINNT\Media\chimes.wav"[0x2C..] přeskočí prvních 0x2C bajtů hlavičky WAV ve zvukovém souboru a zavede jen zbytek (syrové hudební vzorky) do překládaného cíle, jako by byly definovány pomocí DB.

Viz též test t2470.

Pseudoinstrukce LINK určuje soubor(y), které by měly být linkovány do aktuálního programu.

Každý ordinální operand reprezentuje název souboru, může mít žolíkové znaky * ? a může být specifikován bez anebo s cestou. Relativní cesta odkazuje na aktuální adresář.

Neobsahuje-li jméno souboru cestu, bude hledáno ve všech adresářích definovaných volbou EUROASM LINKPATH=. Na rozdíl od inkludovaných souborů zde suboperace nejsou podporovány.

Linkovatelné soubory mají speciální interní strukturu, která by patrně byla suboperací poškozena.

Pozice příkazu LINK v programu není důležitá, k samotnému linkování dojde až bude poslední průchod programu končit. Pořadí linkovaných souborů však respektuje pořadí, v němž se objevily v příkazech LINK. Příklady:

 LINK Subproc.obj, "..\My modules\W*.obj"

Viz také statické linkování pro další informace

↑ PUBLIC

Pseudoinstrukce GLOBAL, PUBLIC, EXTERN, EXPORT, IMPORT nastavují viditelnost symbolu, což bude použito při linkování.

Symbol, jehož viditelnost se deklaruje, může být v poli návěstí nebo v poli operandů nebo v obojím. Více než jeden symbol může být deklarován jedním povelem. Dotyčné symboly mohou být odkazovány dopředu nebo zpětně.

Explicitní deklarace viditelnosti se může objevit potom nebo předtím, než je symbol definován či odkazován.

Příklad explicitní deklarace čtyř symbolů: Sym1 PUBLIC Sym2, Sym3, Sym4

Deklarace symbolu jako PUBLIC pouze sděluje EuroAssembleru, že symbol, který byl či bude definován někde jinde v programu, by měl být odkazovatelný z jiných staticky linkovaných modulů. Deklarace PUBLIC zatím symbol nevytváří, ve skutečnosti musí být definován někde jinde v tomtéž programu.

↑ EXTERN

Pseudoinstrukce EXTERN symbol říká EuroAssembleru, že tento symbol není definován v programu, takže odkazy na jeho adresu musí být v link-time záplatovány. Bylo by chybou definovat symbol deklarovaný jako EXTERN v tomtéž modulu. Místo toho bude symbol hledán v ostatních modulech v čase linkování a pouze linker může ohlásit chybu, pokud jej nenajde.

↑ GLOBAL

Pseudoinstrukci GLOBAL lze použít ke zjednodušení nakládání s viditelnostmi PUBLIC a EXTERN. Pokud je symbol deklarován jako GLOBAL, chová se buď jako PUBLIC nebo jako EXTERN, v závislosti na tom, zda byl či nebyl definován ve stejném programu.

Programátor ovšem ví, jestli symbol patří do aktuálního programu nebo ne, tak proč je deklarace PUBLIC a EXTERN duplikována pomocí GLOBAL? Mějme program PgmA definující PUBLIC symbol SymA a odkazující na EXTERN symbol SymB. Podobně program PgmB definuje SymB a odkazuje na SymA:
PgmA PROGRAM
      PUBLIC SymA
      EXTERN SymB
      CALL SymB: ; Reference na externí symbol.
SymA: RET        ; Definice public symbolu.
     ENDPROGRAM PgmA

PgmB PROGRAM
      PUBLIC SymB
      EXTERN SymA
      CALL SymA: ; Reference na externí symbol.
SymB: RET        ; Definice public symbolu.
     ENDPROGRAM PgmB
Nahradíme-li deklarace PUBLIC a EXTERN pomocí GLOBAL, stejná deklarace bude moci být použita ve všechn staticky linkovaných programech a můžeme ji copy&pastovat nebo inkludovat, což je snazší k údržbě.:
PgmA PROGRAM
      GLOBAL SymA, SymB
      CALL SymB: ; Reference na externi symbol.
SymA: RET        ; Definice public symbolu.
     ENDPROGRAM PgmA

PgmB PROGRAM
      GLOBAL SymA, SymB
      CALL SymA: ; Reference na externí symbol.
SymB: RET        ; Definice public symbolu.
     ENDPROGRAM PgmB
Další raison d'être direktivy GLOBAL je zpětná kompatibilita s NASM, který nezná direktivu PUBLIC a používá místo ní GLOBAL.

↑ IMPORT

Viditelnosti IMPORT a EXPORT se používají při dynamickém linkování, kdy náš program volá importovanou funkci z DLL. Tato pseudoinstrukce akceptuje klíčový parametr LIB=, jenž specifikuje soubor knihovny. Parametr LIB= lze vynechat, pokud jsou symboly importovány z výchozí knihovny MS-Windows kernel32.dll.
Knihovní soubor nemusí být v uvozovkách, pokud dodržuje DOSové konvence 8.3. Knihovna je vždy specifikována bez cesty. Operační systém má svoje vlastní pravidla ([WinDllSearchOrder]) týkající se adresářů, v nichž se mají knihovny hledat v bind-time.

↑ EXPORT

Viditelnost EXPORT se použije, když vytváříme dynamickou knihovnu; deklaruje symboly, které mají být importovány jinými programy. Podobně jako u PUBLIC, symbol označený pro EXPORT musí být dříve či později definován v programu.

Pseudoinstrukce EXPORT rozeznává dva klíčové parametry FWD= a LIB= specifikující, že exportovaný symbol (jméno funkce) je ve skutečnosti poskytováno jinou dynamickou knihovnou (definovanou pomocí LIB=) pod odlišným názvem symbolu (definovaným pomocí FWD=). Příklad:

kernel32 PROGRAM FORMAT=DLL
          EXPORT EnterCriticalSection, LIB="NTDLL.dll", FWD=RtlEnterCriticalSection
          ; Další kernelové funkce.
         ENDPROGRAM kernel32

Knihovna "kernel32.dll" nabízí API funkci RtlEnterCriticalSection, která je ve skutečnosti poskytována knihovnou "NTDLL.dll". V jiné verzi MS-Windows může být poskytnuta odlišnou knihovnou "XPDLL.dll", ale programy importující funkci z proxy knihovny "kernel32.dll" nebudou potřebovat aktualizaci ani rekompilaci.

↑ ALIGN

Tato pseudoinstrukce je určena k explicitnímu zarovnání aktuálního sekčního ukazatele $. Kupříkladu ALIGN OWORD v kódové sekci bude emitovat několik (0 až 15) bajtů instrukce NOP, takže další instrukce bude emitována na adresu zarovnanou k octwordu (16). V datové sekci ALIGN používá bajt NUL (0x00) namísto NOP (0x90) jako výplň.

Operand může být specifikován v krátké nebo dlouhé notaci: B, U, W, D, Q, T, O, Y, Z, BYTE, UNICHAR, WORD, DWORD, QWORD, TBYTE, OWORD, YWORD, ZWORD nebo jako aritmetický výraz vyhodnocovaný na mocninu dvou: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512.
ALIGN TBYTE zarovnává na 8.

Pseudoinstrukce ALIGN nesmí mít návěstí, ale může mít dva operandy. Ten druhý je určen k záměrnému "odrovnání"; nemusí být mocninou dvou, ale musí být menší než první operand. Například ALIGN OWORD, QWORD zarovná $ na lichý násobek osmi.
ALIGN 8,2 zarovná aktuální ofset na druhý bajt osmibajtového slova. Tomu vyhovují ofsety 2, 10, 18, 26 atd.

↑ STRUC

↑ ENDSTRUC

Struktura reprezentuje virtuální sekci datových deklarací, kterou si lze představit jako masku nebo mřížku položenou nad kusem paměti. Struktura je deklarována blokem STRUC..ENDSTRUC. Jediné instrukce použitelné v bloku jsou

  1. definice dat specifikované pseudoinstrukcí D a jejími klony, buď inicializované, nebo neinicializované
  2. instrukce pro explicitní zarovnání (pseudoinstrukce ALIGN)
  3. pseudoinstrukce STRUC a ENDSTRUC (€ASM dovoluje vnořené definice struktur)
  4. řádkové a značkovací komentáře
|[.data] ::::Section changed. |00000000: | ; Příklad deklarace struktury: |[MyStruc] |MyStruc: STRUC |00000000:................ |.Member1 D Q ; Neinicializovaný člen typu QWORD. |00000008:........ |.Member2 D D ; Neinicializovaný člen typu DWORD. |0000000C:........ | D D ; Neinicializovaný anonymní člen typu DWORD. |00000010:FF |.Member3 D B 255 ; Inicializovaný čle typu BYTE. |00000011:.. |.Member4 D B ; Neinicializovaný člen typu BYTE. |00000012:............ | ALIGN QWORD ; Zvětši velikost MyStruc na násobek QWORD. |00000018: | ENDSTRUC MyStruc |[.data] ::::Section changed. |00000000: | |00000000: | |00000000:18000000 | DD SIZE# MyStruc ; MyStruc je dlouhá 0x18 bajtů. |00000004:53000000 | DD TYPE# MyStruc ; Typ kterékoli struktury je 'S'. |00000008:00000000 | DD SEGMENT# MyStruc ; Segment/sekce/ofset kterékoli struktury je skalární nula. |0000000C: |

Deklarace struktury neemituje žádná data do cílového souboru. Data budou emitována nebo rezervována až když bude struktura skutečně použita v datové definici (v pseudoinstrukci D nebo DS). Říkáme tomu, že struktura bude instanciována.
Jsou-li v definici struktury definována inicializovaná data, budou použita k inicializaci odpovídajících členů při její instancionizaci. (pseudoinstrukcí D nebo DS), ledaže by byly explicitně redefinovány.

Definici dat ve struktuře musí mít lokální jména (začínající tečkou .).
To dovoluje použít

  1. stejná jména jako členy různých struktur
  2. a vyvarovat se konfliktu jmen, jsou-li definovány vícenásobné objekty téže struktury.

Každý člen dostává svůj ofset relativní k začátku struktury. Nezaáleží na tom, jaká programová sekce byla aktuální při deklaraci struktury. Každá deklarace dočasně vytváří svou vlastní pseudosekci s virtuální adresou 0.

Struktura musí dostat unikátní název definovaný v poli návěstí instrukce STRUC a volitelně také v poli operandu instrukce ENDSTRUC.

Na velikost struktury můžeme odkazovat pomocí atributu SIZE#Jméno_struktury.

Pseudoinstrukce STRUC akceptuje klíčový operand ALIGN= specifikující zarovnání instancí struktury, pokud je EUROASM AUTOALIGN=ON.
Není-li zarovnání explicitně požadováno v deklaraci STRUC, bude použito zarovnání závislé na šířce programu (PROGRAM WIDTH=), tedy WORD, DWORD nebo QWORD.

Viz testy t2500, t2501, t2504 pro více příkladů deklarací struktur.

↑ D, DB, DU, DW, DD, DQ, DT, DO, DY, DZ, DI, DS

Inicializovaná i neinicializovaná data jsou definována a rezervována pseudoinstrukcí D. Je-li v ní specifikována statická hodnota, data jsou definována. Pokud je hodnota vynechána, data jsou rezervována. Je-li nastavena volba EUROASM AUTOSEGMENT=ON, data typu INSTR způsobí přepnutí do kódové sekce, všechny ostatní definice dat přepínají do datové sekce a rezervace dat do sekce bss (neinicializovaná data).

|[.data] ::::Section changed. |00000000: |; Definice celých čísel: |00000000:01 | D BYTE 1 ; Definuj integer typu BYTE s hodnotou 1 za použití dlouhého typového jména. |00000001:00 ....AutoAlignment stuff. |00000002:0200 | D W 2 ; Definuj integer typu WORD s hodnotou 2 za použití zkratky typu. |00000004:03000000 | D D 3 ; Definuj integer typu DWORD s hodnotou 3. |00000008:0400000000000000 | D Q 4 ; Definuj integer typu QWORD s hodnotou 4. |00000010: |; Definice čísel s plovoucí tečkou: |00000010:0000A040 | D D 5.0 ; Definuj FP číslo s jednoduchou přesností s hodnotou 5. |00000014:00000000 ....AutoAlignment stuff. |00000018:0000000000001840 | D Q 6.0 ; Definuj FP číslo s dvojitou přesností s hodnotou 6. |00000020:00000000000000E0~| D T 7.0 ; Definuj FP číslo s rozšířenou přesností s hodnotou 7. |0000002A: | ; Definice řetězců: |0000002A:4279746573 | D B "Bytes" ; Definuj řetězec bajtů |0000002F:00 ....AutoAlignment stuff. |00000030:55006E0069006300~| D U "Unichars" ; Definuj řetězec unicharů. |00000040:4368617273 | D "Chars" ; Definuj řetězec znaků (záleží na volbě UNICODE=). |00000045: | ; Definice instrukčního kódu: |[.text] ::::Section changed. |00000000:90 | D INSTR "NOP" ; Definuj operační kód instrukce NOP za použití dlouhého typového jména. |00000001:C3 | D I "RET" ; Definuj operační kód instrukce RET za použití krátkého typového jména. |00000002: | ; Rezervace řetězců: |[.bss] ::::Section changed. |00000000:................ | D 8 * B ; Rezervuj místo pro řetězec dlouhý 8 bajtů. |00000008:................~| D 9 * U ; Rezervuj místo pro řetězec dlouhý 9 unicharů. |0000001A: | ; Rezervace čísel: |0000001A:.... | D W ; Rezervuj místo pro 1 WORD. |0000001C:........ | D D ; Rezervuj místo pro 1 DWORD. |00000020:................ | D Q ; Rezervuj místo pro 1 QWORD. |00000028:................~| D T ; Rezervuj místo pro 1 TBYTE. |00000032: | ; Rezervace vektorů: |00000032:................~....AutoAlignment stuff. |00000040:................~| D O ; Rezervuj místo pro 1 OWORD (může obsahovat 2*QWORD nebo 4*DWORD). |00000050:................~....AutoAlignment stuff. |00000060:................~| D Y ; Rezervuj místo pro 1 YWORD (může obsahovat 4*QWORD nebo 8*DWORD). |00000080:................~| D Z ; Rezervuj místo pro 1 ZWORD (může obsahovat 8*QWORD nebo 16*DWORD). |000000C0: |

Viz test t2482 pro další příklady.

Každý operand pseudoinstrukce D je datový výraz.

K mnemonice D může být připojena přípona B, U, W, D, Q, T, O, Y, Z, I, S. Tato přípoda definuje výchozí datový typ použitý, pokud nebyl výslovně specifikován v operandu. Například DD 2,3,4 definuje tři proměnné DWORD se statickými hodnotami 2, 3 a 4.

Přípona zároveň určuje typ symbolu, který definuje data. V definici Sym1 DQ B 1, W 2, D 4 přípona Q určuje, že typ symbolu Sym1 je QWORD, třebaže tento symbol definuje pouze bajt, slovo a dvojslovo.

V jedné instrukci D se mohou míchat různé datové typy.

Výchozí typ určený příponou může být přepsán v operačním poli explicitním datovým type v krátké nebo dlouhé notaci. Operandy bez explicitní redefinice berou svůj typ z přípony instrukce D, např. DB 27, "$", W 120 definuje dva bajty následované jedním slovem. Datatypy v operandu mohou být také specifikovány dlouhým typovým názvem, např. DB 27, "$", WORD 120.
Viz test t2481 pro další příklady.

Data mohou být duplikována.

Například TranslateTable: D 256 * BYTE rezervuje 256 neinicializovaných bajtů.
Není-li duplikace použita, výchozí duplikační hodnota (duplikátor) je 1. Negativní duplikátor není povolen.
Duplikátor 0 nedefinuje ani nerezervuje žádná data, ale stále poskytuje datový typ svému symbolu a pokud je AUTOALIGN=ON, zarovnává aktuální ofset $.

Není-li použita žádná přípona, výchozí datový typ se bere z prvního neprázdného operandu např. D D 2,3,4 definuje tři DWORDy s hodnotami 2,3 a 4. Není-li výchozí typ určen, jako např. D 2, €ASM oznámí chybu.

Jedinou výjimkou, kdy datový typ nemusí být specifikován, je definice textového řetězce s vynecháním specifikátoru B nebo U, např. D "Nějaký text.". V tom případě bude datovým typem BYTE nebo UNICHAR v závislosti na aktuální hodnotě volby EUROASM UNICODE=.

Data nejsou definována ani rezervována, pokud není použit žádný operand.
L1: D  B 5      ; Definuj jeden bajt s hodnotou 5.       TYPE#L1='B', SIZE#L1=1.
L2: D  2*WORD 3 ; Definuj dvě slova s hodnotou 3.        TYPE#L2='W', SIZE#L2=4.
L3: DW W        ; Rezervuj jedno slovo.                  TYPE#L3='W', SIZE#L3=2.
L4: DW 0*D      ; Nezerezvuj nic, jen zarovnej na WORD.  TYPE#L4='W', SIZE#L4=0.
L5: DQ          ; Nerezervuj nic, jen zarovnej na QWORD. TYPE#L5='Q', SIZE#L5=0.
L6: D           ; Nedělej nic.                           TYPE#L6='A', SIZE#L6=0.
Na rozdíl od jiných asemblerů vynechaný operand neemituje žádná data, €ASM vyžaduje, aby byl specifikován typ operandu a případně i jeho hodnota, bez ohledu zda je operace D s příponou nebo bez ní. Kupříkladu DB rezervuje jeden bajt dat v MASM, avšak nedělá nic v €ASM. Použijte místo toho D B nebo DB B.

EuroAssembler umí definovat strojový kód instrukce jako data pomocí pseudoinstrukce DI. Ta se podobá pseudoinstrukcím DB nebo DU, ale obsah řetězce není doslovně emitován, nýbrž nejprve přeložen asemblerem. Text v uvozovkách operandu DI by měla být platná strojová instrukce, může mít prefix a operandy, ale ne návěstí.

Například DI "SEGES:MOVSB" definuje bajty 0x26,0xA4.
D 8*I"MOVSD" definuje osm bajtů 0xA5.
Viz test t2515 pro další příklady instrukce DI.

Strukturovaná paměťová proměnná je definována pseudoinstrukcí DS jméno_struktury nebo jen D jméno_struktury.

V instrukci D může být definován pouze jeden strukturovaný objekt.

€ASM nedovoluje vícenásobné operandy při definici strukturovaného objektu, jako DS MyStruc1, Mystruc2. Duplikace je ale podporována, např. DS 4*MyStruc.

Členy struktury mohou být přepsány staticky, pomocí klíčových operandů. Klíčem je lokání jméno člena bezprostředně následované rovnítkem = a novou hodnotou tohoto člena. Jmenný prostor pole operandů v instrukci DS je dočasně změněn na jmenný prostor deklarace struktury.

Instance struktury MyStruc deklarované výše v příkladu STRUC mohla být definována jako MyObject DS MyStruc, .Member2=2, .Member4=4. To inicializuje obsah MyObject.Member2 na DWORD integer 2, a obsah MyObject.Member4 na BYTE integer 4. Obsah MyObject.Member3 je již staticky definován jako BYTE integer 255, ostatné členy MyObject zůstávají neinicializovány.
Je-li aspoň jeden člen inicializován, objekt je při AUTOSEGMENT=ENABLED emitován do datové sekce namísto bss, neinicializované členy jsou naplněny nulami. Viz též test t2510.

↑ EQU

↑ =

Pseudoinstrukce EQU (nebo její synonymum =) definuje symbol uvedený v jejím poli návěstí. Tato pseudoinstrukce musí mít právě jeden operand specifikující adresu nebo číselnou hodnotu symbolu.

Instrukce Label:EQU $ nebo Label:= $ jsou ekvivalentní k Label:, tj. specifikaci samotného návěstí, což přiřazuje adresu návěstí k hodnotě Label.

EQU je jediný způsob, jak definovat prostý číselný symbol, jako třeba FILE_ATTRIBUTE_ARCHIVE = 00000020h.

Viz kteroukoli makroknihovnu v říši PROGRAM jako příklad definic numerických symbolů, např. winsfile.htm.

↑ %COMMENT

↑ %ENDCOMMENT

Tyto pseudoinstrukce definují blokovou poznámku, tedy rozsah zdrojového kódu ignorovaný EuroAssemblerem. V poli návěstí %COMMENT může být identifikátor dávající bloku jméno, avšak netvoří symbol. Stejný identifikátor může být použit jako operand instrukce %ENDCOMMENT. Pomáhá to ke kontrole správného spojení %COMMENT & %ENDCOMMENT, zejména pokud jsou poznámky vnořeny.

↑ %DROPMACRO

%DROPMACRO říká EuroAssembleru, aby zapomenul dříve deklarované makroinstrukce. Jedna pseudoinstrukce %DROPMACRO může zapomenout jedno nebo více maker specifikovaných jako její operand(y), např. %DROPMACRO Macro1, Macro2, Macro3.

Taky může zapomenou všechna dosud deklarovaná makra pomocí %DROPMACRO *.

Viz příklad %DROPMACRO example níže.

↑ %IF

↑ %ELSE

↑ %ENDIF

Instrukce mezi %IF a %ENDIF se překládají pouze tehdy, pokud podmínka v prvním (a jediném) operandu pseudoinstrukce je vyhodnocena jako pravda. %IF akceptuje booleovská rozšíření a rovněž akceptuje prázdný operand, který je vždy vyhodnocen jako nepravda.

Uvnitř bloku %IF..%ENDIF se může vyskytnout pseudoinstrukce %ELSE, který obrací logiku: instrukce mezi %IF a %ELSE se překládají, pokud je podmínka v %IF pravda a instrukce mezi %ELSE a %ENDIF se překládají, pokud je podmínka %IF nepravda..

Pseudoinstrukce %IF může mít identfikátor v poli pro návěstí, který netvoří symbol, ale identifikuje blok. Stejný identifikátor může být použit v poli operandu instrukcí %ELSE a %ENDIF.

↑ %FOR

↑ %EXITFOR

↑ %ENDFOR

Pseudoinstrukce %FOR a %ENDFOR vytvářejí blok, jenž je překládán opakovaně pro každý pořadový operand %FOR. V poli návěstí %FOR musí být identifikátor. Není to symbol, místo toho definuje formální preprocesní %proměnnou, která je dostupná v těle bloku %FOR..%ENDFOR (a nikde jinde). Jméno této %proměnné sestává ze znaménka procenta % následovaného identifikátorem.

Operandem může být libovolný element: registr, číslo, výraz, řetězec. Formální %proměnné bude postupně přiřazován každý z pořadových operandů a blok bude emitován s touto hodnotou. Následující příklad definuje smyčku %FOR se třemi operandy a emituje tři paměťové proměnné:

data %FOR "a", 3*B(5), "Long text"
       D %data
     %ENDFOR data
bude expandováno na |00000000:61 + D "a" |00000001:050505 + D 3*B(5) |00000004:4C6F6E672074657874 + D "Long text" |0000000D: |

Zopakování identifikátoru v poli operandu instrukcí %ENDFOR a %EXITFOR je dobrovolné a slouží ke kontrole správného párování blokových instrukcí.

Operandem %FOR rovněž může být číselný rozsah; blok pak bude emitován pro každou celočíselnou hodnotu z tohoto rozsahu. Sklon rozsahu může být negativní, krok řídicí formální %proměnné pak je -1 namísto +1.

i  %FOR  0..5    ; Sklon je pozitivní, tedy krok je +1.
      DB "A"+%i  ; Definuj bajty "A","B","C","D","E","F".
   %ENDFOR i
j  %FOR 'z'..'x' ; Sklon je negativní, tedy krok je -1.
      DB %j      ; Definuj bajty 'z','y','x'.
   %ENDFOR j

Viz také test t2640.

%FOR akceptuje celočíselný klíčový parametr STEP= explicitně určující krok, kterým je %proměnná inkrementována při použití rozsahu. Výchozí hodnotou je nula (STEP=0), která má speciální význam: efektivní krok je pak buď +1 nebo -1 v závislosti na sklonu rozsahu.

Oba druhy operandů (výčtový a rozsah) se mohou kombinovat. Je-li STEP= explicitně stanoven a jeho znaménko se liší od sklonu v operandu rozsahu, smyčka není v tom případě překládána. Na druhé straně, pokud je STEP= vynechán nebo nastaven na 0, rozsahy obou sklonů mohou být kombinovány v jednom bloku %FOR a každý z operandů rozsahu obdrží svůj vhodný krok +1 nebo -1. Ukázka:

a %FOR 1..3, 6..4, 7
     ; Blok je přeložen s %a = 1,2,3,6,5,4,7.
   %ENDFOR

b %FOR 0..64, 256, 400..300, 512, STEP=16
     ; Blok je přeložen s %b = 0,16,32,48,64,256,512.
   %ENDFOR

Má-li formální %proměnná bloku %identické jméno s jinou předtím uživatelsky definovanou %proměnnou, formální %proměnná převáží a ta uživatelsky definovaná není v bloku %FOR..%ENDFOR viditelná. Viz test t2641.

Pokud €ASM narazí na pseudoinstrukci %EXITFOR, přeruší překlad dalších instrukcí bloku %FOR..%ENDFOR a pokračuje pod %ENDFOR bez ohledu na to, kolik nezpracovaných operandů ještě zbývá.

i  %FOR 0..9
     DB %i
     %IF %i>=3
       %EXITFOR i
     %ENDIF
     DB "a" + %i
   %ENDFOR i ; Definuje bajty  0,"a",1,"b",2,"c",3

Ve vnořených blocích %FOR..%ENDFOR může být formální proměnná (první a jediný operand %EXITFOR) použita ke specifikaci, který z vnořených bloků má být opuštěn. Viz test t2642 jako příklad.

↑ %WHILE

↑ %EXITWHILE

↑ %ENDWHILE

Blok instrukcí mezi %WHILE a %ENDWHILE se překládá asemblerem opakovaně dokud podmínka v prvním (a jediném) operandu %WHILE je pravda. Je-li podmínka nepravda už při vstupu do bloku, bude celý přeskočen.

V poli návěstí %WHILE a v poli operandu %ENDWHILE a %EXITWHILE může být stanoven identifikátor pro vizuální svázání, který však netvoří symbol.

Na rozdíl od %FOR, který dočasně deklaruje a udržuje svou vlastní řídicí %proměnnou, %WHILE to nedělá. Je na programátorovi, aby deklaroval nějakou uživatelskou %proměnnou před vstupem do bloku a pak ji uvnitř %WHILE..%ENDWHILE měnil a testoval. Příklad:

%i  %SETA 3        ; Definuj uživatelskou %proměnnou %i, která bude řídit expanzi bloku.
Id1 %WHILE %i      ; Opakuj blok, dokud je %i nenulové. Id1 je identifikátor bloku.
C%i:  DB %i
%i    %SETA %i - 1 ; Změň řídicí proměnnou %i.
    %ENDWHILE Id1  ; Konec smyčky. Identifikátor souhlasí.
; Instrukce emitované blokem %WHILE..%ENDWHILE: C3: DB 3, C2: DB 2, C1: DB 1.

%EXITWHILE v bloku způsobí přeskočení zbytku instrukcí, €ASM bude pokračovat pod %ENDWHILE.

Viz testy t2700, t2701, t2702.

↑ %REPEAT

↑ %EXITREPEAT

↑ %ENDREPEAT alias

↑ %UNTIL

Podmíněný blok %REPEAT..%ENDREPAT se podobá na %WHILE..%ENDWHILE, avšak logika je obrácená. %REPEAT nepřijímá návěstí ani operand. Instrukce v bloku jsou přeloženy vždy aspoň jednou. Test řídicí podmínky je v poli operandu %ENDREPEAT; pokud se vyhodnotí jako nepravda, €ASM bude blok opakovaně překládat. Namísto mnemoniky %ENDREPEAT lze použít alias %UNTIL.

Blok %REPEAT..%ENDREPEAT taky může používat identifikátor ke kontrole spárování. Na rozdíl od ostatních blokových instrukcí je ale pozice blokového identifikátoru odlišná: může být specifikován jako první operand %REPEAT a zopakován v poli návěstí %ENDREPEAT (neboli %UNTIL).

%i  %SETA 3           ; Definuj %proměnnou %i, která bude řídit expanzi bloku.
    %REPEAT Id1       l Id1 je pouze identifikátor bloku, jinak nemá význam.
      C%i: DB %i
      %i %SETA %i - 1 ; Změň řídicí %proměnnou i.
Id1 %UNTIL %i = 0     ; Konec smyčky. Identifikátor souhlasí.
; Instrukce emitované blokem %REPEAT..%UNTIL block: C3: DB 3, C2: DB 2, C1: DB 1.

%EXITREPEAT v bloku způsobí přeskočení zbývajících instrukcí; €ASM bude pokračovat pod %ENDREPEAT.

Viz testy t2750, t2751, t2752.

↑ %SET

Pseudoinstrukce %SET spolu s ostatními členy této rodiny jsou určeny k přiřazení hodnoty do preprocesních %proměnných. Přiřazovaná %proměnná bude v poli návěstí této pseudoinstrukce.

%SET přiřazuje seznam operandů jako doslovný text, včetně oddělujících čárek. Pouze mezery mezi mnemonikou (%SET) a seznamem operandů a také mezery za posledním operandem jsou vynechány. Podobně jsou mezery vynechány při použití pokračování řádku.

%CardList %SET Hearts, Diamonds, Clubs, Spades  ; Comment

%CardList nyní obsahuje řetězec Hearts, Diamonds, Clubs, Spades (31 znaků včetně mezer a čárek).

Viz test t2810.

↑ %SETA

%SETA akceptuje aritmetické výrazy. Budou vyhodnoceny a pak přiřazeny %proměnné jako dekadické číslo. Pokud operand %SETA není platným výrazem, ohlásí se chyba.

Je-li použit více než jeden operand, každá hodnota je vložena jako odpovídající položka do %proměnné, které je přiřazováno. Příklad:

%Value %SETA PoolEnd - PoolBegin
%Sizes %SETA 2+3, 4, ,-5*2

Rozdíl mezi ofsety PoolEnd a PoolBegin v předchozím příkladu je spočítán a přiřazen do %proměnné %Value jako dekadické číslo.
%Proměnná %Sizes nyní obsahuje text 5,4,,-10 (8 znaků). Individuální položky ze %Sizes mohou být získány pomocí operace sublist, jako třeba %Sizes{2}.

Viz test t2821.

%SETA je vhodnější pro modifikaci kontrolní proměnné v preprocesních smyčkách, jako %i %SETA %i+1. I když textové přiřazení pomocí %i %SET %i+1 by také fungovalo, s pseudoinstrukcí %SET není výraz počítán okamžitě a mohli bychom skončit s něčím jako +1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 po patnácté expanzi.

↑ %SETB

%SETB se podobá %SETA, ale akceptuje rozšířené booleovské výrazy, které po vyhodnocení přiřazuje v podobě binárních číslic 1 a 0.

Viz též test t2831.

Na rozdíl od %SETA, binární číslice nejsou odděleny čárkami, je-li více než jeden operand použit v pseudoinstrukci %SETB. Položky mohou být získány pomocí operace substring. Příklad:

%TooBig %SETB 5 > 4                   ; %Proměnné %TooBig je přiřazena hodnota znaku 1 (pravda).
%Flags  %SETB %TooBig, 2,,3>2,off,4,, ; %Flags je přiřazena hodnota 110101.
        %IF %Flags[1]                 ; Pravda, vyhodnotí 1. člen %Flags, tj. %TooBig, tj. 1.
Flags:  DB %Flags[]b                  ; Přeloží se jako Flags: DB 110101b.

↑ %SETC

%SETC akceptuje matematický výraz ve svém operandu, který se musí vyhodnotit na prosté číslo ne vyšší než 255 a ne menší než -128. Výsledek pak bude přiřazen jako znak s touto vypočtenou hodnotou ASCII bajtu. Příklad:

%Quote %SETC """" ; Přiřadí znak "uvozovka" (ASCII 33).
%Tab   %SETC 9    ; Přiřadí znak "tabelátor" (ASCII 9).
%NBSP  %SETC -1   ; Přiřadí znak "nepřerušitelná mezera" (ASCII 255).

Podobně jako %SETB, mohou být definovány vícenásobné operandy a výsledné znaky nejsou oddělovány čárkami.

%Hexadigits %SETC 'A','B','C','D','E','F'
; %Hexadigits nyní obsahuje šest znaků ABCDEF.

Viz test also t2841.

%SETC dovoluje přiřazení speciálních znaků, což by jinak nemuselo být možné kvůli syntaktickým pravidlům €ASM.
%Space %SETC 32 přiřazuje jednu mezeru. Téhož bychom mohli dosáhnout pomocí
%QuotedSpace %SET " " a suboperací vybrat pouze druhý ze tří přiřazených znaků:
%Space %SET %QuotedSpace[2].

↑ %SETE

Tato pseudoinstrukce čte environmentovou proměnnou operačního systému v době překladu (asm-time) a přiřazuje ji preprocesní %proměnné. Jméno environmentové proměnné je specifikováno v poli operandu bez uvozovek, procent či dolarů, např.

%OS %SETE OS
Msg: DB "This program was assembled at %OS system."

€ASM oznámí varování W2520 pokud je požadovaná proměnná prázdná nebo není definována.

%SETE dovoluje načítat více než jednu environmentovou proměnnou, jejich hodnoty budou přiřazeny bez uvovozek a odděleny čárkami. Příklad:

%CpuInfo %SETE PROCESSOR_ARCHITECTURE, PROCESSOR_IDENTIFIER, \
               PROCESSOR_LEVEL, PROCESSOR_REVISION
Na mém starém počítači to přiřadí následující text do %CpuInfo:
x86,x86 Family 15 Model 1 Stepping 2, GenuineIntel,15,0102. Kvůli čárce vložené do hodnoty %PROCESSOR_IDENTIFIER% nemusí být snadné načítat individuální komponenty pomocí sublistu %CpuInfo{4}. Takže je lepší použít %SETE pouze pro jednu environmentovou proměnnou.

↑ %SETS

%SETS se dívá na %proměnnou ve svém poli prvního operandu a přiřazuje jeho velikost (size), tj. počet bajtů, které jeho hodnota okupuje.

%SomeVar        %SET  ABC, DEF
%SomeSize       %SETS %SomeVar  ; %SomeSize je nyní 8 (3 písmena + čárka + mezera + 3 písmena).
%SizeOfSomeSize %SETS %SomeSize ; %SizeOfSomeSize je nyní 1 (jedna číslice).

%SETS musí mít právě jeden operand, který vypadá jako preprocesní %proměnná (procento následované identifikátorem).

Viz test t2861.

↑ %SETL

%SETL se podobá na %SETS, avšak přiřazuje délku (length) obsahu %proměnné, tj počet čárkou oddělených položek.

%SomeVar            %SET  ABC, DEF
%SomeLength         %SETL %SomeVar    ; %SomeLength je nyní 2 (2 čárkou oddělené položky).
%LengthOfSomeLength %SETL %SomeLength ; %LengthOfSomeLength je nyní 1 (jedna položka).

%SETL musí mít právě jeden operand, který vypadá jako preprocesní %proměnná (procento následované identifikátorem).

Vzi test t2866.

↑ %SET2

Uvažme, jak se překládá povel %Var1 %SET %Var2. €ASM nejprve expanduje %Var2 a výsledek expanze přiřadí do %Var1. První dvě slova nejsou expandována, neboť %Var1 je právě přiřazovaný cíl, a %SET je rezervované jméno, které se neexpanduje nikdy.

%SET2 je podobné jako %SET, ale pole operandů je expandováno 2 krát před samotným přiřazením. Každá expanze "spolkne" jeden znak procenta.

%V1 %SET "A"
%V2 %SET "B"
%V3 %SET "C"
i   %FOR 1..3
      %DataExp %SET2 %%V%i
      DB %DataExp
    %ENDFOR i ; Emituje DB "A", DB "B", DB "C".

Viz také test t2871.

Pseudoinstrukce %SET2 se uplatní pouze v některých speciálních makrech, jako EndProcedure, kde je použita k expandování %proměnné s dosud neznámým, dynamicky se měnícím jménem.

↑ %SETX

Když jsou překládány pseudoinstrukce z rodiny SET*, €ASM neexpanduje slovo v poli návěstí v pseudoinstrukcích jako %Label %SET* cokoli. Toto platí pro %SET, %SETA, %SETB, %SETC, %SETU, %SETE, %SETS, %SETL, %SET2 ale nikoli pro %SETX. V této pseudoinstrukci je pole návěstí rovněž expandováno. Po expanzi návěstí se %SETX chová stejně jako obyčejné %SET, což znamená, že vyžaduje platné jméno %proměnné v poli návěstí. Kupříkladu %%Var1 %SETX ABC je ekvivalentní s %Var1 %SET ABC.

Použitím %SETX můžeme přiřazovat %proměnné, jejichž jména nejsou explicitně určena a dynamicky se mění. Příklad:

i %FOR 1..4
     %%M%i %SETX %i  ; Totéž jako %M1 %SET 1, %M2 %SET 2 atd.
  %ENDFOR  ; Přiřadily se hodnoty 1,2,3,4 %proměnným %M1,%M2,%M3,%M4.

Viz také test t2881.

%SETX se uplatní ve speciálních makrech, jako Procedure, kde je použito k přiřazování adres ze zásobníkového rámce (např. EBP+12) %proměnným, jejichž název nebyl určen v době psaní makra.

↑ %MACRO

↑ %EXITMACRO

↑ %ENDMACRO

Blok instrukcí ohraničený pseudoinstrukcemi %MACRO a %ENDMACRO se nazývá deklarace makra. Identifikátor v poli návěstí %MACRO je název makra.
Pseudoinstrukce %MACRO spolu se svými operandy tvoří prototyp makra, který deklaruje jméno makra a dává jména jeho argumentům. Jakmile bylo deklarováno, makro může být v programu expandováno mnohokrát.

Dokud €ASM čte instrukce deklarace makra ve zdrojovém textu, neemituje žádná data. Instrukce z těla makra bydou emitovány až když je makro expandováno, uvedením jména makroinstrukce v programu.

Pseudoinstrukce %EXITMACRO umožňuje přerušit emitování například když byla detekována nějaká chyba.

Jak %EXITMACRO, tak %ENDMACRO mohou mít uvedeno jméno makra v poli operandu ke zvýraznění párování bloku.

Příklad definice a expanze makra:

AlignEAX %MACRO       ; Makro pro zaokrouhlení EAX na násobek 4.
           ADD EAX,3
           AND EAX,-4
         %ENDMACRO AlignEAX

         MOV EAX,13
         AlignEAX     ; Po expanzi makra bude EAX obsahovat 16.

Pro více informací viz kapitolu Makroinstrukce.

↑ %SHIFT

Pseudoinstrukce %SHIFT je užitečná pouze v makru. Snižuje pořadové číslo operandů makra o hodnotu definovanou svým operandem. %SHIFT nemůže mít návěstí a má povolen pouze jeden operand, který se vyhodnotí na prosté číslo. Při jeho vynechání se předpokládá hodnota 1.

%SHIFT 0 nedělá nic. %SHFT s negativním číslem invertuje směr posunu operandů.

Účinek operace %SHIFT je omezen pouze je-li k operandům makra přistupováno podle jejich pořadových čísel, jako %1, %2 atd. Přístup k operandům pomocí formálních jmen zůstává operací %SHIFT nenarušen.

Operandy vysunuté vlevo z pozice %1 do pozice nula nebo negativní již nebudou nadále přístupné pomocí pořadových čísel, avšak nejsou navždy ztraceny, neboť mohou být posunuty zpět pomocí negativního argumentu pseudoinstrukce %SHIFT.

| |Sample %MACRO Oper1, Oper2, Oper3 | |L1: DB %1, %Oper1 | | %SHIFT 1 | |L2: DB %1, %Oper1 | | %SHIFT 2 | |L3: DB %1, %Oper1 | | %ENDMACRO Sample |0000: | |0000: |Sample 0x44, 0x55, 0x66, 0x77 | +Sample %MACRO Oper1, Oper2, Oper3 |0000:4444 +L1: DB %1, %Oper1 | + %SHIFT 1 |0002:5544 +L2: DB %1, %Oper1 | + %SHIFT 2 |0004:7744 +L3: DB %1, %Oper1 | + %ENDMACRO Sample |0006: |

Viz také test t7221.

↑ %ERROR

Pseudoinstrukce %ERROR vloží uživatelsky definované oznámení do listingu a na standardní výstup oznámení. Oznámení se podobá těm, která jsou generována samotným €ASM. %ERROR se často používá v makroinstrukcích a obvykle varuje programátora, že makro nebylo použito očekávaným způsobem.

Uživatelská oznámení mají kód závažnosti U a úroveň 5, tedy někde mezi varováním a chybou. Programátor může určit identifikátor zprávy nepovinným klíčovým operandem ID=, který může specifikovat prosté číslo mezi 5000 a 5999. %ERROR rovněž akceptuje číslo identifikátoru v rozmězí 0..999 a v tom případě k němu interně přidává 5000. Výchozí hodnotou je 0, takže uživatelsky definované oznámení má identifikaci U5000, nebylo-li (použitím ID=) určeno jinak.

Text oznámení nemusí být v uvozovkách. Pokud sestává z více než jednoho operandu, budou spojeny doslova, včetně uvozovek a čárek. Příklady:

%ERROR Id=5123, Došlo k chybě. Zkuste to znovu.

Viz test t2581 pro více příkladů.

↑ %DISPLAY

Pseudoinstrukce %DISPLAY je určena k získávání informací o interních objektech EuroAssembleru. Každý takový objekt je zobrazen formou ladicího oznámení se závažností 1. Oznámení je zobrazeno na standardní konzole (v každém průchodu) a v listingu (v posledním průchodu).
%DISPLAY je aktivní i v neemitujících pasážích, jako bloky zakomentované pomocí %COMMENT nebo %IF. Je určen k vyšetřování postupů €ASM, pokud něco nefunguje dle očekávání.

Pseudoinstrukce %DISPLAY přijímá libovolný počet operandů – kategorií specifikujících druh objektů, které chceme zkontrolovat. Kategorie mohou být uvedeny jako pořadové nebo klíčové operandy s hodnotou určující filtr, který může omezit počet zobrazených řádků. Názvy kategorií nezávisí na velikosti písmen, ale hodnota filtru ano. Hodnota filtru specifikuje prvních několik znaků z názvu objektů, které chceme zobrazit. Hodnota filtru může končit hvězdičkou *, ale ta není povinná a bez ní to funguje stejně. Například instrukce %DISPLAY Macros=Alig zobrazí všechna makra, jejich jména začínají "Alig".

Operandy pseudoinstrukce %DISPLAY mají poněkud uvolněnou syntaxi. Kategorie objektu (pořadový nebo klíčový operand) může být zkrácen. Stačí uvést tolik znaků, kolik je potřeba k identifikaci kategorie. Například %DISPLAY se zobrazí mapu všech segmentů a jejich sekcí. %DISPLAY File zobrazuje seznam vstupních souborů (zdrojový a vložené knihovny). %DISPLAY sym=Num*, sym=En zobrazí symboly, jejichž jména začínají Num nebo En.

%DISPLAY UserVar, %DISPLAY UserVar=* a %DISPLAY user= fungují stejně (prázdný filtr propustí všechna jména %proměnných). Nefiltrovatelné kategorie, jako segmenty, kontextový zásobník, automatické makro %proměnné, vždy zobrazují kompletní seznam, případná hodnota filtru se ignoruje.

Při specifikaci filtru uživatelsky definovaných a systémových %proměnných může být počáteční znak procenta %, případně %^ vynechán, anebo musí být procento zdvojeno (jinak by byla proměnná expandována na svůj obsah). %DISPLAY UserVar=Loc, %DISPLAY us=Loc* a %DISPLAY user=%%Loc mají shodnou funkci: zobrazují aktuální obsah uživatelsky definovaných %proměnných, jejichž jména začínají na %Loc.

Kategorie %DISPLAY
Operand %DISPLAYOznámeníFiltrŘazeníZobrazované objekty
AllD1100..D1900anoabecední Všechny níže specifikované objekty (zkratka pro Fil,Ch,Se,St,Co,Sym,L,Rel,M,V).
FilesD1150..D1190ignorovánpřirozenéZdrojové soubory vložené do programu.
ChunksD1200..D1240ignorovánpřirozenéKusy zdrojového kódu.
SectionsD1250..D1290ignorovánpřirozenéMapa grup, segmentů a sekcí.
SegmentsD1250..D1290ignorovánpřirozenéMapa grup, segmentů a sekcí.
GroupsD1250..D1290ignorovánpřirozenéMapa grup, segmentů a sekcí.
StructuresD1300..D1340anoabecedníStruktury deklarované v programu.
ContextD1350..D1390ignorovándle zásobníkuKontextový zásobník blokových instrukcí.
SymbolsD1400..D1450anoabecední Všechny explicitně definované symboly (zkratka pro Fix,Unf,Unr,Ref).
  UnfixedSymbolsD1410..D1450anoabecedníSymboly, jejichž vlastnosti dosud nejsou stabilní.
  FixedSymbolsD1420..D1450anoabecedníSymboly, jejichž vlastnosti již jsou fixovány.
  UnreferencedSymbolsD1430..D1450anoabecedníDosud nepoužité symboly.
  ReferencedSymbolsD1440..D1450anoabecedníAspoň jednou zmíněné symboly.
LiteralSymbolsD1500..D1540ignorovánabecedníVšechny literály.
RelocationsD1550..D1590ignorovánpřirozenéRelokační záznamy.
MacrosD1600..D1690anoabecedníMakroinstrukce dosud definované.
VariablesD1700..D1790anoabecední Všechny preprocesní %proměnné momentálně nastavené (zkratka pro Au,Fo,Us,Sys).
  AutomaticVariablesD1710..D1730ignorovánfixníAutomatické makro %proměnné.
  FormalVariablesD1740..D1750anoabecedníFormální makro/for %proměnné.
  UserVariablesD1760..D1770anoabecedníUživatelem definované preprocesní %proměnné.
  SystemVariablesD1780..D1790anoabecedníSystémové preprocesní %^proměnné.

Zobrazené oznámení zpravidla obsahuje jméno objektu, jeho atributy a další vlastnosti.

Operandy Groups, Segments, Sections jsou stejné, kterýkoli z nich vždy zobrazuje kompletní strom.
Řádky D1260 s grupami zobrazuje názvy grup.
Řádky D1270 se segmenty jsou odsazeny dvěma mezerami a zobrazují účel, šířku, zarovnání, kombinování, třídu, zdroj.
Řádky D1280 se sekcemi jsou odsazeny o čtyři mezery a zobrazují adresu, velikost, zarovnání, referenci, zdroj.

Vlastnost src= specifikuje, zda soubor nebo kus zdroje je

Vlastnost Chunku type= určuje informaci obsaženou v tomto kusu zdrojového textu:

Booleovská vlastnost ref= specifikuje, zda symbol, struktura nebo sekce byly použity (referovány aspoň jednou v programu). Členové skupiny jsou automaticky brány jako used, když je struktura definována.
Podobnou vlastností je fix= specifikující, zda ofset tohot symbolu je již fixní, tj. stabilní mezi průchody.
Vlastnost kontextu emit= informuje, zda je blok v normálním (emitujícím) stavu, nebo zda je jím pouze procházeno bez generování kódu či dat.

Kontextová vlastnost %.= zobrazuje momentální hodnotu expanzního počitadla v tomto bloku.

Vlastnost src= identifikuje pozici ve zdrojovém textu, kde byl zobrazovaný objekt definován, ve standardní podobě "FileName"{LineNumber}.

Automatické a formální %proměnné jsou definovány pouze při expanzi %macro nebo %for, tj. pokud je příkaz %DISPLAY Auto,Formal vložen do těla %MACRO..%ENDMACRO nebo %FOR..%ENDFOR. a makro je pak voláno.

Viz testy t2901..t2917 pro příklady volání %DISPLAY.

Na rozdíl od jiných instrukcí je %DISPLAY živá i v neemitujících blocích. Opatrně se zařazováním nefiltrované instrukce %DISPLAY v opakujících se preprocesních smyčkách (%FOR, %WHILE, %REPEAT), jelikož to může podstatně zahltit výstup.

Hlavním účelem %DISPLAY je hledat chybu v asm-time, kdy €ASM nepracuje podle očekávání. Spolu s volbami EUROASM DISPLAYSTM=, DISPLAYENC= a s volbami PROGRAM LISTGLOBALS=, LISTLITERALS=, LISTMAP= poskytuje %DISPLAY silnou zbraň.
Pro vyšetřování programu za běhu použijte debugger nebo makro Debug.

↑ %DEBUG

↑ %PROFILE

Tyto pseudoinstrukce jsou rezervovány pro další rozšiřování EuroAssembleru, nejsou zatím implementovány. Viz také booleovské volby EUROASM DEBUG= a PROFILE=.


↑ Macroinstrukce

Makro je definováno blokem instrukcí (tělem makra) mezi pseudoinstrukcemi %MACRO a %ENDMACRO. Samotná pseudoinstrukce %MACRO, neboli ( prototyp makra) musí mít návěstí, které bude později použito k vyvolání makra (neboli k jeho expanzi).

Makro musí být definováno dříve, než je vyvoláno.

Instrukce, která má jméno dříve definovaného makra ve svém poli operace, se nazývá makroinstrukce nebo zkrátka jen makro. Bude nahrazeno instrukcemi z bloku %MACRO..%ENDMACRO.
Makrem může být pevný statický sled instrukcí, jako

CarriageReturn %MACRO
                 MOV AH,2  ; 3 instrukce mezi %MACRO a %ENDMACRO jsou tělem makra.
                 MOV DL,13
                 INT 21h
               %ENDMACRO CarriageReturn

Užitečnější jsou makra, která mohou modifikovat expandované instrukce v závislosti na operandech, se kterými jsou volány. Makro bývá voláno s operandy dostupnými v těle makra jako formální %proměnné nebo jako pořadové %proměnné %1, %2, %3,.... Operandy v makrodefinici mohou dostat dočasné formální symbolické jméno; uvnitř makra jsou pak dostupné pod tímto formálním jménem prefixovaným znakem procenta %. Nebo mohou být referovány svým pořadovým číslem, rovněž prefixovaným znakem procenta %. Klíčové operandy jsou dostupné pouze svým formálním jménem (klíčem) prefixovaným znakem procenta %. Příklady:

Copy %MACRO Source, Destination, Size=ECX ; Instrukci %MACRO se říká prototyp makra.
       MOV ESI, %Source      ; nebo MOV ESI, %1
       MOV EDI, %Destination ; nebo MOV EDI, %2
       MOV ECX, %Size
       REP MOVSB
     %ENDMACRO Copy

Předchozí makro nepotřebně přesouvá počet kopírovaných bajtů (Size) do registru ECX i když už tam jsou v době jeho volání. V tom případě může být expandovaná instrukce MOV ECX,ECX uspořena:

Copy %MACRO Source, Destination, Size=ECX
       MOV ESI, %Source
       MOV EDI, %Destination
       %IF "%Size" !== "ECX"
         MOV ECX, %Size
       %ENDIF
       REP MOVSB
     %ENDMACRO Copy

Nyní když je makro voláno s parametry Copy From, To, Size=ecx nebo jako Copy From, To, žádná nadbytečná instrukce MOV ECX,ECX do něj nebude expandována.

Pokud by jméno formální makro %proměnné náhodou kolidovalo se jménem některé dříve uživatelem definované %proměnné, viditelnost uživatelské %proměnné je dočasně potlačena ve prospěch formální %proměnné. Viz test t7347.
Automatické %proměnné, jako %*, %#, %:, %1, %2,,, nejsou viditelné vně těla makra.

Všechna makra v EuroAssembleru mohou mít proměnný počet operandů.

Počet operandů specifikovaný při volání makra nemusí odpovídat počtu operandů zadanému při jeho deklaraci. Je-li makro voláno s méně pořadovými operandy než deklaruje jeho prototyp, €ASM to nepovažuje za chybu a tiše expanduje chybějící operandy do ničeho (do prázdna).
Je-li makro vyvoláno s více operandy, než specifikuje jeho prototyp, tyto nadbytečné operandy nejsou k dispozici pod formálními jmény, ale stále mohou být referovány pomocí automatického pořadového čísla, jako %2, %3 atd. Viz též pseudoinstrukci %SHIFT.

Je-li při invokaci makra vynechán klíčový operand, ponechává si výchozí hodnotu deklarovanou v definici makra. Přidání dobrovolného klíčového operandu dovoluje rozšířit funkčnost makroinstrukce bez narušení zpětné kompatibility. Uvažujme toto prosté makro:

Write %MACRO TextPtr,TextSize ; Zapiš text na standardní výstup.
   MOV DX,%TextPtr
   MOV CX,%TextSize
   MOV BX,1       ; Handle standardního výstupu.
   MOV AH,40h     ; Zapiš řetězec DS:DX do souboru nebo zařízení.
   INT 21h        ; Vyvolej službu DOS.
 %ENDMACRO Write

Později můžeme chtít použít toto makro pro zápis i do jiných zařízení, než standardní výstup. Rozšiříme je tedy klíčovým operandem Handle= s předdefinovanou výchozí hodnotou standardního výstupu:

Write %MACRO TextPtr,TextSize,Handle=1 ; Zapiš text na standardní výstup nebo do zařízení.
   MOV DX,%TextPtr
   MOV CX,%TextSize
   MOV BX,%Handle ; Handle požadovaného zařízení.
   MOV AH,40h     ; Zapiš řetězec DS:DX do souboru nebo zařízení.
   INT 21h        ; Vyvolej službu DOS.
 %ENDMACRO Write

Nyní je možné zapisovat i do jiných zařízení, například do řádkové tiskárny pomocí Write Message,80,Handle=4. Rozšířené makro Write je zpětně kompatibilní. Ani když náš starý program obsahuje aktualizovanou makroknihovnu s vylepšeným makrem Write, nemusíme jej rekompilovat.

Podobně jako preprocesní %proměnné, mohou být makra redefinována. Není to ale obvyklé a €ASM bude v tom případě varovat oznámením W2512. Jednou definované makro může být oddefinováno pseudoinstrukcí %DROPMACRO.

Příklad situace, kdy může být zapomenutí makra užitečné, je emulace strojové instrukce makrem se stejným jménem.
Strojová instrukce BSWAP, která reverzuje pořadí bajtů v 32bitovém registru, nebyla dostupná, dokud se neobjevil procesor Intel 80386. Přehození pořadí bylo u starších CPU řešitelné makrem, pomocí tří instrukcí ROR nebo ROL. Pokud zjistíme, že náš program poběží na Pentiu, můžeme zapomenout na makro a €ASM bude překládat BSWAP jako nativní strojovou instrukci.

|00000000: | | |BSWAP %MACRO reg32 ; Makro k záměně bajtů v registru. | | %IF TYPE# %reg32 <> 'R' || SIZE# %reg32 <> 4 | | %ERROR 'Makro "BSWAP" očekává 32bitový GPR jako operand.' | | %EXITMACRO BSWAP | | %ENDIF | |%reg16 %SET %reg32[2..3] ; Název dolní poloviny registru reg32 (vynechej písmeno E). | | ROL %reg16,8 | | ROL %reg32,16 | | ROL %reg16,8 | | %ENDMACRO BSWAP |00000000: | |00000000:BA78563412| MOV EDX,0x12345678 |00000005: | BSWAP EDX ; Očekávaný výsledek je EDX=0x78563412. | +BSWAP %MACRO reg32 ; Makro k záměně bajtů v registru. |FALSE + %IF TYPE# %reg32 <> 'R' || SIZE# %reg32 <> 4 | + %ERROR 'Makro "BSWAP" očekává 32bitový GPR jako operand.' | + %EXITMACRO BSWAP | + %ENDIF |4458 +%reg16 %SET %reg32[2..3] ; Název dolní poloviny registru reg32 (vynechej písmeno E). |00000005:66C1C208 + ROL %reg16,8 |00000009:C1C210 + ROL %reg32,16 |0000000C:66C1C208 + ROL %reg16,8 | + %ENDMACRO BSWAP | | ; Pokud je CPU aspoň 486 nebo vyšší, preferuje strojovou instrukci. | | %DROPMACRO BSWAP |00000010:0FCA | BSWAP EDX ; Tentokrát zaměň pořadí bajtů nativní instrukcí. |00000012: |

Pokročilý makrojazyk EuroAssembleru dovoluje měnit programovací styl. Můžeme tvořit makroinstrukce, které napodobují funkce vyššího programovacího jazyka Viz makra Ii* ve zdrojovém souboru €ASM ii.htm jako příklad pseudojazyka vyvinutého pro inteligentní popis konverze instrukcí do strojového kódu.

Pokud něco nefunguje podle očekávání, je vždy možné se podívat na generovaný kód expandovaných makroinstrukcí a zůstat u prostého asembleru.


↑ Programové formáty

BIN ↓

COM ↓

MZ ↓

OMF ↓

LIBOMF ↓

COFF ↓

LIBCOF ↓

ELF ↓

ELFX ↓

ELFSO ↓

PE ↓

DLL ↓

RSRC ↓

Šířka formátů ↓

Cílem činnosti €ASM je výstupní soubor v některém z formátů vybraném volbou PROGRAM FORMAT=. Jsou tři kategorie výstupních souborů EuroAssembleru:

  1. Linkovatelný soubor (také nazývaný modul nebo objektový soubor) je určen ke spojení s jinými moduly a knihovnami do konečného spustitelného souboru nebo do objektové knihovny.
    €ASM umí generovat tři hlavní standardy objektových souborů: ELF, OMF a COFF. Extenze objektových souborů je .o nebo .obj.
  2. Knihovna je kolekce modulů připravená být linkována na požádání do konečného spustitelného souboru. €ASM generuje několik druhů knihoven:

    Defaultní přípona objektové nebo importní knihovny je .lib, v případě dynamické knihovny to je .so nebo .dll.

  3. Spustitelný soubor (také nazývaný image) může být zaveden a spuštěn shellem hostitelského operačnho systému.
    €ASM generuje spustitelné soubory ve formátech ELFX, PE, MZ, COM, jejich souborová přípona je .x, .exe nebo .com. Může rovněž vytvářet dynamicky zaváděnou knihovnu DLL, velmi podobnou formátu PE, ovšem ta může být vykonávána pouze nepřímo, invokací jejích exportovaných funkcí jiným programem nebo speciálním Windows zaváděčem, jako je RUNDLL32.exe.
    Programové formáty BIN a BOOT jsou taky považovány za spustitelné. Nicméně jelikož v nich chybí služební (red tape) informace, binární soubor potřebuje k zavedení vlastní ad hoc zaváděcí program nebo musí být zaveden na speciální místo v počítači, jako je firmware anebo bootovací sektor diskového zařízení.

↑ BIN

Volba PROGRAM FORMAT=BIN byla vybrána jako výchozí, pokud není FORMAT= explictině uvedeno. Další výchozí volby pro formát BIN jsou:

Name: PROGRAM FORMAT=BIN, OUTFILE=%^PROGRAM.bin, MODEL=TINY, WIDTH=16, \
              ENTRY=0, IMAGEBASE=0, SECTIONALIGN=0, FILEALIGN=0
.

€ASM vytváří výchozí segment [BIN] s univerzálním účelem:

[BIN] SEGMENT WIDTH=16,ALIGN=16, \
              PURPOSE=CODE+DATA+BSS+STACK+LITERALS
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Obsah souboru formátu BIN je jednoduchý: prosté spojení emitovaných obsahů jeho segmentů. Neinicializované segmenty (BSS) jsou vynechány.

Zarovnání segmentů v image je určeno nejvyšší hodnotou z PROGRAM FILEALIGN=0, PROGRAM SECTIONALIGN=0 a SEGMENT ALIGN=16. Mezery mezi segmenty jsou zaplněny buď kódem NOP 0x90 (pokud oba sousední segmenty mají SEGMENT PURPOSE=CODE), jinak kódem 0x00.

Typickou aplikací binárního formátu jsou čistě datové soubory, konverzní tabulky, ovladače a jiné speciální záležitosti, viz BIN projects.

↑ BOOT

Volba PROGRAM FORMAT=BOOT generuje binární formát přizpůsobený bootování (zavádění operačního systému). Rozdíly oproti formátu BIN:

  1. Velikost výstupního souboru je 512 bytes,
  2. je zaváděn na lineární adresu 07C00h,
  3. velikost kódu a dat je zarovnána na 510 a pak jsou zapsány dva bajty s hodnotou 0x55,0xAA (podpis boot-sektoru),
  4. výchozí přípona souboru je .sec.

Výchozí volby pro formát BOOT:

Name: PROGRAM FORMAT=BOOT, OUTFILE=%^PROGRAM.sec, MODEL=TINY, WIDTH=16, \
              ENTRY=, IMAGEBASE=0, SECTIONALIGN=0, FILEALIGN=0
.
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Viz vzorové projekty boottest.htm a boot16.htm.

↑ COM

Soubory ve formátu COM jsou dědictvím po operačním systému CP/M, jsou přímo spustitelné v DOS a ve 32bitových Windows. V jiných systémech pouze v emulátoru DOSu.

Výchozí volby pro formát COM:

Name: PROGRAM FORMAT=COM,OUTFILE=%^PROGRAM.com,MODEL=TINY,WIDTH=16,IMAGEBASE=0, \
              ENTRY=256,SECTIONALIGN=0,FILEALIGN=0
.

Volby ENTRY=0x100 a IMAGEBASE=0 jsou v tomto formátu pevné a nelze je měnit (mohou být vynechány z instrukce PROGRAM).

€ASM vytvoří implicitní segment [COM] s univerzálním účelem:

[COM] SEGMENT WIDTH=16,ALIGN=16,PURPOSE=CODE+DATA+BSS+STACK+LITERALS
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Struktura souboru COM se podobá formátu BIN, žádné metainformace nejsou v souboru uloženy s výjimkou jeho přípony .com, která říká operačnímu systému, aby jej považoval za spustitelný.
Zaváděč OS alokuje 64 KB paměti, naplní segmentové registry CS,DS,ES,SS paragrafovou adresou tohoto bloku, inicializuje 256 bajtů dlouhou strukturu [PSP] na ofsetu 0, načte obsah souboru na ofset 256 (0x0100), nastaví ukazatel zásobníku na vrchol alokovaného bloku (obvykle SP=0xFFFE) a nakonec nastaví IP=0x0100.

Velikost kódu, dat a zásobníku by dohromady neměla přesáhnout 64 KB. Program ve formátu COM může používat 32bitové registry, pokud je CPU=386 nebo vyšší. Rovněž může za běhu požadovat další paměťové bloky od operačního systému.

Typickou aplikací tohoto zastaralého formátu jsou krátké a rychlé utility a programy Terminate-and-Stay-Resident (TSR) poskytující služby v DOS. Viz ukázkové projekty pro DOS.

Následující příklad programu ve formátu COM je pouze 1 bajt dlouhý, ale i tak je to formálně platný počítačový program, i když nic nedělá:

         EUROASM
Shortest PROGRAM FORMAT=COM
           RET
         ENDPROGRAM Shortest

Program ve formátu COM také může linkovat jiné moduly a knihovny, viz kombinace linkeru.

↑ MZ

Specifikací programového formátu MZ vytvoříme 16bitový, případně 32bitový spustitelný program pro reálný mód, který může být přímo spuštěn v DOS a ve 32bitových Windows. Jeho struktura je popsána v dokumentaci [MZ] a [MZEXE]. Dosový spustitelný program začíná podpisem MZ 'M','Z'.

Výchozí volby pro PROGRAM FORMAT=MZ jsou:

PROGRAM FORMAT=MZ, ENTRY=, OUTFILE=%^PROGRAM.exe, MODEL=SMALL, WIDTH=16, IMAGEBASE=0, \
        SECTIONALIGN=0, FILEALIGN=0, SIZEOFSTACKCOMMIT=8K, SIZEOFHEAPCOMMIT=1M

€ASM vytvoří výchozí implicitní segmenty [CODE], [RODATA], [DATA], [BSS], [STACK] ve formátech MZ, OMF, LIBOMF.

Parametr PROGRAM SizeOfStackCommit= vytváří defaultní velikost segmentu [STACK], takže nemusíme explicitně definovat strojový zásobník, pokud byla volba AUTOSEGMENT= povolena.

Parametr PROGRAM SizeOfHeapCommit= může být použit k omezení velikosti heap prealokované zaváděčem (člen .e_maxalloc Dosové hlavičky).

Pokud je paměťový model HUGE nebo FLAT a šířka programu není explicitně určena, použije se PROGRAM WIDTH=32, jinak je to 16.

ImageBase=0 v tomto formátu a nemůže být měněna.
Explictní stanovení PROGRAM Entry= je v MZ formátu povinné.

Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SIZEOFHEAPRESERVE, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Jako příklad spustitelného programu MZ pro DOS viz test t8300.

↑ OMF

Object Module Format popsaný v dokumentaci [OMF] je určen k linkování do 16bitových a 32bitových programů pro reálný mód. Importy v tomto formátu jsou linkovatelné také do programů v chráněném módu (MS-Windows).

Výchozí segmenty jsou stejné jako u formátu MZ.

Soubor je rozpoznán pro linkování, pokud sestává z platných záznamů OMF a první záznam je THEADR nebo LHEADR.

Výchozí volby pro tento formát jsou:

Name: PROGRAM FORMAT=OMF,OUTFILE=%^PROGRAM.obj,MODEL=SMALL,WIDTH=16
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, FILEALIGN, ICONFILE, IMAGEBASE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Jako příklad modulu OMF viz test t8400.

↑ LIBOMF

Formát knihovny OMF je popsán v Apendix2 stejného dokumentu jako [OMF]. Hashovaný slovník vyžadovaný formátem na konci knihovny je EuroAssemblerem vytvářen, avšak při linkování je ignorován. Je-li knihovna LIBOMF linkována EuroAssemblerem do jiného programu, její PUBLIC symboly budou hledány sekvenčně.
Velikost stránky knihoven LIBOMF vytvářených EuroAssemblerem je napevno 16.

Výchozí segmenty jsou stejné jako ve formátu MZ.

Souborový formát LIBOMF je rozpoznáván pro LINK pokud začíná záznamem LIBHDR s délkou strany 16, 32, 64,..32K, a pokud je tento záznam následován platnými moduly OMF, které začínají záznamem THEADR nebo LHEADR a které končí záznamem MODEND nebo MODEND32. Slovník hashů na konci knihovny není používán.

Výchozí volby formátu PROGRAM FORMAT=LIBOMF jsou:

Name: PROGRAM FORMAT=LIBOMF,OUTFILE=%^PROGRAM.lib

Ostatní vlastnosti jsou zděděny z linkovaných modulů.

Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, FILEALIGN, ICONFILE, IMAGEBASE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MODEL, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM, WIDTH.

Moduly, které mají být vloženy do knihovny, by měly být předem přeloženy do souborů ve formátu OMF. Pokud program představující knihovnu také obsahuje nějaký kód, bude přeložen a uložen jako první modul knihovny. Moduly z jiných linkovaných knihoven, které neobsahují žádný globální symbol, nebudou do cílové knihovny vůbec zařazeny.
Příklad statické knihovny linkované ze tří samostatných modulů:

MyLib: PROGRAM FORMAT=LIBOMF
        LINK "Module1.obj", "Module2.obj", "Module3.obj"
       ENDPROGRAM MyLib

Třebaže byl formát OMF vyvinut pro programy v reálném módu, může být doplněn OMF záznamy COMENT/IMPDEF a taková knihovna importních záznamů použita v programu pro Windows.

Některé knihovní programy, jako [ALIB], vytvářejí delší variantu importních záznamů, která přidává záznamy LEDATA+FIXUPP včetně relokabilního strojového kódu proxy-skoků na importovanou funkci.
€ASM nevytváří delší verzi importních záznamů, ale jak dlouhá, tak krátká verze jsou akceptovány linkerem. Příklad programu vytvářejícího čistě importní knihovnu v krátkém formátu OMF:

ImpLib PROGRAM FORMAT=LIBOMF
  IMPORT LIB="kernel32.dll",TerminateProcess,TerminateThread
  IMPORT LIB="user32.dll",CreateCursor,CreateIcon,CreateMenu
 ENDPROGRAM ImpLib

Jako příklad knihovny LIBOMF viz test t8600.

↑ COFF

EuroAssembler implementuje objektový formát COFF v modifikaci od Microsoftu popsané v [MS_PECOFF]. Tento popis také platí pro €ASM formáty LIBCOF, PE, DLL (formáty založené na COFF).

€ASM zde vytváří výchozí segmenty ("sekce" v terminologii Microsoftu):
[.text], [.rodata], [.data], [.bss]. Strojový zásobník pro spustitelný soubor bude vytvořen zaváděčem při spouštění programu a nemusíme se o něj starat.

Výchozí volby pro PROGRAM FORMAT=COFF jsou:

PROGRAM FORMAT=COFF,OUTFILE=%^PROGRAM.obj,MODEL=FLAT,WIDTH=32
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, FILEALIGN, ICONFILE, IMAGEBASE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Hodnota generovaná do členu PFCOFF_FILE_HEADER.Machine je pro zděděný mód COFF vždy 0x014C (Intel 386) bez ohledu na hodnotu EUROASM CPU=. Pro 64bitový mód PECOFF je vždy 0x8664 (architektura AMD64). Architektura Itanium (0x0200) není podporována

Obsah členu PFCOFF_FILE_HEADER.TimeDateStamp odpovídá aktuálnímu systémovému času, ledaže by byl zfalšován volbou EUROASM TIMESTAMP=.

Linkovaný modul COFF je rozeznáván obsahem členu PFCOFF_FILE_HEADER.Machine, který může mít jednu z hodnot 0x0000, 0x014C, 0x014D, 0x014E, 0x0200, 0x8664.

Jako příklad modulu COFF viz test t8850 (pro Windows) nebo t9000 (pro Linux).

↑ LIBCOF

Formát knihovny COFF je popsán v [COFFlib].

Výchozí volby pro PROGRAM FORMAT=LIBCOF jsou:

PROGRAM FORMAT=LIBCOF,OUTFILE=%^PROGRAM.lib,MODEL=FLAT,WIDTH=32

Výchozí segmenty jsou stejné jako u formátu COFF.

Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, FILEALIGN, ICONFILE, IMAGEBASE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

Knihovna COFF je identifikována podpisem !<arch> následovaným bajtem 0x0A.

Knihovnu LIBCOF můžeme vytvořit linkováním z jiných objektových souborů. Moduly by měly být nejprve přeloženy do souborů ve formátu COFF (ale lze i OMF nebo ELF). Pokud program představující knihovnu také obsahuje nějaký kód (mimo instrukce LINK), bude přeložen a uložen jako první člen knihovny. Moduly nedeklarující žádný globální symbol nebudou do knihovny vůbec zařazeny. Příklad knihovny LIBCOF obsahující tři moduly:

MyLib: PROGRAM FORMAT=LIBCOF
         LINK "Module1.obj", "Module2.obj", "Module3.obj"
       ENDPROGRAM MyLib

€ASM nevytváří delší verzi importních knihovních záznamů, ale jeho linker akceptuje dlouhou i krátkou verzi. Příklad programu vytvářejícího importní knihovnu v krátkém formátu:

ImpLib: PROGRAM FORMAT=LIBCOF
         IMPORT LIB="kernel32.dll",TerminateProcess,TerminateThread
         IMPORT LIB="user32.dll",CreateCursor,CreateIcon,CreateMenu
        ENDPROGRAM ImpLib:

Jako příklad knihovny LIBCOF viz test t9150.

↑ ELF

ELF neboli Executable and Linkable Format je používán v Linuxu. Existují tři druhy souborů ELF:

Výchozí volby pro PROGRAM FORMAT=ELF jsou

Name: PROGRAM FORMAT=ELF, OUTFILE=%^PROGRAM.o, MODEL=FLAT, WIDTH=32, \
      FILEALIGN=16

ELF je objektový (linkovatelný) soubor s přípomou .o. Jeho defaultní segmenty jsou [.text], [.rodata], [.data], [.bss]. Segmentům se říká sekce v dokumentaci [ELF]. Vedle těchto "sekcí" vytváří €ASM také služební sekce [.symtab], [.strtab], [.shstrtab], [.rela.text], [.rela.data] aj.. Viz test t9750 jako příklad objektu ELF.

Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, ICONFILE, IMAGEBASE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

↑ ELFX

Spustitelnému programu pro Linux přiděluje €ASM souborovou příponu .x, pokud není předepsáno jinak volbou PROGRAM OUTFILE=.

Formát ELFX vytváří segmentové skupiny [LOAD.HDR], [LOAD.CODE], [LOAD.RODATA], [LOAD.DATA], viz například test t9850. Těmto skupinám se v [ELF] dokumentaci říká program headers.

Name: PROGRAM FORMAT=ELFX, OUTFILE=%^PROGRAM.x, MODEL=FLAT, WIDTH=32, \
    ENTRY=, IMAGEBASE=4M, FILEALIGN=16, SECTIONALIGN=4K

Výchozí přípona souboru je .x. Parametr ENTRY= je povinný, určuje vstupní bod programu.

Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

↑ ELFSO

Volba PROGRAM FORMAT=ELFSO vytváří DSO - Dynamic Shared Object pro Linux. EuroAssembler vytváří DSO s příponou souboru .so, avšak neumí jej dynamicky linkovat, nenahrazuje zde funkcionalitu komplexního Linuxového dynamického linkeru GNU ld. Soubor DSO může být linkován do programu ELFX pouze staticky.

Name: PROGRAM FORMAT=ELFSO, OUTFILE=%^PROGRAM.so, MODEL=FLAT, WIDTH=32, \
    IMAGEBASE=4M, FILEALIGN=4K, SECTIONALIGN=4K
Následující volby pseudoinstrukce PROGRAM jsou irelevantní: DLLCHARACTERISTICS, ENTRY, ICONFILE, MAJOROSVERSION, MAJORSUBSYSTEMVERSION, MAJORIMAGEVERSION, MAJORLINKERVERSION, MINOROSVERSION, MINORSUBSYSTEMVERSION, MINORIMAGEVERSION, MINORLINKERVERSION, WIN32VERSIONVALUE, SECTIONALIGN, SIZEOFHEAPCOMMIT, SIZEOFHEAPRESERVE, SIZEOFSTACKCOMMIT, SIZEOFSTACKRESERVE, STUBFILE, SUBSYSTEM.

↑ PE

Portable Executable formát PE pro Windows je popsán v dokumentu [MS_PECOFF]. Výchozí volby pro PROGRAM FORMAT=PE jsou

Name: PROGRAM FORMAT=PE,OUTFILE=%^PROGRAM.exe,MODEL=FLAT,WIDTH=32,IMAGEBASE=4M,FILEALIGN=512,SECTIONALIGN=4K, \
              SUBSYSTEM=CON,ICONFILE="euroasm.ico",MAJORLINKERVERSION=1,MINORLINKERVERSION=0,ENTRY=,          \
              MAJOROSVERSION=4,MINOROSVERSION=0,MAJORIMAGEVERSION=1,MINORIMAGEVERSION=0,                      \
              MAJORSUBSYSTEMVERSION=4,MINORSUBSYSTEMVERSION=0,WIN32VERSIONVALUE=0,DLLCHARACTERISTIC=0x000F,   \
              SIZEOFSTACKRESERVE=1M,SIZEOFSTACKCOMMIT=8K,SIZEOFHEAPRESERVE=4M,SIZOHEAPCOMMIT=1M

Výchozí segmenty jsou stejné jako ve formátu COFF.

Soubor PE začíná Dosovým programem (stub) ve formátu MZ, který se spouští pokud PE program není spuštěn ve Windows. Na pozici členu PFMZ_DOS_HEADER.e_lfanew očekává signaturu PE s bajty 'P','E',0,0.

Starší souborový formát se signaturou NE (New Executable), používaný v 16bitových Windows a OS/2, není EuroAssemblerem podporován.

Po souborové hlavičce COFF následuje PFPE_OPTIONAL_HEADER. Téměř všechna její pole lze konfigurovat pomocí voleb pseudoinstrukce PROGRAM.
Položka PROGRAM ENTRY= je v PE formátu povinná.
Volba PROGRAM STUBFILE= specifikuje jméno MZ programu použitého, když byl náš program spuštěn v DOS. Pokud je ponecháno prázdné, €ASM použije vlastní vestavěný stub, který oznámí This program was launched in DOS but it requires Windows. a skončí.
Výchozí volba PROGRAM ICONFILE="euroasm.ico" určuje jméno souboru s ikonou , která bude vestavěna do segmentu resources spustitelného souboru. Vizuálně reprezentuje náš program na Ploše nebo v Průzkumníku Windows.

Tento parametr je ignorován, pokud byl explicitně přilinkován libovolný soubor resources; pak se použije první ikona z tohoto souboru. Je-li volba ICONFILE= prázdná, a pokud není přilinkován žádný soubor resources, příslušná sekce [.rsrc] bude z PE souboru zcela vynechána.

Po "volitelné" hlavičce následuje 16 záznamů speciálních adresářů, které identifikují sekce s účely jinými než běžné účely CODE, DATA, BSS. Viz posledních 16 řádků lines v tabulce účelu segmentů, počínaje EXPORT.

EuroAssembler nativně podporuje jen několik speciálních adresářů:

EXPORT
automaticky vytváří sekci [.edata] s tabulkou exportovaných symbolů.
IMPORT
automaticky vytváří sekci [.idata] s tabulkou jmen a čísel importovaných symbolů.
RESOURCE
se vytváří, když je soubor se zdroji přilinkován nebo pokud volba ICONFILE= specifikuje existující ikonu.
BASERELOC
obsahuje tabulku relokací, která musí být aplikována zaváděčem programu, pokud PE nemohl být zaveden na adresu preferovanou ve volbě IMAGEBASE=.
IAT
importní adresní tabulka se vytváří v sekci [.idata], stejné jako speciální adresář IMPORT. Spojení tabulek IAT, IMPORT a thunk proxy skoků do jedné společné sekce [.idata] šetří velikost image.

Ostatní speciální adresáře nejsou v této verzi €ASM podporovány. Nicméně jejich segmenty mohou být definovány explicitně a jejich obsah vytvořen ručně nebo nějakou utilitou třetí strany, a pak emitován do segmentu pomocí INCLUDEBIN nebo definicemi dat. Pokud parametr segmentu PURPOSE= přesně (až na velikost písmen) souhlasí s názvem v tabulce účelů, bude vytvořen odpovídající vstup ve "volitelné" hlavičce PE, který pokryje celý obsah segmentu. Příklad:

[.cormeta] SEGMENT PURPOSE=CLR
 D '<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">'
 D '  <application>'
 D '     <!-- A list of all Windows versions that this application is designed to work with.>'
 D '   </application>'
 D ' </compatibility>'

Pokud je povolena volba EUROASM DEBUG=ENABLED, tabulka symbolů bude připojena k image souboru PE.

Debugery by měly být schopny načítat symbolická jména z laděného spustitelného souboru, a spojit je s disasemblovanými zdrojovými řádky. Bohužel ale žádný z mně známých debugerů nebyl schopen využít tabulku symbolů z PE (místo toho bylo třeba nejprve přeložit do formátu COFF).

↑ DLL

Souborový formát DLL je téměř identický s formátem PE, s několika drobnými rozdíly:
Člen souborové hlavičky PFCOFF_FILE_HEADER.Characteristic je označen jako pfcoffFILE_DLL = 0x2000,
výchozí přípona souboru je .dll, ImageBase je 256 MB.

Name: PROGRAM FORMAT=DLL,OUTFILE=%^PROGRAM.dll,IMAGEBASE=256M

Volba ENTRY= je u DLL nepovinná.

Výchozí segmenty jsou stejné jako ve formátu COFF.

Dynamicky linkovatelné symboly musí být deklarovány s viditelností EXPORT.
Pseudoinstruckce EXPORT podporuje DLL forwarding exportovaných funkcí do jiné funkce v jiné knihovně DLL, používajíc klíčové operandy EXPORT se jmény FWD= and LIB=. Viz test t9475 jako příklad forwardingu.

Formát DLL může být používán pro knihovnu resource, která obsahuje pouze sekci [.rsrc], typicky se jedná o sbírku ikon. Toho je dosaženo linkováním souboru resources, který byl vytvořen pomocí resource kompileru třetí strany. Příklad resource-only DLL obsahující 3 ikony můžeme vidět v testech t9485 a t9536.

↑ RSRC

Microsoft resources je obecné jméno pro multimediální data, jako bitmapové obrázky, ikony, tvary kurzorů, fonty apod. Tyto zdroje (resources) používané v grafických programech jsou popsány ve skriptu resources jako strom odkazující na jednotlivé prvky grafických souborů. Typický skript je prostý textový soubor s příponou .rc a měl by být zkonvertován pomocí resource compiler na binární soubor resources s příponou .res, kterou umí €ASM linkovat. Jeho formát je popsán v dokumentaci [RSRC].

MyCompiledResource PROGRAM FORMAT=RSRC nefunguje, EuroAssembler neumí kompilovat skripty resources. Použijte nástroj třetí strany, jako [MS_RC], [GoRC], nebo [ResourceHacker].

Je-li soubor resources linkován do PE nebo DLL image vytvořené EuroAssemblerem, volba PROGRAM ICONFILE= se ignoruje. Soubor je přeložen na interní strukturu binárního stromu v sekci [.rsrc], na niž odkazuje speciální adresář RESOURCE.

↑ Šířka formátů

Šířka výstupních souborů linkovaných EuroAssemblerem je určována volbou PROGRAM WIDTH=, jejíž výchozí hodnota pro formáty založené na COFF je 32 bitů. K vytvoření 64bitových programů ELF, ELFX, ELFSO, PE, DLL, COFF nebo LIBCOF musí být explicitně stanovena PROGRAM WIDTH=64. Rovněž by pak měla být povolena volba EUROASM CPU=X64.

Rozdíly mezi formáty PE-COFF generovanými EuroAssemblerem
ČlenPROGRAM WIDTH=16PROGRAM WIDTH=32PROGRAM WIDTH=64
PFCOFF_FILE_HEADER.Machine 0x014C (Intel 386)0x014C (Intel 386)0x8664 (AMD64)
PFCOFF_FILE_HEADER.Characteristics:32BIT_MACHINE 0 (nepravda)0x0100 (pravda)0 (nepravda)
PFCOFF_FILE_HEADER.Characteristics:LARGE_ADDRESS_AWARE 0 (nepravda)0 (nepravda)0x0020 (pravda)
PFPE_OPTIONAL_HEADER32.Magic 0x010B (PE32)0x010B (PE32)0x020B (PE32+)
SIZE# PFPE_OPTIONAL_HEADER32 224224240

↑ Funkce EuroAssembleru

Preprocesing ↓

Refaktorizace ↓

Asembler ↓

Hledání chyb v asembleru ↓

Linker ↓

Knihovník ↓

Objektový konvertor ↓

Makefile manažer ↓

Optimalizace ↓

Kde začít ↓

Tato kapitola popisuje možnosti EuroAssembleru

↑ Preprocesing

Mnoho asemblerů poskytuje nástroje pomáhající programátorovi s opakující se namáhavou prací, říká se jim makroasemblery. Preprocesní (makro) aparát je v EuroAssembleru rozpoznatelný podle znaménka procenta % přidaného před pseudoinstrukce řídicí opakované generování bloků kódu (%REPEAT, %WHILE, %FOR, %MACRO), podmíněný překlad (%IF, %COMMENT), laděni v asm-time (%DISPLAY) a přiřazování a expanzi preprocesních %proměnných (rodina pseudoinstrukcí %SET*).

Tato sbírka nástrojů manipuluje se zdrojovým textem dříve, než je předložen ke konečnému zpracování asemblerem (předložen prostému asembleru, který o preprocesním aparátu nic neví).

Některé kompilery provedou preprocesing ve speciálním nultém průchodu, který načítá vstupní zdrojový kód a jehož výstupem je kód prostého asembleru. Předzpracovaný mezikód pak může být manuálně prohlédnut.

EuroAssembler používá odlišný přístup: namísto předzpracování celého zdrojového souboru najednou jej předzpracovává instrukci po instrukci v každém průchodu. To dovoluje manipulovat i s údaji, jenž se dynamicky mění a které nejsou pevné dříve než €ASM dostal příležitost projít celým programem aspoň jednou; týká se to například vzdálenosti mezi návěstími, velikosti dosud nedefinovaných struktur apod.

Když €ASM čte řádek zdrojového textu, nejprve ho prohledá, zda obsahuje procento %. Pokud ano, dívá se na následující znak a připraví kopii zdrojového řádku pro prostý asembler, expandovanou dle následujících pravidel:
Znak následující %PříkladCo jej nahradí
%%%Jednoduchý znak procenta %
&%&Velikost nebo délka suboperace
.%.Počitadlo expanzí
:%:Návěstí makra
!%!formalInvertovaná podmínka, např. NC
*%*Seznam pořadových operandů makra
#%#Počet pořadových operandů makra
=*%=*Seznam klíčových operandů makra
=#%=#Počet klíčových operandů makra
^identifier%^WidthSystémová %^proměnná (čísla 16, 32 nebo 64}
decimal digit(s)%12Pořadový operand makra, např. dvanáctý
letter(s) %IfJméno pseudoinstrukce je ponecháno neexpandované (%If)
%SizePokud je to formální operand, bude expandován na svou hodnotu,
%OtherIdjinak je expandován jako uživatelem definovaná preprocesní %proměnná
Pro více detailů ohledně viditelnosti %proměnných viz zdrojový text VarExpand.

Vztah mezi preprocesingem a prostým asemblerem se podobá vztahu mezi Javascriptem a prostým textem HTML v internetových browserech.

Správnou funkci €ASM preprocesingu můžeme zkontrolovat v listingu povolením voleb EUROASM LISTVAR=ENABLE, LISTREPEAT=ENABLE, LISTMACRO=ENABLE.

↑ Refaktorizace

Inline kód↓

Přeskočená PROC ↓

PROC ve vlastní sekci ↓

PROC1 ↓

PROC v INCLUDE ↓

Staticky linkovaná PROC ↓

Dynamicky linkovaná PROC ↓

Inline makro ↓

Makro volající PROC ↓

Napůl-inline makro ↓

V této kapitole se podíváme, jako se dá v €ASM rozdělit funkčnost programu na menší subprogramy.

Dejme tomu, že budeme potřebovat funkci, která kalkuluje třetí mocninu kladného čísla. Výsledek by se měl vejít do 32 bitů, jinak program ohlásí přetečení a skončí.

Předpokládejme 32bitový mód a vstupní číslo načtené do registru EAX. Použijeme instrukci MUL (unsigned multiplication) dvakrát:

↑ Inline kód

Přímé řešení vkládá kód přímo do hlavního toku programu.

    ; EAX obsahuje vstupní číslo N.
    MOV ECX,EAX ; Zkopíruj vstupní číslo N do registru ECX.
    MUL ECX     ; Nechť EDX:EAX = N*N
    JC Abort:   ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
    MUL ECX     ; Nechť EDX:EAX = N*N*N
    JC Abort:   ; Abort při přetečení.
    ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ Přeskočená PROC

Pokud je výše zmíněná kalkulace potřebná častěji než jednou, měli bychom uvážit refactorizaci přímého kódu na subproceduru, která bude volána opakovaně. Vložíme proceduru nazvanou Cube do hlavního toku programu, když bude její funkce poprvé potřeba. Vložení volatelné procedury vyžaduje její přeskočení.

       ; EAX obsahuje vstupní číslo N.
       CALL Cube:  ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
       JMP Bypass: ; Přeskoč kód funkce.
Cube PROC  ; Procedura kalkuluje třetí mocninu N.
; Input:   EAX=celé číslo N.
; Output:  CF=OF=0, EAX=N3, ECX=N, EDX=0.
; Overflow:CF=OF=1, EAX,ECX,EDX nedefinováno.
       MOV ECX,EAX ; Zkopíruj vstupní číslo N do registru ECX.
       MUL ECX     ; Nechť EDX:EAX = N*N
       JC .Abort   ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
       MUL ECX     ; Nechť EDX:EAX = N*N*N
.Abort:RET         ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
     ENDPROC Cube
Bypass:  ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ PROC ve vlastní sekci

Instrukci JMP Bypass: bychom mohli uspořit, pokud by procedura byla definována někde jinde, mimo programový tok. Toho lze dosáhnout přemístěním procedury do jiné sekce, například do [Subproc].

       ; EAX obsahuje vstupní číslo N.
       CALL Cube:  ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
%CurrentSect %SET %^Section ; Zálohuj jméno současné sekce do %proměnné.
[Subproc]  ; Přepni emitování do jiné kódové sekce.
Cube PROC  ; Procedura kalkuluje třetí mocninu N.
; Input:   EAX=celé číslo N.
; Output:  CF=OF=0, EAX=N3, ECX=N, EDX=0.
; Overflow:CF=OF=1, EAX,ECX,EDX nedefinováno.
       MOV ECX,EAX ; Zkopíruj vstupní číslo N do registru ECX.
       MUL ECX     ; Nechť EDX:EAX = N*N
       JC .Abort   ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
       MUL ECX     ; Nechť EDX:EAX = N*N*N
.Abort:RET         ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
     ENDPROC Cube
[%CurrentSect]     ; Návrat k původní sekci.
        ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ PROC1

Namísto ručního přepnutí do odlišné sekce bychom mohli využít blok PROC1..ENDPROC1, který přepíná do jiné sekce [@RT1] a vrací se zpět zcela automaticky.

       ; EAX obsahuje vstupní číslo N.
       CALL Cube:  ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
Cube PROC1 ; Procedura kalkuluje třetí mocninu N. Je umístěna v sekci [@RT1].
; Input:   EAX=celé číslo N.
; Output:  CF=OF=0, EAX=N3, ECX=N, EDX=0.
; Overflow:CF=OF=1, EAX,ECX,EDX nedefinováno.
       MOV ECX,EAX ; Zkopíruj vstupní číslo N do registru ECX.
       MUL ECX     ; Nechť EDX:EAX = N*N
       JC .Abort   ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
       MUL ECX     ; Nechť EDX:EAX = N*N*N
.Abort:RET         ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
     ENDPROC1 Cube ; Konec procedury v sekci [@RT1]. Návrat do [.text].
      ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ PROC v INCLUDE

Definice funkce Cube v místě, kde je použita, je vhodná pro porozumění. Na druhé straně, pokud je takových funkcí více, zahlcuje to hlavní linku programu. Organizace by byla jasnější, pokud by pomocné podprogramy byly odloženy do jiného souboru, např. functions.inc. Tento soubor pak bude inkludována do hlavního zdrojového kódu v asm-time.

       INCLUDE "functions.inc" ; Soubor obsahující proceduru Cube: PROC.
       ; EAX obsahuje vstupní číslo N.
       CALL Cube:  ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
       ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

Funkce definované v inkludovaném souboru functions.inc mohou být zabaleny do bloku functions PROGRAM..ENDPROGRAM a přeloženy zvlášť do objektového formátu OMF, ELF nebo COFF functions.obj, případně do knihovny objektů. Jméno funkce (Cube) musí být deklarováno jako GLOBAL nebo PUBLIC v objektovém kódu, a jako GLOBAL nebo EXTERN v hlavním souboru. Namísto explicitní deklarace pomocí GLOBAL lze globálnost funkcí označovat dvojitou dvojtečkou (Cube::). Přeložený objekt pak bude staticky linkován do hlavního programu v link-time.

       LINK "functions.obj" ; Objektový soubor s procedurou Cube.
       ; EAX obsahuje vstupní číslo N.
       CALL Cube:: ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
       ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

Funkce definované v inkludovaném souboru functions.inc také mohly být zabaleny do bloku functions PROGRAM..ENDPROGRAM a přeloženy zvlášť do dynamicky linkované knihovny functions.dll. Jméno funkce (Cube) musí být deklarováno jako EXPORT v této knihovně, a jako IMPORT v hlavním spustitelném souboru. Přeložená funkce z programu DLL pak bude dynamicky svázána s hlavním programem v bind-time.

       IMPORT Cube, LIB="functions.dll"
       ; EAX obsahuje vstupní číslo N.
       CALL Cube:: ; Vyvolej funkci, která kalkuluje N3.
       JC Abort:   ; Abort při overflow.
       ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ Inline macro

Alternativní přístup k opakování inline kódu je využití makra, které expanduje kdykoli je požadována jeho funkčnost.

Instrukce, které definují makro, nemusí být přeskakovány, neboť neemitují žádný kód, avšak makrodefinice se musí objevit dříve, než bude makro použito. Tato definice také mohla být odložena do inkludovaného souboru, podobně jako v metodě PROC v INCLUDE.

Cube %MACRO
       MOV ECX,EAX ; Zkopíruj vstupní číslo N do registru ECX.
       MUL ECX     ; Nechť EDX:EAX = N*N
       JC Abort%.: ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
       MUL ECX     ; Nechť EDX:EAX = N*N*N
Abort%.:           ; Jméno návěstí je modifikováno %proměnnou %., jež se inkrementuje při každé expanzi.
     %ENDMACRO Cube
     ; EAX obsahuje vstupní číslo N.
     Cube          ; Expanze makra.
     JC Abort:     ; Abort při overflow.
     ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ Makro volající PROC

Inline makra jsou rychlá, ale každá invokace opakuje celý kód procedury. Velikost programu bychom mohli omezit, pokud by makro volalo proceduru s funkčním kódem, která mohla být rovněž odložena do inkludovaného functions.inc. Funkce makra pak bude omezena na předání eventuálních parametrů a skrytí volací konvence (v našem prostém příkladu ale žádné parametry předávány nejsou).

     INCLUDE "functions.inc" ; Soubor s definicí procedury Cube.
Cube %MACRO       ; Definuj makro Cube.
       CALL Cube: ; Volání procedury Cube:
     %ENDMACRO Cube
     ; EAX obsahuje vstupní číslo N.
     Cube         ; Vyvolej makro volající inkludovanou proceduru.
     JC Abort     ; Abort při overflow.
     ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ Napůl-inline makro

Nevýhodou předchozí metody je, že musíme udržovat dva bloky kódu: definici makra a definici procedury. €ASM poskytuje blok procedury PROC1, který se překládán pouze jednou, i když je makro tento blok obsahující voláno opakovaně. Díky tomu je kód procedury emitován pouze jednou, když je makro voláno poprvé, a pokud by nebylo vůbec voláno, kód procedury se vůbec neemituje. Makroknihovna s takovými napůl-inline makry může být začleněna do zdrojového kódu a nezvyšuje přitom velikost výsledného kódu, pokud makro nebylo v programu použito (expandováno).

Tato metoda je preferována ve většině makroknihoven dodaných s EuroAssemblerem.

Cube %MACRO          ; Definice napůl-inline maker Cube.
       CALL Cube:    ; Volání procedury Cube:
 Cube: PROC1         ; PROC1 blok je emitován pouze jednou při první expanzi makra.
         MOV ECX,EAX ; Kopíruj vstupní číslo N do registru ECX.
         MUL ECX     ; Nechť EDX:EAX = N*N
         JC .Abort:  ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
         MUL ECX     ; Nechť EDX:EAX = N*N*N
  .Abort:RET         ; CF=OF=1 pokud je EDX nenulové (32bitové přetečení).
       ENDPROC1 Cube:
     %ENDMACRO Cube
     ; EAX obsahuje vstupní číslo N.
     Cube            ; Vyvolej makro, které volá PROC1.
     JC Abort        ; Abort při overflow.
     ; EAX nyní obsahuje N3, pokračuj v hlavním toku programu.

↑ Asembler

Obálka zdrojového programu ↓

Řetězené programy ↓

Vnořené programy ↓

Tato kapitola se blíže zabývá, jak jsou bloky programu zpracovány EuroAssemblerem.

↑ Obálka zdrojového programu

Uvažme prostý textový soubor src.asm předložený asembleru:

 DB 'This source "src.asm" has'
 DB ' no PROGRAM statement.',13,10
 DB 'EuroAssembler will use '
 DB 'a fictive envelope instead.'

Jelikož v souboru není definován žádný blok PROGRAM..ENDPROGRAM, výstupní formát cílového souboru je určen pouze sekcí [PROGRAM] konfiguračního souboru euroasm.ini, nebo vestavěným továrním defaultem, kterým je PROGRAM FORMAT=BIN,MODEL=TINY,WIDTH=16.

EuroAssembler formálně balí každý zdrojový soubor do dvou fiktivních obálkových pseudoinstrukcí PROGRAM a ENDPROGRAM. Přidaná obálková instrukce PROGRAM odvozuje své návěstí (název modulu) ze jména zdrojového souboru po odříznutí přípony. Ze zdrojového souboru src.asm tedy vytvoří binární soubor src.bin. To je chování kompatibilní s mnoha dalšími asemblery.

Pokud by jméno zdrojového souboru začínalo číslicí, např. 123.asm, takový název programu není přijatelný pro €ASM, který proto před jméno modulu přidá znak grave ` a zdroj 123.asm bude přeložen na `123.bin.

Podobně, pokud by návěstí pseudoinstrukce PROGRAM obsahovalo otazník ? nebo jiný znak nepřijatelný pro souborový systém, takový znak pak bude v názvu souboru nahrazen podtržítkem _. Instrukce IsNumlockOn? PROGRAM FORMAT=COM vyrobí program se jménem IsNumlockOn_.com.

€ASM používá ANSI verze Windows API pro zacházení se jmény souborů, takže je lepší se vyvarovat národních znaků mimo aktuální codepage ve jménech souborů.

Jakmile je zdrojový soubor načten v paměti, €ASM začíná číst zdroj počínaje fiktivní obálkovou instrukcí PROGRAM. Až bude načtena odpovídající pseudoinstrukce ENDPROGRAM, skončil jeden průchod asembleru. €ASM se podívá na všechny symboly nadefinované v programu a kontroluje, zda jejich ofsety jsou označeny jako fixed, tj. nezměnily se mezi průchody. Jestliže aspoň jeden symbol dosud nemá svůj ofset zafixován, je potřeba další průchod a €ASM se vrací k pseudoinstrukci PROGRAM. Až budou mít všechny symboly ofset stabilní, €ASM zahájí finální průchod, v němž se generuje kód a data do cílového souboru a také se generuje listing. K přeložení každého programu jsou zapotřebí nejméně dva průchody.

                                                     assembly progress ─>
┌─────────┬──────────────────────────────────┐
│envelope │src: PROGRAM                      │      █       ┌█
├─────────┼──────────────────────────────────┤       █      │ █
│      {1}│ DB 'This source "src.asm" has'   │        █     │  █
│"src.asm"│ DB ' no PROGRAM statement.',13,10│         █    │   █
│      {3}│ DB 'EuroAssembler will use '     │          █   │    █
│      {4}│ DB 'a fictive envelope instead.' │           █  │     █
├─────────┼──────────────────────────────────┤            █ │      █
│envelope │ ENDPROGRAM src:                  │             █┘       █─┐
└─────────┴──────────────────────────────────┘
                                                   ││        │      │ │
I0010 EuroAssembler started.───────────────────────┤│        │      │ │
I0180 Assembling source file "src.asm".────────────┤│        │      │ │
I0270 Assembling source "src".─────────────────────┘│        │      │ │
I0310 Assembling source pass 1.─────────────────────┘        │      │ │
I0330 Assembling source pass 2 - final.──────────────────────┘      │ │
I0760 16bit TINY BIN file "src.bin" created from source, size=99.───┘ │
I0750 Source "src" (4 lines) assembled in 2 passes with errorlevel 0.─┤
I0860 Listing file "src.asm.lst" created, size=717.───────────────────┤
I0990 EuroAssembler terminated with errorlevel 0.─────────────────────┘

Dvě obálkové pseudoinstrukce jsou použity nezávisle na tom, zda byl explicitní blok PROGRAM..ENDPROGRAM ve zdrojovém textu definován či ne. Zdrojové řádky mezi začátkem souboru a explicitní pseudoinstrukcí PROGRAM, stejně jako řádky mezi explicitní pseudoinstrukcí ENDPROGRAM a koncem souboru be neměly emitovat žádný kód ani data. V tom případě je obálkový zdroj prázdný a nevytváří se z něj žádný cílový soubor.

Uvažme následující zdrojový soubor src.asm. Obsahuje explicitní blok Src:PROGRAM..ENDPROGRAM Src: (řádky 5..8) uvnitř neviditelných obálkových pseudoinstrukcí src: PROGRAM a ENDPROGRAM src:. Když byl interní blok Src:PROGRAM..ENDPROGRAM Src: spatřen během překladu, celý tento blok je přeskočen až dokud nedojde k poslednímu průchodu vnějším blokem src: PROGRAM..ENDPROGRAM src:. Pak €ASM odloží momentálně překládaný poslední průchod stranou, a začne překládat vnitřní blok v potřebném počtu průchodů, dokud nevytvoří a neuzavře cílový soubor. Pak se €ASM vrátí k dokončení posledního průchodu předtím přerušeného průchodu vnějším (obálkovým) programem.

    EUROASM ; Common options.
    ; Source file "src.asm"
    ; with PROGRAM defined
explicitly.
Src:PROGRAM FORMAT=BIN
     DB 'Data emitted '
     DB 'by program Src.'
     ENDPROGRAM Src:

Všimněte si chyby: zalomení komentářového řádku {3} způsobilo vznik ne-komentářového řádku {4}. Výraz explicitly. bude považován za platné návěstí (definice adresního symbolu). To způsobí, že obálkový program již není považován za prázdný a bude z něj vytvořen cílový binární soubor src.bin, i když s nulovou délkou (obsahuje pouze jeden symbol s nulovou délkou).
Vnitřní program z řádků {5..8} vytváří cílový soubor Src.bin dlouhý 28 bajtů, avšak ten bude hned přepsán obálkovým cílovým souborem src.bin s nulovou délkou, který má náhodou téměř identické jméno (souborový systém v Dos a Windows je nezávislý na velikosti znaků).


┌─────────┬──────────────────────────────────┐  █              assembly progress ─────────>
│envelope │src: PROGRAM                      │   █         ┌█         ┌█
├─────────┼──────────────────────────────────┤    █        │ █        │ █
│      {1}│ EUROASM ; Common options.        │     █       │  █       │  █
│      {2}│    ; Source file "src.asm"       │      █      │   █      │   █
│      {3}│    ; with PROGRAM defined        │       █     │    █     │    █
│      {4}│explicitly.                       │        █┐   │     █┐   │     █
│"src.asm"│Src:PROGRAM FORMAT=BIN            │         │   │      │   │      █─█   ┌█
│      {6}│     DB 'Data emitted '           │         │   │      │   │         █  │ █
│      {7}│     DB 'by program Src.'         │         │   │      │   │          █ │  █
│      {8}│     ENDPROGRAM Src:              │         └█  │      └█  │           █┘   █┐
├─────────┼──────────────────────────────────┤           █ │        █ │                 └█
│envelope │ ENDPROGRAM src:                  │            █┘         █┘                   █┐
└─────────┴──────────────────────────────────┘
                                                ││          │          │    │ ││    │  │  ││
I0010 EuroAssembler started.────────────────────┤│          │          │    │ ││    │  │  ││
I0180 Assembling source file "src.asm".─────────┤│          │          │    │ ││    │  │  ││
I0270 Assembling source "src".──────────────────┘│          │          │    │ ││    │  │  ││
I0310 Assembling source pass 1.──────────────────┘          │          │    │ ││    │  │  ││
I0310 Assembling source pass 2.─────────────────────────────┘          │    │ ││    │  │  ││
I0330 Assembling source pass 3 - final.────────────────────────────────┘    │ ││    │  │  ││
W2101 Symbol "explicitly." was defined but never used. "src.asm"{4}─────────┘ ││    │  │  ││
I0470 Assembling program "Src". "src.asm"{5}──────────────────────────────────┘│    │  │  ││
I0510 Assembling program pass 1. "src.asm"{5}──────────────────────────────────┘    │  │  ││
I0530 Assembling program pass 2 - final. "src.asm"{5}───────────────────────────────┘  │  ││
I0660 16bit TINY BIN file "Src.bin" created, size=28. "src.asm"{8}─────────────────────┤  ││
I0650 Program "Src" assembled in 2 passes with errorlevel 0. "src.asm"{8}──────────────┘  ││
W3990 Overwriting previously generated output file "Src.bin".─────────────────────────────┤│
I0760 16bit TINY BIN file "src.bin" created from source, size=0.──────────────────────────┤│
I0750 Source "src" (8 lines) assembled in 3 passes with errorlevel 3.─────────────────────┤│
I0860 Listing file "src.asm.lst" created, size=1372.──────────────────────────────────────┘│
I0990 EuroAssembler terminated with errorlevel 3.──────────────────────────────────────────┘

↑ Řetězené programy

EuroAssembler dovoluje definovat v jednom zdrojovém souboru více programových bloků a pak je překládat jedním příkazem. Pamatujte, že symboly použité v různých blocích PROGRAM..ENDPROGRAM mají privátní viditelnost, takže se navzájem nevidí, i když byly definovány ve stejném zdrojovém souboru. Chceme-li volat proceduru definovanou v Pgm1 z programu Pgm2, volaný symbol musí být globální a oba přeložené moduly musejí být slinkovány dohromady.

┌─────────┬──────────────────────────────────┐ █            assembly progress ─────────────────>
│envelope │src: PROGRAM                      │  █       ┌█
├─────────┼──────────────────────────────────┤   █      │ █
│      {1}│     EUROASM ; Common options.    │    █     │  █
│      {2}│Pgm1:PROGRAM FORMAT=PE,ENTRY=Run1:│     █┐   │   █─█   ┌█   ┌█
│      {3}│      ; Pgm1 data.                │      │   │      █  │ █  │ █
│      {4}│Run1: ; Pgm1 code.                │      │   │       █ │  █ │  █
│"src.asm"│     ENDPROGRAM Pgm1:             │      │   │        █┘   █┘   █┐
│      {6}│     ; Pgm2 description.          │      │   │                   █
│      {7}│Pgm2:PROGRAM FORMAT=PE,ENTRY=Run2:│      │   │                   └█   ┌█   ┌█
│      {8}│      ; Pgm2 data.                │      │   │                     █  │ █  │ █
│      {9}│Run2: ; Pgm2 code.                │      │   │                      █ │  █ │  █
│     {10}│      ENDPROGRAM Pgm2:            │      └█  │                       █┘   █┘   █┐
├─────────┼──────────────────────────────────┤        █ │                                  └█
│envelope │ ENDPROGRAM src:                  │         █┘                                    █┐
└─────────┴──────────────────────────────────┘
                                               ││        │    │    │    │  │ │    │    │   │ ││
I0010 EuroAssembler started.───────────────────┤│        │    │    │    │  │ │    │    │   │ ││
I0180 Assembling source file "src.asm".────────┤│        │    │    │    │  │ │    │    │   │ ││
I0270 Assembling source "src".─────────────────┘│        │    │    │    │  │ │    │    │   │ ││
I0310 Assembling source pass 1.─────────────────┘        │    │    │    │  │ │    │    │   │ ││
I0330 Assembling source pass 2 - final.──────────────────┘    │    │    │  │ │    │    │   │ ││
I0470 Assembling program "Pgm1". "src.asm"{2}─────────────────┤    │    │  │ │    │    │   │ ││
I0510 Assembling program pass 1. "src.asm"{2}─────────────────┘    │    │  │ │    │    │   │ ││
I0510 Assembling program pass 2. "src.asm"{2}──────────────────────┘    │  │ │    │    │   │ ││
I0530 Assembling program pass 3 - final. "src.asm"{2}───────────────────┘  │ │    │    │   │ ││
I0660 32bit FLAT PE file "Pgm1.exe" created, size=14320. "src.asm"{5}──────┤ │    │    │   │ ││
I0650 Program "Pgm1" assembled in 3 passes with errorlevel 0. "src.asm"{5}─┘ │    │    │   │ ││
I0470 Assembling program "Pgm2". "src.asm"{7}────────────────────────────────┤    │    │   │ ││
I0510 Assembling program pass 1. "src.asm"{7}────────────────────────────────┘    │    │   │ ││
I0510 Assembling program pass 2. "src.asm"{7}─────────────────────────────────────┘    │   │ ││
I0530 Assembling program pass 3 - final. "src.asm"{7}──────────────────────────────────┘   │ ││
I0660 32bit FLAT PE file "Pgm2.exe" created, size=14320. "src.asm"{10}─────────────────────┤ ││
I0650 Program "Pgm2" assembled in 3 passes with errorlevel 0. "src.asm"{10}────────────────┘ ││
I0750 Source "src" (10 lines) assembled in 2 passes with errorlevel 0.───────────────────────┤│
I0860 Listing file "src.asm.lst" created, size=1736.─────────────────────────────────────────┘│
I0990 EuroAssembler terminated with errorlevel 0.─────────────────────────────────────────────┘

Proč bychom měli balit moduly spolu s jejich dokumentací do jednoho velkého zdrojového souboru, místo abychom je roztrousili do balíku menších souborů? Je to otázka individuálních preferencí.

Jedním z důvodů může být přenos informací mezi moduly preprocesními %proměnnými. Na rozdíl od běžných symbolů není viditelnost %proměnných omezována hranicemi bloků PROGRAM..ENDPROGRAM. Předpokládejme, že v programu Pgm2 potřebujeme znát velikost datového segmentu programu Pgm1. Jeho velikost můžeme načíst do %proměnné povelem %Pgm1DataSize %SETA SIZE# [DATA] umístěným v Pgm1 hned nad jeho ENDPROGRAM Pgm1. V posledním průchodu Pgm1 již je velikost segmentu spolehlivě určena a %proměnná %Pgm1DataSize bude viditelná v celém zdroji pod svou definicí, takže s ní Pgm2 může počítat.

Dalším příkladem užitečnosti seskupování programů je, pokud jsou si navzájem podobné nebo sdílejí společná data deklarovaná preprocesními %proměnnými. Následující příklad generuje ve smyčce tři podobné krátké programy RstLPT1.com, RstLPT2.com, RstLPT3.com:

Nr %FOR 1,2,3     ; Zopakuj blok %FOR..%ENDFOR třikrát.
 RstLPT%Nr PROGRAM FORMAT=COM ; Program k resetu portu tiskárny.
   MOV DX,%Nr     ; Pořadové číslo LPT portu (1,2,3).
   MOV AH,1       ; Funkce BIOSu INITIALIZE LPT PORT.
   INT 17h        ; Použij funkci BIOSu k resetu tiskárny.
   MOV DX,Message ; Vlož adresu řetězce do DS:DX.
   MOV AH,9       ; Funkce DOSu WRITE STRING TO STDOUT.
   INT 21h        ; Použij funkci DOSu k ohlášení výsledku.
   RET            ; Ukonči program
   Message:DB "LPT%Nr was reset.$"
 ENDPROGRAM RstLPT%Nr
%ENDFOR Nr        ; Generuj 3 klony programu.

↑ Vnořené programy

Programové moduly mohou být vnořeny jeden do druhého. Například při překladu obojživelného programu spustitelného v DOSu i ve Windows můžeme chtít zohlednit fakt, že DOSovský spustitelný soubor MZ je vestavěn jako stub do spustitelného PE programu pro Windows a poskytuje stejnou funkčnost.
Viz vzorový projekt LockTest jako příklad duálního DOS&Windows programu.

Opět, pokud vnější program vidí vnitřní programový blok v neposledním průchodu, bude přeskočen. Až v posledním průchodu vnějšího bloku bude tento dočasně suspendován, vnitřní program kompletně přeložen a uložen, a pak se teprve vnější program vrátí k dokončení posledního průchodu.

┌─────────┬──────────────────────────────────┐ █                   assembly progress ──────────────>
│envelope │src: PROGRAM                      │  █       ┌█
├─────────┼──────────────────────────────────┤   █      │ █
│      {1}│      EUROASM ; Common options.   │    █     │  █
│      {2}│Pgm1: PROGRAM FORMAT=PE,ENTRY=Run:│     █┐   │   █─█       ┌█       ┌█
│      {3}│Run:   ; Pgm1 data + code.        │      │   │      █      │ █      │ █
│      {4}│ Pgm2: PROGRAM FORMAT=COFF        │      │   │       █┐    │  █┐    │  █─█  ┌█
│"src.asm"│        ; Pgm2 data + code.       │      │   │        │    │   │    │     █ │ █
│      {6}│       ENDPROGRAM Pgm2:           │      │   │        └█   │   └█   │      █┘  █─█
│      {7}│       ; Pgm1 more code.          │      │   │          █  │     █  │             █
│      {8}│       LINK "Pgm2.obj"            │      │   │           █ │      █ │              █
│      {9}│      ENDPROGRAM Pgm1:            │      └█  │            █┘       █┘               █─█
├─────────┼──────────────────────────────────┤        █ │                                         █
│envelope │ ENDPROGRAM src:                  │         █┘                                          █─┐
└─────────┴──────────────────────────────────┘
                                               ││        │    │        │        │   │   │ │    │   │ │
I0010 EuroAssembler started. ──────────────────┤│        │    │        │        │   │   │ │    │   │ │
I0180 Assembling source file "src.asm".────────┤│        │    │        │        │   │   │ │    │   │ │
I0270 Assembling source "src".─────────────────┘│        │    │        │        │   │   │ │    │   │ │
I0310 Assembling source pass 1.─────────────────┘        │    │        │        │   │   │ │    │   │ │
I0330 Assembling source pass 2 - final.──────────────────┘    │        │        │   │   │ │    │   │ │
I0470 Assembling program "Pgm1". "src.asm"{2}─────────────────┤        │        │   │   │ │    │   │ │
I0510 Assembling program pass 1. "src.asm"{2}─────────────────┘        │        │   │   │ │    │   │ │
I0510 Assembling program pass 2. "src.asm"{2}──────────────────────────┘        │   │   │ │    │   │ │
I0530 Assembling program pass 3 - final. "src.asm"{2}───────────────────────────┘   │   │ │    │   │ │
I0470 Assembling program "Pgm2". "src.asm"{4}───────────────────────────────────────┤   │ │    │   │ │
I0510 Assembling program pass 1. "src.asm"{4}───────────────────────────────────────┘   │ │    │   │ │
I0530 Assembling program pass 2 - final. "src.asm"{4}───────────────────────────────────┘ │    │   │ │
I0660 32bit FLAT COFF file "Pgm2.obj" created, size=78. "src.asm"{6}──────────────────────┤    │   │ │
I0650 Program "Pgm2" assembled in 2 passes with errorlevel 0. "src.asm"{6}────────────────┘    │   │ │
I0560 Linking COFF module ".\Pgm2.obj". "src.asm"{9}───────────────────────────────────────────┤   │ │
I0660 32bit FLAT PE file "Pgm1.exe" created, size=14320. "src.asm"{9}──────────────────────────┤   │ │
I0650 Program "Pgm1" assembled in 3 passes with errorlevel 0. "src.asm"{9}─────────────────────┘   │ │
I0750 Source "src" (9 lines) assembled in 2 passes with errorlevel 0.──────────────────────────────┤ │
I0860 Listing file "src.asm.lst" created, size=1237.───────────────────────────────────────────────┘ │
I0990 EuroAssembler terminated with errorlevel 0.────────────────────────────────────────────────────┘

↑ Hledání chyb v asembleru

Několik užitečných vlastností EuroAssembleru pomůže programátorovi s kontrolou, zda se jeho zdrojový kód přeložil tak, jak bylo zamýšleno.

Toto hledání chyb v asm-time pomáhá nalézt nedorozumění a chyby v EuroAssembleru samotném, nikoli v překládaném programu.

Nejvíce pomůže sloupec pro dump přeloženého kódu v listingu. Opakované úseky považované za bezchybné jsou ze zobrazování vynechány, ale mohou být vyžádány direktivami EUROASM LISTINCLUDE=ON, LISTVAR=ON, LISTMACRO=ON, LISTREPEAT=ON.

Rozpoznávání polí v instrukcích lze objednat pomocí volby EUROASM DISPLAYSTM=ON, která přidává komentářové řádky identifikující každé pole. Jelikož to významně nafukuje listing, je lepší omezit DISPLAYSTM pouze na podezřelé řádky a pak volby zase vypnout anebo obnovit předchozí stav:

   EUROASM PUSH, DISPLAYSTM=ON ; Nejprve ulož všechny volby EUROASM pomocí PUSH.
   MyMacro Operand1, Operand2  ; "MyMacro" zatím nebylo deklarováno jako makro, takže se považuje za návěstí (label).
D1010 **** DISPLAYSTM "MyMacro Operand1, Operand2"
D1020 label="MyMacro"
D1040 unknown operation="Operand1"
D1050 ordinal operand number=1,value="Operand2"
   EUROASM POP                 ; Obnov volby EUROASM.
D1010 **** DISPLAYSTM "EUROASM POP"
D1040 pseudo operation="EUROASM"
D1050 ordinal operand number=1,value="POP"
                              ; Pole instrukcí nejsou nadále zobrazovány.

Podrobnosti zakódování strojových instrukcí si lze vyžádat volbou EUROASM DISPLAYENC=ON, která pod strojové instrukce vkládá komentářový řádek se seznamem použitých modifikátorů.

   EUROASM PUSH, DISPLAYENC=ON ; Nejprve ulož všechny volby EUROASM pomocí PUSH.
   SHRD [RDI+64],RDX,2
D1080 Emitted size=6,DATA=QWORD,DISP=BYTE,SCALE=SMART,ADDR=ABS,IMM=BYTE.
   VMOVNTDQA XMM17,[RBP+40h]
D1080 Emitted size=7,PREFIX=EVEX,DATA=OWORD,OPER=0,DISP=BYTE,SCALE=SMART,ADDR=ABS.
   EUROASM POP         ; Obnov volby EUROASM. Detaily nadále nebudou zobrazovány.

Všechny konfigurační volby nastavitelné v pseudoinstrukcích EUROASM a PROGRAM lze získat a testovat pomocí systémových %^proměnných:

   %IF %^NOWARN[2101]
     %ERROR Neměli byste potlačovat varování W2101. Raději přesuňte nepoužité symboly do inkludovaných souborů.
   %ENDIF

Nejmocnějším nástrojem pro asm-time ladění je pseudoinstrukce %DISPLAY, která zobrazuje interní €ASM objekty v čase překladu a pomáhá tak zjistit, proč €ASM nefunguje podle očekávání.

Viz testy t2901..t2917 jako příklady.

Statické linkování ↓

Dynamické linování ↓

Linkování je v terminologii výpočetní techniky proces, kdy separátně přeložené moduly jsou spojovány, interakce mezi globálními symboly vyřešeny, kód a data zkombinovány a přeformátovány do cílového souboru. Viz dokumentaci [Linkers] pro podrobnější informace.

Na rozdíl od jných linkerů nevytváří EuroAssembler pouze spustitelné soubory, ale také relinkovatelné soubory ve formátech ELF, COFF a OMF, případně jejich knihovny LIBCOF a LIBOMF (viz Objektové konvertory a tabulky podporovaných kombinací).

Linkování přichází v EuroAssembleru ke slovu, když je pseudoinstrukce ENDPROGRAM zpracovávána v posledním průchodu.

Linkování je řízeno pseudoinstrukcí LINK následovanou jmény vstupních modulů. Přijatelné formáty vstupních souborů jsou dvojího druhu:

  1. linkovatelné formáty pro statické linkování jsou ELF, COFF, OMF, LIBCOF, LIBOMF, RSRC.
  2. importovatelné formáty pro dynamické linkování jsou DLL, LIBCOF, LIBOMF.
Formáty souborů akceptované příkazem LINK
CPU
mód
Šířka
programu
Výstupní
spustitelný
Výstupní
linkovatelný
Vstupní
linkovatelný
Vstupní
importovatelný
Real16BIN, BOOT, COM, MZOMF, LIBOMF, COFF, LIBCOFOMF, LIBOMF, COFF, LIBCOF-
Real32BIN, BOOT, COM, MZOMF, LIBOMF, COFF, LIBCOFOMF, LIBOMF, COFF, LIBCOF-
Prot32ELFX, PE, DLLELF, COFF, LIBCOF, OMF, LIBOMFELF, COFF, LIBCOF, RSRC, OMF, LIBOMFELF, COFF, LIBCOF, DLL, OMF, LIBOMF
Prot64ELFX, PE, DLLELF, COFF, LIBCOFELF, COFF, LIBCOF, RSRCELF, COFF, LIBCOF, DLL, OMF, LIBOMF

Viz také tabulky přípustných kombinací.
Všimněte si, že se formát OMF nemůže linkovat do 64bitových programů.

Formát linkovaného souboru se rozpoznává podle svého obsahu, nikoli podle souborové přípony. Každý linkovaný modul se nejprve načte a převede do interního formátu (PGM) před vlastním linkováním.

Není důležité, kde v bloku PROGRAM..ENDPROGRAM jsou pseudoinstrukce LINK umístěny; ony pouze sbírají jména linkovaných modulů a jejich linkování je odloženo na konec programu.

↑ Statické linkování

Kód a data linkovaných objektových souborů ve formátech ELF, COFF nebo OMF budou zkombinovány a přidány ke kódu a datům hlavního programu (tj. do toho, ke kterému je linkováno). Hlavní program může být také prázdný. Linker zároveň vyřeší vzájemné odkazy mezi PUBLIC a EXTERN symboly všech linkovaných modulů.

Na rozdíl od jiných linkerů neočekává EuroAssembler jména linkovaných modulů jako argumenty příkazového řádku. I když chceme využít EuroAssembler jen jako pouhý linker, musíme vytvořit linkovací skript, což je v podstatě €ASM zdrojový program. Požadovaný výstupní formát a šířka bude specifikován jako argument pseudoinstrukce PROGRAM:

MyExeFile PROGRAM FORMAT=PE, WIDTH=32, ListMap=Yes, ListGlobals=Yes
              LINK MyCoff.obj, PascalOmf.obj, Win32.lib
          ENDPROGRAM MyExeFile

Uložení tohoto skriptu jako MyScript.asm a vykonání euroasm MyScript.asm vyprodukuje program pro Windows MyExeFile.exe a listing MyScript.asm.lst s mapou linkovaných sekcí a globálních symbolů.

Vedle samostatných objektových modulů (ELF, OMF, COFF) mohou být kód a data linkovány také z objektových knihoven ve formátech LIBCOF a LIBOMF.

Je-li hlavní výstupní program spustitelný, €ASM linkuje pouze ty moduly z knihovny, které jsou aspoň jednou zmíněny jinými moduly (tzv. chytré linkování). Pomáhá to udržovat malou velikost linkovaného souboru vyloučením mrtvého kódu.

Pokud bychom přesto potřebovali zkombinovat neodkazované knihovní procedury do našeho spustitelného programu, museli bychom explicitně deklarovat jejich nereferencovaná jména v hlavním programu jako GLOBAL.

Chytré linkování se neuplatňuje při vytváření linkovatelného výstupního formátu, například pokud tvoříme knihovnu LIBCOF z jiných knihoven a samostatných objektových modulů. V tom případě všechny (referencované i nereferencované) moduly budou do výstupního souboru přilinkovány.

Dobrým důvodem, proč rozdělovat velký projekt na menší, separátně překládané moduly, je rychlejší sestavení.

Jakmile projekt roste a velikost jeho zdrojového kódu se zdvojnásobí, počet symbolů v něm se pravděpodobně také zdvojnásobí. Každý symbol musí být porovnán s polem jiných již definovaných symbolů kvůli vyloučení duplicit, počet porovnávání se tedy zečtyřnásobí. Počet kontrol, a tedy spotřebovaný čas roste téměř kvadraticky s velikostí zdroje.

Během vývoje jsme zpravidla soustředěni na jednu část (modul) projektu, takže ostatní nezměněné moduly se nemusejí rekompilovat během každého vývojového cyklu. Viz také Makefile manažer).

Rekapitulace: Chcete-li staticky linkovat vlastní funkci (proceduru), deklarujte ji jako PUBLIC function (nebo zakončete její jméno při definici dvěma dvojtečkami function:: PROC) a přeložte funkci do objektového nebo knihovního formátu.
Pak přeložte hlavní program, kde byla linkovaná funkce deklarována jako EXTERN function (anebo její jméno zakončeno dvěma dvojtečkami) a přidejte do programu pseudoinstrukci LINK module.obj. V hlavním programu pak lze CALL function:: jako by byla přeložena v jeho vlastním těle.
Totéž lze aplikovat na funkce z knihoven třetí strany. Je ovšem třeba respektovat její zveřejněné jméno, volací konvenci, počet, pořadí a typy argumentů.

↑ Dynamické linkování

Tato verze EuroAssembleru nepodporuje dynamické linkování Linuxových dynamických knihoven (DSO). Povel LINK DSO.so se pokusí přilinkovat soubor pouze staticky. Tato kapitola se zabývá pouze dynamickými knihovnami MS-Windows.

Kód a data dynamicky linkovaných funkcí není kopírován do cílového spustitelného souboru (image), zůstávají v dynamické knihovněě (DLL), která musí být dostupná na počítači, kde program běží. Jakmile náš program zavolá funkci z DLL, ve skutečnosti vykonává zástupný kód (thunk) reprezentovaný voláním instrukce proxy-skoku (stub).
€ASM generuje stuby ve speciální importové sekci [.idata] ve formě nepřímého absolutního blízkého skoku (JMPN). Každý takový skok je 7 bajtů dlouhý (0xFF2425[00000000]) a používá ukazatel do Import Address Table (IAT) jako svůj nepřímý 32bitový cíl. Virtuální adresa ukazatele [00000000] je vyřešena linkerem, ale vlastní 32 nebo 64bitová virtuální adresa knihovní funkce (ukazované vyřešeným dvojslovem) bude upravena později, zaváděčem v čase bind-time, kdy naše aplikace startuje.

Zaváděč implementovaný v jádře Windows, potřebuje dvě informace ke spojení knihovní funkce a k úpravě její adresy v IAT:

1) Jméno dynamicky linkovaného symbolu (jméno funkce) nebo její pořadové číslo v tabulce exportovaných symbolů

Volání podle těchto čísel (ordinal numbers) není v €ASM podporováno.

2) Název knihovny exportující daný symbol (bez cesty).

Cesta k souboru knihovny bude stanovena zaváděčem. Pořadí, v jakém Windows prohledává cesty ke knihovně, je vysvětleno ve [WinDllSearchOrder].

Program, který chce volat symbol (importovanou funkci) z DLL, by měl deklarovat symbol pomocí IMPORT. Může být deklarován také jako GLOBAL, buď explicitně nebo implicitně ( CALL ImportedSymbol::), avšak €ASM považuje takový globální symbol za EXTERN (staticky linkovaný) a nikoli IMPORT (dynamicky linkovaný) a postěžuje si, že nebyl nalezen odpovídající PUBLIC symbol.
Je několik metod, jako říci EuroAssembleru, že symbol má být linkován dynamicky:

Rekapitulace: Chcete-li dynamicky linkovat svou vlastní funkci (proceduru) do jiného programu, deklarujte ji jako EXPORT function a přeložte funkci do formátu DLL (mylib PROGRAM FORMAT=DLL). Nezapomeňte distrubuovat mylib.dll spolu s vašimi programy.
Pak přeložte hlavní spustitelný program a v něm deklarujte linkovanou funkci pomocí IMPORT function, LIB=mylib.dll. Hlavní program ji pak může volat pomocí CALL function.
Častěji asi budete potřebovat volat funkce z dynamické knihovny třetí strany, což je případ MS-Windows API. Mohli byste explicitně vyjmenovat každou funkci WinAPI pseudoinstrukcemi jako IMPORT function1,function2,LIB=user32.dll, ale pohodlnější řešení je použít importovou knihovnu, která deklaruje všechna jména funkcí touto dynamickou knihovnou exportovaných. Pak nebude potřeba přidávat novou importní deklaraci pokaždé, jakmile bude během vývoje vašeho programu přidána nová funkce z WinAPI. Prostě volejte novou funkci s dvojitou dvojtečkou (CALL NováFunkce::) a pokud se jmého NováFunkce objeví v importní knihovně, funkce bude importována. Můžete rovněž chtít používat makra WinAPI (32bit) nebo WinABI (64bit) která se postarají o deklarace IMPORT a o automatický výběr mezi variantami ANSI a WIDE.

↑ Knihovník

EuroAssembler umí vytvářet knihovny z předem přeložených objektových modulů (souborů ve formátu ELF, OMF nebo COFF). A pokud knihovní program také obsahuje nějaký kód, bude přilinkován do knihovny jako její první člen.

Library PROGRAM FORMAT=LIBOMF  ; nebo FORMAT=LIBCOF
ObjModule1:: PROC ; Jeden z objektových modulů může být také definován zde.
                  ; Zdojový kód modulu ObjModule1.
             ENDP ObjModule1::
             LINK "ObjModule2.obj", "ObjModule3.obj" ; Další moduly ELF, OMF nebo COFF.
        ENDPROGRAM Library

Pokud linkované moduly obsahují importní informace, budou také zkopírovány do výstupní knihovny. Čistě importní knihovny obsahují pouze importní deklarace. Tyto mohou být explicitně specifikovány jako IMPORT, nebo načteny z existující dynamické knihovny DLL, nebo linkovány z jiných importních knihoven. Následující příklad využívá postupně všechny tři metody:

ImpLibrary PROGRAM FORMAT=LIBOMF ; nebo FORMAT=LIBCOF
             IMPORT Symbol1, Symbol2, LIB="DynamicLibrary1.dll" ; Explicitní deklarace.
             LINK "C:\MyDLLs\DynamicLibrary2.dll"               ; Automatická detekce exportů z DLL.
             LINK "OtherImportLibrary.lib"                      ; Reimport z jiné knihovny.
           ENDPROGRAM ImpLibrary

Příklady knihoven vytvořených ze tří separátně přeložených modulů jsou v €ASM testech:
t8552 (objektová knihovna LIBOMF pro 16bitový Dos),
t9113 (objektová knihovna LIBCOF pro 32bitová Windows),
t9164 (objektová knihovna LIBCOF pro 64bitová Windows),
t8675 (importní knihovna LIBOMF pro Windows),
t9225 (importní knihovna LIBCOF pro Windows),

↑ Objektový konvertor

Poptávka po objektovém konvertoru bude asi slabá, neboť EuroAssembler může přímo linkovat všechny hlavní objektové formáty OMF, ELF a COFF. Příklady:

OMFobject PROGRAM FORMAT=OMF ; Konvertuj objekt COFF na objekt OMF.
            LINK "COFFobject.obj"
          ENDPROGRAM OMFobject
COFFobject PROGRAM FORMAT=COFF; Konvertuj objekt OMF na objekt COFF.
             LINK "OMFobject.obj"
           ENDPROGRAM COFFobject
ELFobject PROGRAM FORMAT=ELF; Konvertuj objekt COFF na objekt ELF.
             LINK "COFFobject.obj"
           ENDPROGRAM ELFobject
COFFobject PROGRAM FORMAT=COFF; Konvertuj objekt ELF na objekt COFF.
             LINK "ELFobject.o"
           ENDPROGRAM COFFobject
OMFlibrary PROGRAM FORMAT=LIBOMF ; Konvertuj knihovnu LIBCOF na knihovnu LIBOMF.
             LINK "COFFlibrary.lib"
           ENDPROGRAM OMFlibrary
COFFlibrary PROGRAM FORMAT=LIBCOF ; Konvertuj knihovnu LIBOMF na knihovnu LIBCOF.
              LINK "OMFlibrary.lib"
            ENDPROGRAM COFFlibrary

↑ Makefile manažer

Atributový operátor FILETIME# načítá čas poslední modifikace souboru, což se dá využít k detekci, zda cílový soubor potřebuje přeložit nebo ne. Stačí porovnat čas cílového souboru s časem všech zdrojových souborů, na kterých cíl záleží. Pokud cílový soubor dosud neexistoval, jeho FILETIME# vrací 0, což je totéž, jako by byl velmi starý, takže jeho vytvoření bude i tak vyžadováno.

       ; Rekompiluj "source.asm" pouze poku "target.exe" neexistuje nebo je starší než jeho zdrojové soubory.
    %IF FILETIME# "target.exe" > FILETIME# "source.asm" && FILETIME# "target.exe" > FILETIME# "included2source.inc"
       %ERROR "target.exe" je čerstvý, není třeba ho znovu překládat.
    %ELSE
       target PROGRAM FORMAT=PE
               INCLUDE "source.asm"
              ENDPROGRAM target
    %ENDIF

Jako příklad sofistikovanějšího makefile viz hlavní zdrojový soubor EuroAssembleru euroasm.htm.


↑ Optimalizace

Počítačové programy často píšeme v asembleru proto, aby byly rychlé a malé. To ale nejsou jediná kritéria, jak se dá program optimalizovat:

Optimalizace na velikost programu ↓

Optimalizace na rychlost programu ↓

Optimalizace na rychlost překladu ↓

Optimalizace na zapisovatelnost programu ↓

Optimalizace na čitelnost programu ↓

Viz také optimalizační tutoriály.

Podívejme se, jak může EuroAssembler pomoci s optimalizací.

↑ Optimalizace na velikost programu

Ve výchozím stavu vybírá €ASM nejkratší možné zakódování strojových instrukcí. Na druhé straně ale respektuje mnemoniku zvolenou programátorem, což nemusí být vždy ta nejkratší varianta. Za zapamatování stojí několik pravidel:

|0000:B80000 | MOV AX,0 |0003:29C0 | SUB AX,AX ; Použití SUB nebo XOR pro nulování registru je kratší. Vedlejší efekt: změní to flagy. |0005: | |0005:89D8 | MOV AX,BX |0007:93 | XCHG AX,BX ; XCHG je kratší než MOV. Vedlejší efekt: druhý registr je také změněn. |0008: | |0008: |Label: |0008:8D06[0800] | LEA AX,[Label] |000C:B8[0800] | MOV AX,Label ; Zavedení ofsetu do registru (MOV) je kratší nez zavedení jeho adresy (LEA). |000F: | |000F:5053 | PUSH AX,BX |0011:60 | PUSHAW ; PUSH/POP všech 8 registrů najednou je kratší než individuální PUSH/POP. |0012: | |0012:050100 | ADD AX,1 |0015:40 | INC AX ; Increment/decrement je kratší než add/subtract 1. |0016: | |0016: |LoopStart: |0016:49 | DEC CX |0017:75FD | JNZ LoopStart: |0019:E2FB | LOOP LoopStart: ; LOOP, JCXZ jsou kratší nez separátní test a skok.

Programy aspirující do kategorie těch nejkratších by měly mít PROGRAM FORMAT=COM a EUROASM AUTOALIGN=OFF. Mohou končit prostým RET namísto volání DOS funkce TERMINATE PROCESS, protože návratová adresa na zásobníku programů COM je inicializována na 0 a tam na začátku bloku PSP leží přerušení ukončující proces.

Hello PROGRAM FORMAT=COM
       MOV DX,=B "Hello world!$"
       MOV AH,9
       INT 21h
       RET
      ENDPROGRAM Hello

Pro další inspiraci se podívejte na [Golfing_tips],
Hugi Size Coding Competition Series,
Assembly nibbles competition,
Graphical Tetris in 1986 bytes by Sebastian Mihai,
BootChess play in 487 bytes by Oliver Poudade.

Programy pro Windows vytvořené v €ASM budou kratší, pokud bude volba PROGRAM ICONFILE= explicitně prázdná a nebude přilinkován žádný soubor resources. V tom případě nebude sekce [.rsrc] v PE souboru vůbec přítomna. Můžete také experimentovat s použitím programových voleb jako PROGRAM FILEALIGN=.

↑ Optimalizace na rychlost programu

Psaní rychlých programů je plně v rukou programátora, EuroAssembler zde příliš nepomůže, neprovádí žádnou optimalizaci za vašimi zády, jako to dělají kompilátory vyšších jazyků. Možná budete chtít nastavit EUROASM AUTOALIGN=ON, aby se všechna data zarovnala kvůli rychlému přístupu. Naprostá kontrola zakódování instrukce pomocí modifikátorů dovoluje v €ASM vybrat variantu s přesnou velikostí kódu, což může být rychlejší než verze s minimální velikostí doplněnou pomocí NOP. €ASM podporuje optimalizované instrukce NOP pro snadné ruční zarovnávání.

Existuje více triků, jak urychlit program: rozbalení smyček, paralelizace, vyvarování se zbytečných přístupů do paměti a v neposlední řadě výběr nejrychlejšího algoritmu. Výkonnost taky závisí na modelu CPU a jeho generaci. Dobrým průvodcem je manuál [SoftwareOptimisation] od Agnera Foga.

Výkonnost programu se obvykle směňuje s jeho velikostí, například mnoho triků zmenšující velikost programu uvedených nahoře vede k jeho pomalejšímu vykonávání. K optimalizaci na rychlost se hodí hlavně kritické části programu, které budou vykonávány mnohokrát.

↑ Optimalizace na rychlost překladu

EuroAssembler není optimalizován na rychlost překladu, nicméně jeho trvání obvykle není problém. Nejvíce záleží na počtu průchodů, který je řízen EuroAssemblerem samotným a programátor jej nemůže přímo ovlivňovat. Nejméně dva průchody jsou požadovány pokaždé. Jejich počet se zvyšuje, pokud program obsahuje dopředné reference, smyčky v asm-time, makroinstrukce.

Když €ASM překládá dopředný skok, nejprve předpokládá krátkou vzdálenost (DIST=SHORT) k dosud nedefinovanému cíli, a rezervuje prostor pro dvoubajtový operační kód. Pokud víme při psaní programu, že cíl bude dále než 127 bajtů, mohli bychom explicitně určit DIST=NEAR, což by mohlo ušetřit jeden průchod. Ten by ale byl uspořen jen pokud by byly specifikovány vzdálenosti všech podobných skoků, což obvykle nestojí za námahu.

Chcete-li vědět, proč €ASM potřebuje tolik průchodů, vložte direktivu %DISPLAY UnfixedSymbols před ENDPROGRAM, abyste zjistili ofsety kterých symbolů oscilují mezi průchody asembleru.

Čas sestavení velkých projektů může být významně snížen rozdělením kódu na menší, samostatně překládané moduly, které pak budou ve finále spojeny (slinkovány) dohromady. Viz například zdrojový kód euroasm.htm.

↑ Optimalizace na zapisovatelnost programu

EuroAssembler zavádí nové pohodlné rysy ne příliš obvyklé mezi jinými asemblery:

↑ Optimalizace na čitelnost

Dobře okomentovaný program je snadné číst a udržovat. EuroAssembler dovoluje formátování HTML poznámek, takže zdrojový kód v něm psaných programů může být přímo publikován na webových stránkách a každá jeho část může být hned dokumentována bohatě formátovanými poznámkami, tabulkami, obrázky, hypertextovými odkazy.

Velikost a jazyk identifikátorů není omezován, takže mohou být samopopisné. Pokud není angličtina váš rodný jazyk, je dobrým nápadem preferovat symboly s neanglickými názvy, jako Drucken místo Print, файл místo file apod. Pomůže to čtenáři vašeho programu rozeznat vestavěná rezervovaná slova od identifikátorů vytvořených autorem programu.

Některé prvky jazyka EuroAssembler používají dekorátory pomáhajícími lidskému čtenáři rozlišit kategorii dekorovaných identifikátorů:

↑ Kde začít

Pokud jste dočetli tento manuál až sem a chcete vyzkoušet EuroAssembler, stáhněte jeho poslední verzi, vytiskněte si papírový tahák a prohlédněte si vzorové projekty. Mnoho štěstí!

▲Zpět na začátek▲