| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# EuroAssembler dokumentace

## English version of this manual

## Tutorial - jak programovat v asembleru

## 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 `&euro;`.

### ↑ Stručná charakteristika

- €ASM je makroasembler s Intelovskou syntaxí pro architekturu IA-32 a x64 dle AMD&Intel™.
  Rovněž funguje jako linker, knihovník, objektový konvertor, make-manažer.
- EUROASM je 32-bitová konzolová aplikace pro MS-Windows a pro Linux, která načítá zdrojový text napsaný v jazyce asembler a převádí jej na kompilovaný objektový formát nebo na spustitelný program, a vytváří rovněž listingový soubor.
- Programy napsané v €ASM mohou běžet na 16, 32 nebo 64 bitovém operačním systému.
- €ASM je distribuován spolu se svým komentovaným zdrojovým tvarem, knihovnami maker a vzorovými programy.
- €ASM je k dispozici zdarma.

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

- Jedno vyvolání EuroAssembleru může překládat více než jeden zdrojový program. Každý zdrojový soubor vytváří vlastní listing a cílový program.

  > `euroasm.exe source1.asm, source2.asm, more*.asm`

- Listingový soubor úspěšně vygenerovaný předchozím spuštěním €ASM může být znovu využit jako zdrojový soubor. Formát listingu je kompatibilní se zdrojovým textem, neboť hexadecimální kód listingu je při čtení ignorován.
- €ASM is je iterativní mnohoprůchodový makroasembler s plnou podporou dopředných referencí a částečnou podporou datových typů.

  > Návěští, symboly definované pomocí EQU, struktury, to vše může být odkazováno dříve, než bylo definováno (i když to nelze doporučit). `|0000: | ; Odkaz na strukturovanou proměnnou Today, která bude definována později. |0000:C706[1000]E007 | MOV [Today.Year],2016 ; Vlož číslo do proměnné typu WORD. |0006:C606[1200]0C | MOV [Today.Month],12 ; Vlož číslo do proměnné typu BYTE. |000B:C606[1300]1F | MOV [Today.Day],31 ; Vlož číslo do proměnné typu BYTE. |0010: | |0010:00000000 |Today DS Datum ; Definice strukturovaného symbolu, jehož struktura bude deklarována později. |0014: | |[Datum] |Datum STRUC ; Deklarace struktury Datum. |0000:.... |.Year DW WORD |0002:.. |.Month DB BYTE |0003:.. |.Day DB BYTE |0004: | ENDSTRUC Datum`

- Instrukce asembleru mohou být kombinovány s HTML. Řádky zdrojového kódu začínající `<HTML tagem>` se považují za komentáře. To umožňuje dokumentovat zdrojový kód pomocí značkovacího jazyka.
- Povely INCLUDE mohou importovat jiný zdrojový soubor buď jako celek, nebo pouze jeho oddíl, který může být specifikován jako rozsah řádků, nebo jako blok definovaný direktivami `HEAD` a `ENDHEAD`. Vložitelný oddíl programového modulu `HEAD..ENDHEAD` nemusí být udržován v samostatných hlavičkových souborech (jako např. *.h soubory v jazyku C).
- Chyby a varování se zobrazují na standardním výstupu €ASM a jsou rovněž vkládány do listingu, hned pod chybný příkaz.
- €ASM se zotavuje z chyb ve zdrojovém textu. Překlad se nezastavuje na každé zjištěné chybě (ledaže by se jednalo o chybu fatální).
- €ASM vždy generuje ten nejkratší strojový kód, avšak programátor může zvolit delší variantu pomocí instrukčních modifikátorů: `|00000000:41 | INC ECX |00000001:41 | INC ECX,CODE=SHORT |00000002:FFC1 | INC ECX,CODE=LONG |00000004: | |00000004:83D801 | SBB EAX,1 |00000007:83D801 | SBB EAX,1,IMM=BYTE |0000000A:81D801000000 | SBB EAX,1,IMM=DWORD |00000010: | |00000010:E97D000000 | JMP $+0x82, DIST=SHORT |## W2401 Modifier "DIST=SHORT" could not be obeyed in this instruction. |00000015: |`
- Data mohou být definována buď explicitně, pomocí pseudoinstrukcí D, DB, DW atd., anebo implicitně jako literál. `|[DATA] |[DATA] ; Přepnout do datové sekce. |0000:4578706C~|Explicit DB "Explicit text definition.$",0 |[CODE] |[CODE] ; Přepnout do kódové sekce. |0020:BA[0000] | MOV DX,Explicit |0023:B409 | MOV AH,9 ; Zapsat řetězec DS:DX na standardní výstup. |0025:CD21 | INT 21h ; Vyvolat funkci DOSu. |0027:BA[6400] | MOV DX,=B"Implicit text definition (literal).$" |002A:B409 | MOV AH,9 ; Zapsat řetězec DS:DX na standardní výstup. |002C:CD21 | INT 21h ; Vyvolat funkci DOSu. |002E: |`
- EuroAssembler podporuje instrukce Advanced vector extension včetně AVX-512 instrukcí zakódovaných pomocí prefixů MVEX a EVEX.
- Vedle obvyklých podprogramových bloků `PROC..ENDPROC` €ASM zavádí semiinline procedury `PROC1..ENDPROC1`, které se expandují z makra pouze jednou, během jeho první expanze.
- €ASM může linkovat objektové moduly (OMF, ELF, COFF) na spustitelné formáty (COM, EXE, DLL, ELFX) jakož i na jiné objektové moduly a knihovny. Viz seznam přípustných kombinací.
- Při používání dynamicky linkovaných funkcí můžeme specifikovat jejich knihovnu DLL už během deklarace importu, např. `IMPORT RegCloseKey, LIB="user32.dll"`. Importní knihovny nejsou linkerem €ASM vyžadovány, i když je podporuje.
- Každý zdrojový soubor může obsahovat více než jeden modul (program), každý takový blok `PROGRAM..ENDPROGRAM` generuje svůj vlastní objektový nebo spustitelný soubor. Pokud autor chce, může udržovat celý mnohamodulový projekt v jediném velkém souboru.
- Parametry příkazového řádku, nezbytné při spouštění většiny jiných asemblerů a linkerů, nejsou nutné. Při distribuci vašeho zdrojového kódu nemusíte specifikovat, jak ho přeložit. Spustitelný program se vygeneruje povelem `euroasm source.asm`.
- EuroAssembler je napsán v EuroAssembleru, jeho zdrojový tvar může být zkontrolován online.
- Následující příklad vytváří dvě varianty klasického programu Hello, world!, HelloL32.x and HelloL64.x. Oba spustitelné soubory budou vytvořeny z následujícího zdrojového souboru hello.asm jediným povelem `euroasm hello.asm`. Můžeme je pak spustit v Linuxu nebo v jeho Windows emulátoru WSL:

            EUROASM CPU=x64

    HelloL32 PROGRAM Format=ELFX, Entry=Main:, Width=32 ; HelloL32.x funguje v 32bitovém Linuxu.
     Main:    MOV EAX,4             ; Volání jádra sys_write=4.
              MOV EBX,1             ; Souborový deskriptor standardního výstupu (konzoly).
              MOV ECX,Message       ; Adresa zprávy.
              MOV EDX,SIZE# Message ; Velikost zprávy.
              INT 0x80              ; Zavolej jádro.
              MOV EAX,1             ; Operace sys_exit=1.
              XOR EBX,EBX           ; Vrať errorlevel=0.
              INT 0x80              ; Zavolej jádro.
     Message: DB "Hello, world of %^Width bits in Linux!",10
             ENDPROGRAM HelloL32

    HelloL64 PROGRAM Format=ELFX, Entry=Main:, Width=64 ; HelloL64.x funguje v 64bitovém Linuxu.
     Main:    MOV RAX,1             ; Volání jádra sys_write=1.
              MOV RDI,1             ; Souborový deskriptor standardního výstupu (konzoly).
              LEA RSI,[Message]     ; Adresa zprávy.
              MOV RDX,SIZE# Message ; Velikost zprávy.
              SYSCALL               ; Zavolej jádro.
              MOV RAX,60            ; Operace sys_exit=60.
              XOR EDI,EDI           ; Vrať errorlevel=0.
              SYSCALL               ; Zavolej jádro.
     Message: DB "Hello, world of %^Width bits in Linux!",10
             ENDPROGRAM HelloL64

Také bychom mohl skrýt většinu strojových instrukcí předchozích programů pomocí makroinstrukcí z knihoven linapi.htm (32 bit) a linabi.htm (64 bit), a použitím literálů (=B "Hello...") k definici zobrazovaných řetězců:

             EUROASM CPU=x64

    HelloL32 PROGRAM Format=ELFX, Entry=Main:, Width=32 ; HelloL32.x funguje v 32bitovém Linuxu.
              INCLUDE linapi.htm ; Definuj 32bitová makra StdOutput a TerminateProgram.
     Main:    StdOutput =B "Hello, world of %^Width bits in Linux!", Eol=Yes
              TerminateProgram Errorlevel=0
             ENDPROGRAM HelloL32

             %DROPMACRO *        ; Zapomeň makra definovaná v "linapi.htm".

    HelloL64 PROGRAM Format=ELFX, Entry=Main:, Width=64 ; HelloL64.x funguje v 64bitovém Linuxu.
              INCLUDE linabi.htm ; Definuj 64bitová makra StdOutput a TerminateProgram.
     Main:    StdOutput =B "Hello, world of %^Width bits in Linux!", Eol=Yes
              TerminateProgram Errorlevel=0
             ENDPROGRAM HelloL64

A ještě příklad programů určených pro MS-Windows:

            EUROASM CPU=x64, SIMD=Yes

    HelloW32 PROGRAM Format=PE, Entry=Main:, Width=32 ; HelloW32.exe funguje v 32bitových a 64bitových Windows.
             INCLUDE winapi.htm ; Definuj 32bitová makra WinAPI a TerminateProgram.
       Main: WinAPI MessageBox,0,="Hello, world of %^Width bits in Windows!",="Title",0, Lib=user32.dll
             TerminateProgram Errorlevel=0
            ENDPROGRAM HelloW32

            %DROPMACRO *        ; Zapomeň makra definovaná v "winapi.htm".

    HelloW64 PROGRAM Format=PE, Entry=Main:, Width=64 ; HelloW64.exe funguje v 64bitových Windows.
             INCLUDE winabi.htm ; Definuj 64bitová makra WinABI a TerminateProgram.
       Main: WinABI MessageBox,0,="Hello, world of %^Width bits in Windows!",="Title",0, Lib=user32.dll
             TerminateProgram Errorlevel=0
            ENDPROGRAM HelloW64

### ↑ 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 fyzické řá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 znovupoužitelné 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áze | Použitý nástroj
--- | ---
design-time | představivost
write-time | textový editor
assembly-time | asembler
combine-time | linker
link-time | linker
load-time | loader operačního systému
bind-time | loader operačního systému
run-time | procesor

### ↑ K čemu další asembler

Nespokojenost 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 inkluduje 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 ve Windows nebo ~/euroasm v Linuxu, přejděte do něj a rozzipujte stažený soubor euroasm.zip.

V Linuxu přesuňte nebo zkopírujte spustitelný soubor euroasm.x do některého adresáře uvedeného v proměnné environmentu `$PATH`, například příkazem `sudo mv euroasm.x /usr/local/bin/euroasm`. Při prvním spuštění pomocí `sudo euroasm` se pokusí vytvořit globální konfigurační soubor /etc/eurotool/euroasm.ini.

Ve Windows přesuňte nebo zkopírujte s právy administrátora spustitelný soubor euroasm.exe do některého adresáře uvedeného v proměnné environmentu `%PATH%`, například příkazem `copy euroasm.exe %windir%`. Při prvním spuštění pomocí `euroasm.exe` se pokusí vytvořit globální konfigurační soubor %AppData%\eurotool\euroasm.ini.

EuroAssembler by nyní měl jít spustit odkudkoli zadáním příkazu `euroasm`. Nyní byste měli upravit plain-text editorem globální konfigurační soubor.

> 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 nic anebo 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ář. Ano, soubor euroasm.exe nebo euroasm.x 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ávy | Prefix | Rozsah identifikátorů | Závažnost | Vyhledávací značka
--- | --- | --- | --- | ---
Informativní | I | I0000..I0999 | 0 | `|#`
Ladicí | D | D1000..D1999 | 1 | `|#`
Varování | W | W2000..W3999 | 2..3 | `|##`
Nepotlačitelná varování | W | W4000..W4999 | 4 | `|##`
Uživatelem definovaná chyba | U | U5000..U5999 | 5 | `|###`
Chyba | E | E6000..E8999 | 6..8 | `|###`
Fatální chyba | F | F9000..F9999 | 9 | `|###`

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í a lokální.

Globální konfigurační soubor ve Windows verzi má název %AppData%\eurotool\euroasm.ini 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).

Globální konfigurační soubor v Linux verzi má název /etc/eurotool/euroasm.ini 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:\Users\login\AppData\Roaming\eurotool\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 euroasm.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`. 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ů
Znak | Funkce
--- | ---
`|` (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átor | Popis
--- | ---
`~` | 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
`<N` | použ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 neobsahuje 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
Soubor | Význam | Umístění | Viz také
--- | --- | --- | ---
Executable | euroasm.exe | Adresář s euroasm.exe | OS PATH
Input | Globalní euroasm.ini | Viz instalační instrukce |
Output | Globalní euroasm.ini | Viz instalační instrukce |
Input | Lokální euroasm.ini | Adresář se zdrojem |
Input | Zdrojový soubor | Aktuální adresář |
Input | Vložený zdrojový soubor | Adresář vkládaných souborů | `EUROASM INCLUDEPATH=`
Output | Cílový soubor | Aktuální adresář | `PROGRAM OUTFILE=`
Output | Listingový soubor | Adresář se zdrojem | `EUROASM LISTFILE=`
Input | Linkovaný modul | Adresář linkovaných modulů | `EUROASM LINKPATH=`
Input | Linkovaný stub | Adresář linkovaných modulů | `PROGRAM STUBFILE=`
Input | Linkovaný soubor ikony | Adresář linkovaných modulů | `PROGRAM ICONFILE=`
Import | Dynamicky importovaná funkce | Závisí na OS | `IMPORT LIB=`

Aktuálním adresářem se rozumí složka přiřazená shellu v okamžiku, kdy byl 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ů se spokojí 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 tyto tři bajty ignoruje.

#### ↑ 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ů
ASCII | znak | 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..57 | 0..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..90 | A..Z | velká písmena | písmeno
91 | [ | levá hranatá závorka | závorka paměťového obsahu, operátor substringu
92 | \ | zpětné lomítko | aritmetický operátor, pokračování řádku
93 | ] | pravá hranatá závorka | zá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..122 | a..z | malá písmena | písmeno
123 | { | levá složená závorka | operátor sublistu
124 | | | roura | logický operátor, oddělovač strojové poznámky
125 | } | pravá složená závorka | operátor sublistu
126 | ~ | tilda | logický operátor, indikace zkratky
127 |  | delete | netisknutelný znak neboli bílá mezera
128..255 |  | non ASCII znaky | písmeno
ASCII | znak | 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 pole | Ukonč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éno | Skupina | Operační kód
--- | --- | ---
LOCK | 1 | 0xF0
REP | 1 | 0xF3
REPE | 1 | 0xF3
REPZ | 1 | 0xF3
REPNE | 1 | 0xF2
REPNZ | 1 | 0xF2
XACQUIRE | 1 | 0xF2
XRELEASE | 1 | 0xF3
SEGCS | 2 | 0x2E
SEGSS | 2 | 0x36
SEGDS | 2 | 0x3E
SEGES | 2 | 0x26
SEGFS | 2 | 0x64
SEGGS | 2 | 0x65
SELDOM | 2 | 0x2E
OFTEN | 2 | 0x3E
OTOGGLE | 3 | 0x66
ATOGGLE | 4 | 0x67

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í:

- strojové instrukce, jejichž mnemonické názvy jsou definovány výrobcem CPU, jsou nezávislé na velikosti písmen,
- pseudoinstrukce jsou definovány syntaxí asembleru a jsou rovněž nezávislé na velikosti písmen,
- makroinstrukce jsou napsány uživatelem €ASM a jsou citlivé na velikost písmen.

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:

- prefixy,
- strojové instrukce,
- pseudoinstrukce D a její klony (DB, DW, DD atd),
- pseudoinstrukce ALIGN.

#### ↑ 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ávaznost | Co představuje | Co deklaruje | Počátek-bloku | Přerušení-bloku | Konec-bloku
povinné | název programu | program | PROGRAM | nepoužívá se | ENDPROGRAM
povinné | název procedury | symbol | PROC | nepoužívá se | ENDPROC
povinné | název procedury | symbol | PROC1 | nepoužívá se | ENDPROC1
povinné | název struktury | strukturu | STRUC | nepoužívá se | ENDSTRUC
volitelné | identifikátor bloku | nic | HEAD | nepoužívá se | ENDHEAD
volitelné | identifikátor bloku | nic | %COMMENT | nepoužívá se | %ENDCOMMENT
volitelné | identifikátor bloku | nic | %IF | %ELSE | %ENDIF
volitelné | identifikátor bloku | nic | %WHILE | %EXITWHILE | %ENDWHILE
volitelné | přehozené identifikátory | nic | %REPEAT | %EXITREPEAT | %ENDREPEAT
povinné | formální %proměnná | %variable | %FOR | %EXITFOR | %ENDFOR
povinné | název makra | makro | %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átorů, 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 omezeni 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
Notace | Předpona | Báze | Přípona | Násobitel
--- | --- | --- | --- | ---
Binární | 0Y | 2 | B | 1
Oktalová | 0O | 8 | Q | 1
Dekadická | 0N | 10 | D | 1
K | 210
M | 220
G | 230
T | 240
P | 250
Hexadecimální | 0X | 16 | H | 1

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 pole | Obsah
--- | --- | ---
1 | znaménko čísla | `+`, `-` nebo žádné
2 | celočíselná část | číslice `0..9`, separátor `_`
3 | desetinná tečka | `.`
4 | neceločíselná část | číslice `0..9`, separátor `_`
5 | číselný modifikátor | `E` nebo `e`
6 | znaménko exponentu | `+`, `-` nebo žádné
7 | exponentová část | číslice`0..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)
Konstanta | Interpretace | single precision (DD) | double precision (DQ) | extended precision (DT)
--- | --- | --- | --- | ---
#ZERO | zero | `00000000` | `00000000_00000000` | `0000_00000000_00000000`
+#ZERO | positive zero | `00000000` | `00000000_00000000` | `0000_00000000_00000000`
-#ZERO | negative zero | `80000000` | `80000000_00000000` | `8000_00000000_00000000`
#INF | infinity | `7F800000` | `7FF00000_00000000` | `7FFF_80000000_00000000`
+#INF | positive infinity | `7F800000` | `7FF00000_00000000` | `7FFF_80000000_00000000`
-#INF | negative infinity | `FF800000` | `FFF00000_00000000` | `FFFF_80000000_00000000`
#PINF | pseudo infinity | `7F800000` | `7FF00000_00000000` | `7FFF_00000000_00000000`
+#PINF | positive pseudo infinity | `7F800000` | `7FF00000_00000000` | `7FFF_00000000_00000000`
-#PINF | negative pseudo infinity | `FF800000` | `FFF00000_00000000` | `FFFF_00000000_00000000`
#NAN | not a number | `7FC00000` | `7FF80000_00000000` | `7FFF_C0000000_00000000`
+#NAN | positive not a number | `7FC00000` | `7FF80000_00000000` | `7FFF_C0000000_00000000`
-#NAN | negative not a number | `FFC00000` | `FFF80000_00000000` | `FFFF_C0000000_00000000`
#PNAN | pseudo not a number | `7F800001` | `7FF00000_00000001` | `7FFF_00000000_00000001`
+#PNAN | positive pseudo not a number | `7F800001` | `7FF00000_00000001` | `7FFF_00000000_00000001`
-#PNAN | negative pseudo not a number | `FF800001` | `FFF00000_00000001` | `FFFF_00000000_00000001`
#QNAN | quiet not a number | `7FC00000` | `7FF80000_00000000` | `7FFF_C0000000_00000000`
+#QNAN | positive quiet not a number | `7FC00000` | `7FF80000_00000000` | `7FFF_C0000000_00000000`
-#QNAN | negative quiet not a number | `FFC00000` | `FFF80000_00000000` | `FFFF_C0000000_00000000`
#SNAN | signaling not a number | `7F800001` | `7FF00000_00000001` | `7FFF_80000000_00000001`
+#SNAN | positive signaling not a number | `7F800001` | `7FF00000_00000001` | `7FFF_80000000_00000001`
-#SNAN | negative signaling not a number | `FF800001` | `FFF00000_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ůže být zapsáno také jako znaková konstanta, což 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í

- číselnou hodnotu 0 jako logickou hodnotu nepravda a nenulovou hodnotu jako pravda,
- řetězec je vyhodnocen jako nepravda pokud je prázdný, jinak jako pravda (řetězec netisknutelných znaků není prázdný),
- předvolené konstanty TRUE, YES, ON, ENABLE, ENABLED jako pravda, a FALSE, NO, OFF, DISABLE, DISABLED jako nepravda (bez ohledu na velikost písmen).

To se týká

- podmínek v pseudoinstrukcích %IF, %WHILE, %UNTIL,
- pseudoinstrukce %SETB,
- logických modifikátorů strojových instrukcí BCST=, EH=, SAE=, ZEROING=,
- booleovských operandů pseudoinstrukce EUROASM AUTOALIGN=, AUTOSEGMENT=, DEBUG=, DISPLAYENC=, DISPLAYSTM=, DUMP=, DUMPALL=, LIST=, LISTINCLUDE=, LISTMACRO=, LISTREPEAT=, LISTVAR=, PROFILE=, UNICODE=, a všech extenzí CPU,
- booleovských operandů pseudoinstrukce PROGRAM LISTGLOBALS=, LISTLITERALS=, LISTMAP=,
- booleovského operandu NESTINCHECK= pseudoinstrukcí PROC a PROC1.

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ód | GPR | I/O port | Adresní prostor
--- | --- | --- | ---
16bit | 8* 2 B | 64 KB (216) | 1 MB (216+4)
32bit | 8* 4 B | 64 KB (216) | 4 GB (232)
64bit | 16* 8 B | 64 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ů
Rodina | REGTYPE# | Č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, R15W | 2
GPR 32bit | 'D' | EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D | 4
GPR 64bit | 'Q' | RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15 | 8
Segment | 'S' | CS, SS, DS, ES, FS, GS | 2
FPU | 'F' | ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7 | 10
MMX | 'M' | MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7 | 8
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, XMM31 | 16
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, YMM31 | 32
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, ZMM31 | 64
Mask | 'K' | K0, K1, K2. K3, K4, K5, K6, K7 | 8
Bound | 'N' | BND0, BND1, BND2, BND3 | 16
Control | 'C' | CR0, CR2, CR3, CR4, CR8 | 4
Debug | 'E' | DR0, DR1, DR2, DR3, DR6, DR7 | 4
Test | 'T' | TR3, TR4, TR5 | 4

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 | Mnemonika | Alias | Popis | Podmínka | Invertovaná mnemonika
--- | --- | --- | --- | --- | ---
0x4 | E | Z | Equal | ZF=1 | NE
0x5 | NE | NZ | Not Equal | ZF=0 | E
0x4 | Z | E | Zero | ZF=1 | NZ
0x5 | NZ | NE | Not Zero | ZF=0 | Z
0x2 | C | B | Carry | CF=1 | NC
0x3 | NC | NB | Not Carry | CF=0 | C
0x2 | B | C | Borrow | CF=1 | NB
0x3 | NB | NC | Not Borrow | CF=0 | B
0x0 | O |  | Overflow | OF=1 | NO
0x1 | NO |  | Not Overflow | OF=0 | O
0x8 | S |  | Sign | SF=1 | NS
0x9 | NS |  | Not Sign | SF=0 | S
0xA | P | PE | Parity | PF=1 | NP
0xB | NP | PO | Not Parity | PF=0 | P
0xA | PE | P | Parity Even | PF=1 | PO
0xB | PO | NP | Parity Odd | PF=0 | PE
0x7 | A | NBE | Above | CF=0 && ZF=0 | NA
0x6 | NA | BE | Not Above | CF=1 || ZF=1 | A
0x3 | AE | NB | Above or Equal | CF=0 | NAE
0x2 | NAE | B | Not Above nor Equal | CF=1 | AE
0x2 | B | NAE | Below | CF=1 | NB
0x3 | NB | AE | Not Below | CF=0 | B
0x6 | BE | NA | Below or Equal | CF=1 || ZF=1 | NBE
0x7 | NBE | A | Not Below nor Equal | CF=0 && ZF=0 | BE
0xF | G | NLE | Greater | SF=OF && ZF=0 | NG
0xE | NG | LE | Not Greater | SF<>OF || ZF=1 | G
0xD | GE | NL | Greater or Equal | SF=OF | NGE
0xC | NGE | L | Not Greater nor Equal | SF<>OF | GE
0xC | L | NGE | Less | SF<>OF | NL
0xD | NL | GE | Not Less | SF=OF | L
0xE | LE | NG | Less or Equal | SF<>OF || ZF=1 | NLE
0xF | NLE | 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 | Mnemonika | Alias | Popis
--- | --- | --- | ---
0x00 | EQ_OQ | EQ | Equal, Ordered, Quiet
0x01 | LT_OS | LT | Less Than, Ordered, Signaling
0x02 | LE_OS | LE | Less than or Equal, Ordered, Signaling
0x03 | UNORD_Q | UNORD | Unordered, Quiet
0x04 | NEQ_UQ | NEQ | Not Equal, Unordered, Quiet
0x05 | NLT_US | NLT | Not Less Than, Unordered, Signaling
0x06 | NLE_US | NLE | Not Less than or Equal,Unordered, Signaling
0x07 | ORD_Q | ORD | Ordered, Quiet
0x08 | EQ_UQ |  | Equal, Unordered, Quiet
0x09 | NGE_US | NGE | Not Greater than or Equal, Unordered, Signaling
0x0A | NGT_US | NGT | Not Greater Than, Unordered, Signaling
0x0B | FALSE_OQ | FALSE | False, Ordered, Quiet
0x0C | NEQ_OQ |  | Not Equal, Ordered, Quiet
0x0D | GE_OS | GE | Greater than or Equal, Ordered, Signaling
0x0E | GT_OS | GT | Greater Than, Ordered, Signaling
0x0F | TRUE_UQ | TRUE | True, Unordered, Quiet
0x10 | EQ_OS |  | Equal, Ordered, Signaling
0x11 | LT_OQ |  | Less Than, Ordered, Quiet
0x12 | LE_OQ |  | Less than or Equal, Ordered, Quiet
0x13 | UNORD_S |  | Unordered, Signaling
0x14 | NEQ_US |  | Not Equal, Unordered, Signaling
0x15 | NLT_UQ |  | Not Less Than, Unordered, Quiet
0x16 | NLE_UQ |  | Not Less than or Equal, Unordered, Quiet
0x17 | ORD_S |  | Ordered, Signaling
0x18 | EQ_US |  | Equal, Unordered, Signaling
0x19 | NGE_UQ |  | Not Greater than or Equal, Unordered, Quiet
0x1A | NGT_UQ |  | Not Greater Than, Unordered, Quiet
0x1B | FALSE_OS |  | False, Ordered, Signaling
0x1C | NEQ_OS |  | Not Equal, Ordered, Signaling
0x1D | GE_OQ |  | Greater than or Equal, Ordered, Quiet
0x1E | GT_OQ |  | Greater Than, Ordered, Quiet
0x1F | TRUE_US |  | True, 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 | Priorita | Vlastnosti | Levý operand | Operátor | Pravý operand | Výsledek | II (6)
--- | --- | --- | --- | --- | --- | --- | ---
Membership | 16 | binární nekomut. (1) | identifier | `.` | identifier | identifikátor |
Attribute | 15 | unární noncomm. (3) |  | `attr#` | element | číslo nebo adresa |
Case-insens. Equal | 14 | binární komutativní (2) | string | `==` | string | logický | CMPS
Case-sens. Equal | 14 | binární komutativní | string | `===` | string | logický | CMPS
Case-insens. Nonequal | 14 | binární komutativní (2) | string | `!==` | string | logický | CMPS
Case-sens. Nonequal | 14 | binární komutativní | string | `!===` | string | logický | CMPS
Plus | 13 | unární (3) |  | `+` | number | číselný | NOP
Minus | 13 | unární (3) |  | `-` | number | číselný | NEG
Shift Logical Left | 12 | binární nekomutativní | number | `<<` | number | číselný | SHL
Shift Arithmetic Left | 12 | binární nekomutativní | number | `#<<` | number | číselný | SAL
Shift Logical Right | 12 | binární nekomutativní | number | `>>` | number | číselný | SHR
Shift Arithmetic Right | 12 | binární nekomutativní | number | `#>>` | number | číselný | SAR
Signed Division | 11 | binární nekomutativní | number | `#/` | number | číselný | IDIV
Division | 11 | binární nekomutativní | number | `/` | number | číselný | DIV
Signed Modulo | 11 | binární nekomutativní | number | `#\` | number | číselný | IDIV
Modulo | 11 | binární nekomutativní | number | `\` | number | číselný | DIV
Signed Multiplication | 11 | binární komutativní | number | `#*` | number | číselný | IMUL
Multiplication | 11 | binární komutativní | number | `*` | number | číselný | MUL
Scaling | 10 | binární komutativní (5) | number | `*` | register | adresní výraz |
Addition | 9 | binární komutativní | number | `+` | number | číselný | ADD
Subtraction | 9 | binární nekomutativní | number | `-` | number | číselný | SUB
Indexing | 9 | binární komutativní (5) | number | `+` | register | adresní výraz |
Bitwise NOT | 8 | unární (3) |  | `~` | number | číselný | NOT
Bitwise AND | 7 | binární komutativní | number | `&` | number | číselný | AND
Bitwise OR | 6 | binární komutativní | number | `|` | number | číselný | OR
Bitwise XOR | 6 | binární komutativní | number | `^` | number | číselný | XOR
Above | 5 | binární nekomutativní | number | `>` | number | logický | JA
Greater | 5 | binární nekomutativní | number | `#>` | number | logický | JG
Below | 5 | binární nekomutativní | number | `<` | number | logický | JB
Lower | 5 | binární nekomutativní | number | `#<` | number | logický | JL
Above or Equal | 5 | binární nekomutativní | number | `>=` | number | logický | JAE
Greater or Equal | 5 | binární nekomutativní | number | `#>=` | number | logický | JGE
Below or Equal | 5 | binární nekomutativní | number | `<=` | number | logický | JBE
Lower or Equal | 5 | binární nekomutativní | number | `#<=` | number | logický | JLE
číselný Equal | 5 | binární komutativní | number | `=` | number | logický | JE
číselný Nonequal | 5 | binární komutativní (4) | number | `!=` or `<>` | number | logický | JNE
Logical NOT | 4 | unární (3) |  | `!` | number | logický | NOT
Logical AND | 3 | binární komutativní | number | `&&` | number | logický | AND
Logical OR | 2 | binární komutativní | number | `||` | number | logický | OR
Logical XOR | 2 | binární komutativní | number | `^^` | number | logický | XOR
Segment separation | 1 | binární nekomutativní | number | `:` | number | adresní výraz |
Data duplication | 0 | binární nekomut. (1) (5) | number | `*` | datatype | datový výraz |
Range | 0 | binární nekomut. (1) | number | `..` | number | range |
Substring | 0 | binární nekomut. (1) | text | `[ ]` | range | text |
Sublist | 0 | biná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ásledovat | levá závorka | unární operátor | operand | binární operátor | pravá závorka | konec výrazu
začátek výrazu | ano | ano | ano | ne | ne | ano (2)
levou závorku | ano | ano | ano | ne | ano (2) | ne
unární operátor | ano | ne | ano | ne | ne | ne
operand | ne | ne | ne | ano | ano | ano
binární operátor | ano | ano (1) | ano | ne | ne | ne
pravou závorku | ne | ne | ne | ano | ano | ano

(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
baseregistr | BX SS:BP
indexregistr | SI DI
displacement | 16bitový integer se znaménkem, znaménkově roztažený na šířku segmentu
32bitový adresní mód v 16bitovém a 32bitovém segmentu
baseregister | EAX EBX ECX EDX ESI EDI SS:EBP SS:ESP
indexregister | EAX EBX ECX EDX ESI EDI EBP
displacement | 32bitový integer se znaménkem, znaménkově roztažený nebo oříznutý na šířku segmentu
32bitový adresní mód v 64bitovém segmentu
baseregister | EAX EBX ECX EDX ESI EDI SS:EBP SS:ESP R8D..R15D
indexregister | EAX EBX ECX EDX ESI EDI EBP R8D..R15D
displacement | 32bitový integer se znaménkem, znaménkově rozšířený na šířku segmentu
64bitový adresní mód v 64bitovém segmentu
baseregister | RAX RBX RCX RDX RSI RDI SS:RBP SS:RSP R8..R15
indexregister | RAX RBX RCX RDX RSI RDI RBP R8..R15
displacement | 32bitový 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ý
displacement | integer 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:

- k preprocesní %proměnné v okamžiku její expanze, např. `%MyVar[2..8]`
- ke jménu souboru v pseudoinstrukci INCLUDE a její rodině, např. `INCLUDEBIN "tada.wav"[44..%&]`
- ke jménu zdrojového souboru když byl euroasm.exe spuštěn z příkazového řádku, např. `euroasm "MySource1.asm"{0..24}`
- ke jménu cílového souboru ve volbě OUTFILE=, např. `BootSec PROGRAM OutFile="boot.sec"[0x7C01..0x7E00]`.

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
> - 16bitového nebo 32bitového ofsetu, a
> - paragrafové adresy získané z momentálně platného segmentového registru a vynásobené 16.
> 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:
> - segmentová počáteční adresa je určena jeho obsahem vynásobeným 16
> - velikostní limit je 64 KB v 16bitovém adresním módu
> - přístupová práva jsou všechno je dovoleno
> - šířka segmentu je 16 bitů, avšak je povoleno i používání 32bitového ofsetu na CPU 386 a novějších.

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řes 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ů; neexistuje 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řístup | Velikost 32bit | 64bit | Zarovnání v souboru 32bit | 64bit | Poznámka
--- | --- | --- | --- | --- | ---
Hlavička MZ DOS |  | RW | 128 | 128 |  | 0) 2)
Program MZ stub |  | RW |  | 16 | 16 | 0) 2)
Podpis PE |  | RW | 4 | 4 | 32 | 32 | 0) 2)
Hlavička souboru |  | R | 20 | 20 | 16 | 16 | 0)
"Volitelná" hlavička |  | R | 224 | 240 | 16 | 16 | 0) 2)
Hlavičky "sekcí" |  | R | NrOfSe*40 | 16 | 16 | 0)
.text | CODE | RX |  | FiAl|SeAl |
.rodata | RODATA | R |  | FiAl|SeAl |
.data | DATA | RW |  | FiAl|SeAl |
.bss | BSS | RW |  | FiAl|SeAl |
.idata | IMPORT+IAT | RWX |  | 16|16 | 0) 2)
.edata | EXPORT | RW |  | 16|16 | 0) 2) 5)
.reloc | BASERELOC | RW |  | 16|16 | 0) 2)
.rsrc | RESOURCE | RW |  | 16|16 | 0)
Tabulka symbolů | (SYMBOLS) | R | NrOfSym*18 | 16 | 16 | 0) 1) 3)
Tabulka řetězců | (STRINGS) |  |  | 4 | 4 | 0) 1) 3)

Anatomie programu založeného na formátu ELF:
Názve | Účel segmentu | Přístup | Velikost 32bit | 64bit | Zarovnání v souboru 32bit | 64bit | Poznámka
--- | --- | --- | --- | --- | ---
Hlavička souboru |  | R | 52 | 64 |  | 0)
Hlavičky "programů" |  | R | NrOfPh*(32|56) | 16 | 8 | 0) 2)
Hlavičky "sekcí" |  | R | NrOfSe*(40|64) | 8 | 16) | 0)
.symtab | SYMBOLS |  | NrOfSym*(16|24) | 16 | 8 |
.hash | HASH | R |  | 4 | 4 | 4)
.strtab | STRINGS |  |  | 1 | 1 |
.shstrtab | STRINGS |  |  | 1 | 1 |
.interp | RODATA | R |  | 1 | 1 | 4)
.plt | PLT | RX | NrOfJmp*16 | 16 | 4)
.text | CODE | RX |  | FiAl|SeAl |
.rodata | RODATA | R |  | FiAl|SeAl |
.data | DATA | RW |  | FiAl|SeAl |
.bss | BSS | RW |  | FiAl|SeAl |
.dynamic | DYNAMIC | RW | NrOfRec*(8|16) | 8 | 16 | 4)

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
private | Global
Standard | local | statické linkování | dynamické linkování
Public | Extern | eXport | Import

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 typu | Zkratka | Velikost | Auto alignment | Šířka | Typické úložiště | Znakový řetězec | Celé číslo | Číslo s plovoucí tečkou | Spojený vektor
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
BYTE | B | 1 | 1 | 8 | R8 | ANSI | 8bit |  |
UNICHAR | U | 2 | 2 | 16 | R16 | WIDE |  |  |
WORD | W | 2 | 2 | 16 | R16 |  | 16bit |  |
DWORD | D | 4 | 4 | 32 | R32,ST |  | 32bit | jednoduchá přesnost |
QWORD | Q | 8 | 8 | 64 | R64,ST |  | 64bit | dvojitá přesnost |
TBYTE | T | 10 | 8 | 80 | ST |  |  | rozšířená přesnost |
OWORD | O | 16 | 16 | 128 | XMM |  |  |  | 4×D | 2×Q
YWORD | Y | 32 | 32 | 256 | YMM |  |  |  | 8×D | 4×Q
ZWORD | Z | 64 | 64 | 512 | ZMM |  |  |  | 16×D | 8×Q

Ostatní datové typy
Jméno typu | Zkratka | Velikost | Autoalign | Použití
--- | --- | --- | --- | ---
Jméno_struktury | S | různá | Explicitní zarovnání STRUC, jinak šířka programu | strukturované proměnné
INSTR | I | různá | 1 | strojové 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ů
Kategorie | Rezervované 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ů
Kategorie | Nedoporuč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:
> - Je-li název symbolu vhodně vybrán, např. `BufferSize`, je samovysvětlující a nemusíme komentovat, proč jsme plnili ECX zrovna touto hodnotou `16K`.
> - Pokud se později rozhodneme změnit `BufferSize` během vývoje programu, je snazší tak učinit pouze na jednom místě, kde je definována.

#### ↑ 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# ↓

##### RVA# ↓

##### 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.

##### ↑ RVA#

Atribut RVA# představuje Relativní Virtuální Adresu (RVA) symbolu nebo sekce. Zatímco `Symbol` v datech spustitelného souboru reprezentuje virtuální adresu (VA) tohoto symbolu, `RVA# Symbol` od této adresy odečítá hodnotu image base, římž vytváří jeho RVA.
I když by RVA mohla v 64-bitovém kódu zabírat i více než 32 bity, €ASM tuto adresu omezuje tak, aby se vešla do dvaatřicetibitové proměnné typu DWORD, jak v 32-bitovém, tak i v 64 bitovém módu. To předurčuje atribut RVA3 k definování adres v sekci [.pdata] spustitelných programů pro MS Windows. Viz test t1653 jako ukázku.

##### ↑ 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 nalezen. 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ů
Vlastnost | Standardní symbol | Literální symbol
--- | --- | ---
Deklarace | Definovaný 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éno | Programá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ódu | Umístění dat symbolu je zcela v režii programátora. | Programátor nemůže přímo ovlivňovat jeho umístění.
Alignment | Je-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í nulou | Pouze na explicitní žádost, např. `Hello: DU "Hello, world",0`. | Automaticky, např. `MOV ESI,=U "Hello, world"`.
Duplikace | Podporována, např. `FourDoublePrecOnes: DY 4 * Q 1.0` | Podporována, např. `VMOVUPD YMM7, [= 4 * Q 1.0]`.
Přepisování hodnoty | Pří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ůj 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é
--- | --- | --- | --- | ---
EUROASM | PROGRAM | €ASM
forma názvu | %identifikátor | %identifikátor | %speciální_znak | %^volba | %^volba | %^pevný
citlivost na velikost písmen v názvu | Ano | Ano | Ano | Ne | Ne | Ne
Znovupřiřaditelnost | explicitně 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
Kategorie | Rezervované 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
Symboly | Už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é
Kategorie | Ná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, %^MaxErrors, %^MaxExpansions, %^MaxPasses, %^MinorImageVersion, %^MinorLinkerVersion, %^MinorOSVersion, %^MinorSubsystemVersion, %^Model, %^OutFile, %^SectionAlign, %^SizeOfHeapCommit %^SizeOfHeapReserve, %^SizeOfStackCommit, %^SizeOfStackReserve, %^StubFile, %^Subsystem, %^TimeStamp, %^Width, %^Win32VersionValue,
€ASM | %^Date, %^Errorlevel, %^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í €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.
%^Errorlevel
  Aktuální hodnota návratového kódu.
%^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:

- Krátké podmíněné skoky a smyčky procesoru 8086 mimo bajtový rozsah jsou zakódovány jako kompozice proxy-skoku JMPN přeskočeného krátkým skokem nebo smyčkou s invertovanou podmínkou, viz NEAR a FAR LOOP a Jcc.
- Další výjimkou je `MOVZX r64,r/m32` implementované jako `MOV r32,r/m32`, kdy využívá vedlejší efekt architektury IA-64 spočívající v nulování vyšší poloviny 64bitových registrů, pokud se zapisuje do jejich dolní poloviny. Viz test t3043.

#### 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říponu | Přípona
--- | ---
ADC, ADD, AND, CMP, CMPS, CRC32, DEC, DIV, IDIV, IMUL, INC, LODS, MOV, MOVS, MUL, NEG, NOT, OR, PUSH, 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, PUSHF | W, D, Q
PUSHA, POPA | W, D
INS, MOVSX, MOVZX, OUTS | B, W, D
XLAT | B
CALL, RET | N, F
JMP | S, 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:

- Přípona může být použita pouze s omezeným repertoárem všeobecných instrukcí, zatímco modifikátor DATA= může být aplikován na mnoho dalších instrukcí včetně FPU, MMX, SIMD.
- Instrukční modifikátor není přísný příkaz, ale spíše jen nápověda. Pokud aktuální data nemohou splnit požadavek modifikátoru DATA=, bude modifikátor ignorován a €ASM vydá varování. Pokud data neplní pořadavek přípony, €ASM to považuje za chybu.

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):

- `[0*IR+BR+disp] > [BR+disp]`
  Pseudoškálování faktorem nula je zcela vynecháno.
- `[1*IR+BR+disp] > [IR+BR+disp]`
  Škálování faktorem jedna se bere jako absence škálování.
- `[2*IR+disp] > [BR+IR+disp]`
  Škálování faktorem dvě bez bázového registru se zakóduje jako báze+index bez škálování.

`|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:

- Příponu lze použít pouze u instrukcí `JMP, CALL, RET`, zatímco modifikátor DIST= může být aplikován i na další instrukce pro předání zpracování: `LOOPcc, Jcc, JrCXZ`.
- Nelze-li instrukci zakódovat v souladu s požadovanou vzdáleností DIST=, modifikátor se ignoruje a €ASM vydává varování. Nelze-li vyhovět příponě, €ASM to považuje za chybu.

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
Prefix | Požadovaná volba EUROASM
--- | ---
XOP | SIMD=AVX, AMD=ENABLED, XOP=ENABLED
VEX | SIMD=AVX
MVEX | SIMD=AVX512, MVEX=ENABLED
EVEX | SIMD=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=0 | registr-do-registru, EH=1 | paměť-do-registru | registr-do-paměti
--- | --- | --- | --- | ---
0 | no swizzle {dcba} | ROUND=NEAR,SAE=NO | no operation | no conversion
1 | swap (inner) pairs {cdab} | ROUND=DOWN,SAE=NO | bcst 1 element {1to16} or {1to8} | not available
2 | swap with two-away {badc} | ROUND=UP,SAE=NO | bcst 4 elements {4to16} or {4to8} | not available
3 | cross-product swizzle {dacb} | ROUND=ZERO,SAE=NO | convert from {float16} | convert to {float16}
4 | bcst a element across 4 {aaaa} | ROUND=NEAR,SAE=YES | convert from {uint8} | convert to {uint8}
5 | bcst b element across 4 {bbbb} | ROUND=DOWN,SAE=YES | convert from {sint8} | convert to {sint8}
6 | bcst c element across 4 {cccc} | ROUND=UP,SAE=YES | convert from {uint16} | convert to {uint16}
7 | bcst d element across 4 {dddd} | ROUND=ZERO,SAE=YES | convert from {sint16} | convert to {sint16}

Operace kódované s EVEX
OPER= | registr-do-registru | paměť-do-registru
--- | --- | ---
0 | DATA=OWORD,SAE=NO | DATA=OWORD,BCST=OFF
1 | DATA=ZWORD,SAE=YES,ROUND=NEAR | DATA=OWORD,BCST=ON
2 | DATA=YWORD,SAE=NO | DATA=YWORD,BCST=OFF
3 | DATA=ZWORD,SAE=YES,ROUND=DOWN | DATA=YWORD,BCST=ON
4 | DATA=ZWORD,SAE=NO | DATA=ZWORD,BCST=OFF
5 | DATA=ZWORD,SAE=YES,ROUND=UP | DATA=ZWORD,BCST=ON
6 | reserved | reserved
7 | DATA=ZWORD,SAE=YES,ROUND=ZERO | reserved

`|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
Mnemonika | Operační kód (hexa) | Ekvivalentní instrukce v syntaxi €ASM
--- | --- | ---
16bit mode, CPU=086
NOP1 | 90 | XCHG AX,AX
NOP2 | 87C9 | XCHG CX,CX
NOP3 | 9087C9 | XCHG AX,AX ; XCHG CX,CX
NOP4 | 87C987D2 | XCHG CX,CX ; XCHG DX,DX
NOP5 | 9087C987D2 | XCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX
NOP6 | 87C987D287DB | XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX
NOP7 | 9087C987D287DB | XCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX
NOP8 | 87C987D287DB87E4 | XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX ; XCHG SP,SP
NOP9 | 9087C987D287DB87E4 | XCHG AX,AX ; XCHG CX,CX ; XCHG DX,DX ; XCHG BX,BX ; XCHG SP,SP
16bit mode, CPU=686
NOP1 | 90 | NOP DATA=WORD
NOP2 | 6690 | OTOGGLE NOP
NOP3 | 666790 | OTOGGLE ATOGGLE NOP
NOP4 | 670F1F00 | NOP [EAX],DATA=WORD
NOP5 | 670F1F4000 | NOP [EAX],DATA=WORD,DISP=BYTE
NOP6 | 670F1F442000 | NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP7 | 66670F1F442000 | NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP8 | 670F1F8000000000 | NOP [EAX],DATA=WORD,DISP=DWORD
NOP9 | 670F1F842000000000 | NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
32bit mode, CPU=386
NOP1 | 90 | XCHG EAX,EAX,DATA=DWORD
NOP2 | 6690 | XCHG AX,AX,DATA=WORD
NOP3 | 8D4000 | LEA EAX,[EAX],DATA=DWORD
NOP4 | 8D442000 | LEA EAX,[EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP5 | 3E8D442000 | LEA EAX,[DS:EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP6 | 8D8000000000 | LEA EAX,[EAX],DATA=DWORD,DISP=DWORD
NOP7 | 8D842000000000 | LEA EAX,[EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP8 | 3E8D842000000000 | LEA EAX,[DS:EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9 | 663E8D842000000000 | LEA AX,[DS:EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
32bit mode, CPU=686
NOP1 | 90 | NOP DATA=DWORD
NOP2 | 6690 | NOP DATA=WORD
NOP3 | 0F1F00 | NOP [EAX],DATA=DWORD
NOP4 | 0F1F4000 | NOP [EAX],DATA=DWORD,DISP=BYTE
NOP5 | 0F1F442000 | NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP6 | 660F1F442000 | NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP7 | 0F1F8000000000 | NOP [EAX],DATA=DWORD,DISP=DWORD
NOP8 | 0F1F842000000000 | NOP [EAX+0*EAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9 | 660F1F842000000000 | NOP [EAX+0*EAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
64bit mode, CPU=X64
NOP1 | 90 | NOP DATA=DWORD
NOP2 | 6690 | NOP DATA=WORD
NOP3 | 0F1F00 | NOP [RAX],DATA=DWORD
NOP4 | 0F1F4000 | NOP [RAX],DATA=DWORD,DISP=BYTE
NOP5 | 0F1F442000 | NOP [RAX+0*RAX],DATA=DWORD,SCALE=VERBATIM,DISP=BYTE
NOP6 | 660F1F442000 | NOP [RAX+0*RAX],DATA=WORD,SCALE=VERBATIM,DISP=BYTE
NOP7 | 0F1F8000000000 | NOP [RAX],DATA=DWORD,DISP=DWORD
NOP8 | 0F1F842000000000 | NOP [RAX+0*RAX],DATA=DWORD,SCALE=VERBATIM,DISP=DWORD
NOP9 | 660F1F842000000000 | NOP [RAX+0*RAX],DATA=WORD,SCALE=VERBATIM,DISP=DWORD
Mnemonika | Operač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á:

> - vložit strojovou instrukci `Main: NOP`
> - nebo vytvořit proceduru `Main: PROC`
> - nebo přepnout ručně: `[.text]` nad řádkem `Main: StdOutput Title`

>           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= ↓

##### MAXERRORS= ↓

##### MAXEXPANSIONS= ↓

##### MAXPASSES= ↓

##### 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 | .bin | 16bits | TINY | Binární soubor
BOOT | .sec | 16bits | TINY | Bootovatelný soubor
COM | .com | 16bits | TINY | Spustitelný soubor DOS/CPM
ELF | .o | 32bits | FLAT | Linkovatelný objektový modul
ELFX | .x | 32bits | FLAT | Spustitelný soubor pro Linux
ELFSO | .so | 32bits | FLAT | Dynamicky sdílený soubor pro Linux
OMF | .obj | 16bits | SMALL | Linkovatelný objektový modul
LIBOMF | .lib | 16bits | SMALL | Objektová knihovna ve formátu OMF
MZ | .exe | 16bits | SMALL | Spustitelný program pro DOS
COFF | .obj | 32bits | FLAT | Linkovatelný objektový modul
LIBCOF | .lib | 32bits | FLAT | Objektová knihovna ve formátu COFF
PE | .exe | 32bits | FLAT | Spustitelný program pro MS-Windows
DLL | .dll | 32bits | FLAT | Dynamická 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:

- 16bitový mód
- 32bitový mód
- 64bitový mód (vyžaduje 64bitový procesor, volba `EUROASM CPU=X64` by měla být také nastavena.)

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
TINY | NEAR | NEAR | 16 | ne | ne | ano | real | COM
SMALL | NEAR | NEAR | 16 | ne | ne | ne | real | MZ, OMF
MEDIUM | FAR | NEAR | 16 | ano | ne | ne | real | MZ, OMF
COMPACT | NEAR | FAR | 16 | ne | ano | ne | real | MZ, OMF
LARGE | FAR | FAR | 16 | ano | ano | ne | real | MZ, OMF
HUGE | FAR | FAR | 32 | ano | ano | ne | real | MZ, OMF
FLAT | NEAR | NEAR | 32,64 | ne | ne | ano | protected | ELF, 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= | Hodnota | Poznámka
--- | --- | ---
0 | 0 | Neznámý subsystém.
1 | NATIVE | Subsystém není použit (ovladač zařízení).
2 | GUI | Grafický subsystém MS-Windows.
3 | CON | Konzolový (znakový) subsystém MS-Windows.
5 | OS2 | Znakový subsystém OS/2.
7 | POSIX | Znakový subsystém Posix.
8 | WXD | Nativní ovladač MS-Windows 95/98.
9 | WCE | Grafický 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.

##### ↑ MAXERRORS=

Parametr omezuje počet vypisovaných chyb se závažností větší než 3 způsobených vadným programem. Při dosažení tohoto počtu se vypíše fatální chyba F9409 (Number of errors exceeded MAXERRORS) a kompilace je havarijně ukončena. Výchozí hodnotou je MAXERRORS=128.

##### ↑ 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í hodnota je prázdná, tzn. že žádná ikona nebude vestavěna do programů vytvořených EuroAssemblerem. Můžete ovšem přidat např. `ICONFILE="euroasm.ico"` k pseudoinstrukci PROGRAM a použít tak ikonu 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

> Na rozdíl od jiných asemblerů nepoužívá €ASM příznaky jako readable, writeable, executable. Místo toho zavádí vlastnost PURPOSE=, která definuje základní účel segmentu (vykonávatelný kód, data pouze ke čtení, neinicializovaná data, rezervace zásobníku) a která také může deklarovat, že tento segment má specifickou funkci uvedenou v hlavičce optional header souboru PE (např. IMPORT, IAT, BASERELOC...) nebo v hlavičce linuxového souboru ELF (.hash, .strtab, .dynamic atd.).

##### 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= | Alias | Přístup | Výchozí jméno | Obsahuje
--- | --- | --- | --- | ---
CODE | TEXT | read, execute | `[.text]|[CODE]` | Programový kód (instrukce) (1)
RODATA | RDATA | read | `[.rodata]|[RODATA]` | Inicializovaná data pouze ke čtení (1)
DATA | IDATA | read, write | `[.data]|[DATA]` | Inicializovaná data (1)
BSS | UDATA | read, write | `[.bss]|[BSS]` | Neinicializovaná data (1)
STACK |  | read, write | `[STACK]` | Strojový zásobník (1)
LITERALS | LITERAL | read | parazituje na jiných data/code segmentech | Literální sekce (2)
DRECTVE |  | discarded | `[.drectve]` | Direktivy pro linker (3)
PHDR |  |  |  | Hlavičky programu (4)
INTERP |  |  |  | Dynamický 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)
SECURITY |  |  |  | Certifikáty (5)
BASERELOC |  | discarded | `[.reloc]` | Load-time relokace (4)
DEBUG |  |  | `[.debug]` | Data pro debuger (5)
COPYRIGHT | ARCHITECTURE |  |  | Architektura (5)
GLOBALPTR |  |  |  | RVA globálního pointeru (5)
TLS |  |  | `[.tls]` | Paměť vlákna (5)
LOAD_CONFIG |  |  |  | Načtení konfigurace (5)
BOUND_IMPORT |  |  |  | Bound import (5)
IAT |  |  | `[.idata]` | Importní adresní tabulka (4)
DELAY_IMPORT |  |  |  | Zpožděný import (5)
CLR |  |  | `[.cormeta]` | Metadata CLR (5)
RESERVED |  |  |  | Reservová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 (samozřejmě až na velikost písmen) s některým účelem vyjmenovaným v tabulce nahoře, bude použit tento účel.
2. Obsahuje-li jméno řetězec `STACK`, bude použit `PURPOSE=STACK`.
3. Obsahuje-li jméno řetězec `BSS` nebo `UDATA`, bude použit `PURPOSE=BSS`.
4. Obsahuje-li jméno řetězec `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:

> - Kód je lépe strukturován a snazší k porozumění.
> - €ASM kontroluje správné spárování návěstí, což je zvláště důležité, pokud jsou procedury vnořeny.
> - Je jasné, kde procedura končí. Nemusíme prohlížet kód a hledat, která z instrukcí RET je poslední, když potřebujeme zkopírovat proceduru do jiného programu.
> - Každý blok PROC..ENDP definuje svůj vlastní jmenný prostor a zabraňuje tak konfliktům lokálních jmen použitých v proceduře.

##### ↑ 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.

#### ↑ HEAD

#### ↑ 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ík | Příklad | Pokud je nalezen aspoň jeden soubor | Pokud nebyl nalezen žádný soubor
--- | --- | --- | --- | ---
Ne | Ne | file.inc | Hotovo, nehledej dále v INCLUDEPATH. | Error E6914.
Ano | Ne | ./file.inc | Hotovo. | Error E6914.
Ne | Ano | file*.inc | Prohledávej další soubory v INCLUDEPATH. | Nic nebylo vloženo, nehlas žádnou chybu.
Ano | Ano | ./file*.inc | Pokrač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.

#### ↑ LINK

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 %DISPLAY | Oznámení | Filtr | Řazení | Zobrazované objekty
--- | --- | --- | --- | ---
All | D1100..D1900 | ano | abecední | Všechny níže specifikované objekty (zkratka pro Fil,Ch,Se,St,Co,Sym,L,Rel,M,V).
Files | D1150..D1190 | ignorován | přirozené | Zdrojové soubory vložené do programu.
Chunks | D1200..D1240 | ignorován | přirozené | Kusy zdrojového kódu.
Sections | D1250..D1290 | ignorován | přirozené | Mapa grup, segmentů a sekcí.
Segments | D1250..D1290 | ignorován | přirozené | Mapa grup, segmentů a sekcí.
Groups | D1250..D1290 | ignorován | přirozené | Mapa grup, segmentů a sekcí.
Structures | D1300..D1340 | ano | abecední | Struktury deklarované v programu.
Context | D1350..D1390 | ignorován | dle zásobníku | Kontextový zásobník blokových instrukcí.
Symbols | D1400..D1450 | ano | abecední | Všechny explicitně definované symboly (zkratka pro Fix,Unf,Unr,Ref).
UnfixedSymbols | D1410..D1450 | ano | abecední | Symboly, jejichž vlastnosti dosud nejsou stabilní.
FixedSymbols | D1420..D1450 | ano | abecední | Symboly, jejichž vlastnosti již jsou fixovány.
UnreferencedSymbols | D1430..D1450 | ano | abecední | Dosud nepoužité symboly.
ReferencedSymbols | D1440..D1450 | ano | abecední | Aspoň jednou zmíněné symboly.
LiteralSymbols | D1500..D1540 | ignorován | abecední | Všechny literály.
Relocations | D1550..D1590 | ignorován | přirozené | Relokační záznamy.
Macros | D1600..D1690 | ano | abecední | Makroinstrukce dosud definované.
Variables | D1700..D1790 | ano | abecední | Všechny preprocesní %proměnné momentálně nastavené (zkratka pro Au,Fo,Us,Sys).
AutomaticVariables | D1710..D1730 | ignorován | fixní | Automatické makro %proměnné.
FormalVariables | D1740..D1750 | ano | abecední | Formální makro/for %proměnné.
UserVariables | D1760..D1770 | ano | abecední | Uživatelem definované preprocesní %proměnné.
SystemVariables | D1780..D1790 | ano | abecední | 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

- main - hlavní zdroj (specifikovaný na příkazovém řádku),
- lokální konfigurční soubor euroasm.ini
- nebo inkludovaný zdrojový soubor.

Vlastnost Chunku type= určuje informaci obsaženou v tomto kusu zdrojového textu:

- source - normální zdrojový soubor,
- binary - data vkládaná pomocí IncludeBin,
- původní instrukce Include (bude nahrazena obsahem souboru),
- nebo resolved - včetně IncludePath a žolíkových znaků resolvovaných na unikátní jméno souboru.

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 ↓

### BOOT ↓

### 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:
   - LIBOMF, LIBCOF - objektové knihovny obsahují staticky linkovanelné objektové moduly.
   - LIBOMF, LIBCOF - importní knihovny obsahují reference na dynamicky linkované funkce importované z MS-Windows.
   - LIBOMF, LIBCOF - smíšené knihovny, které jsou kombinacemi obou.
   - DLL - dynamicky linkovatelné knihovny MS-Windows.,
   - ELFSO - dynamicky sdílené objekty, nicméně v této verzi linkovatelné EuroAssemblerem pouze staticky.

   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:

- Linkovatelný objektový soubor ELF, v €ASM vytvářený pomocí PROGRAM FORMAT=ELF
- Spustitelný soubor, vytvářený pomocí PROGRAM FORMAT=ELFX
- Dynamicky Sdílený Objekt (DSO), vytvářený pomocí PROGRAM FORMAT=ELFSO

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
Člen | PROGRAM WIDTH=16 | PROGRAM WIDTH=32 | PROGRAM 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 | 224 | 224 | 240

## ↑ Funkce EuroAssembleru

### Preprocesing ↓

### Refaktorizace ↓

### Asembler ↓

### Hledání chyb v asembleru ↓

### Linker ↓

### Knihovník ↓

### Objektový konvertor ↓

### Makefile manažer ↓

### Disasembler ↓

### 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říklad | Co jej nahradí
> --- | --- | ---
> `%` | %% | Jednoduchý znak procenta `%`
> `&` | %& | Velikost nebo délka suboperace
> `.` | %. | Počitadlo expanzí
> `:` | %: | Návěstí makra
> `!` | %!formal | Invertovaná 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` | %^Width | Systémová %^proměnná (čísla 16, 32 nebo 64}
> decimal digit(s) | %12 | Pořadový operand makra, např. dvanáctý
> letter(s) | %If | Jméno pseudoinstrukce je ponecháno neexpandované (`%If`)
> %Size | Pokud je to formální operand, bude expandován na svou hodnotu,
> %OtherId | jinak 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.

#### ↑ Staticky linkovaná PROC

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.

#### ↑ Dynamicky linkovaná PROC

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.

### ↑ Linker

#### 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ý
--- | --- | --- | --- | --- | ---
Real | 16 | BIN, BOOT, COM, MZ | OMF, LIBOMF, COFF, LIBCOF | OMF, LIBOMF, COFF, LIBCOF | -
Real | 32 | BIN, BOOT, COM, MZ | OMF, LIBOMF, COFF, LIBCOF | OMF, LIBOMF, COFF, LIBCOF | -
Prot | 32 | ELFX, PE, DLL | ELF, COFF, LIBCOF, OMF, LIBOMF | ELF, COFF, LIBCOF, RSRC, OMF, LIBOMF | ELF, COFF, LIBCOF, DLL, OMF, LIBOMF
Prot | 64 | ELFX, PE, DLL | ELF, COFF, LIBCOF | ELF, COFF, LIBCOF, RSRC | ELF, 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:

- Použijte explicitní importní deklaraci, například `IMPORT ImportedSymbol1, ImportedSymbol2, LIB="dynamic.dll"`. Dynamická knihovna by měla být specifikována bez cesty a může být vynechána, pokud je to základní knihovna jádra Windows kernel32.dll.

  > Přítomnost dynamic.dll není zjišťována během linkování, program se sestaví bez chyb dokonce i když takový soubor na našem počítači vůbec neexistuje. Avšak Windows si začne stěžovat, že spouštěný program nemůže nalézt knihovnu dynamic.dll anebo že ImportedSymbol nebyl exportován knihovnou dynamic.dll.

- Přilinkujte k programu importní knihovnu, pomocí `LINK "winapi.lib"`. Takový soubor může být ve formátu LIBOMF nebo LIBCOF a obvykle obsahuje pouze deklarace jmen exportovaných symbolů a jejich knihovních souborů (čistě importní knihovna). €ASM ztotožní nedefinované globální symboly s názvy z importní knihovny a redeklaruje je jako IMPORT.

  > Některé starší knihovní programy, jako [ALIB], produkují importní knihovny ve dlouhém formátu, který obsahuje přídavný kód skoků na thunk. €ASM dlouhý formát akceptuje, avšak ignoruje tento nadbytečný obsah.
  > Některé kompilátory zatemňují (mangle) exportovaná jména dekorací pomocí podtržítek a dalším obsahem prozrazujícím volací konvenci a počet operandů. €ASM to nepodporuje, importované funkce musejí být volány identickým jménem, které je exportováno.

  Vzorový projekt dll2lib.htm ukazuje, jak vytvořit exportní knihovnu z dynamických knihoven DLL systému MS-Windows.

- Přilinkujte dynamickou knihovnu abyste zjistili, co exportuje. Knihovna by měla být určena s kompletní cestou a musí existovat v link-time, např.

       %SystemRoot %SETE SystemRoot
       LINK "%SystemRoot\system32\USER32.DLL"

  Linkování dynamické knihovny nekopíruje její kód a data do našeho programu, pouze detekuje jména exportovaných funkcí. Instrukce je ekvivalentní deklaraci `IMPORT *, LIB="USER32.DLL"` nebo přilinkování importní knihovny `LINK "USER32.lib"`.

- Toto načtení knihovny může být odloženo z load-time na run-time, použitím funkce Windows API `LoadLibrary("library.dll"); GetProcAddress(SymbolName);` předtím, než bude použito SymbolName.

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 pokud "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

### ↑ Disasembler

Zpětný překladač neboli EuroDisassembler jako samostatný program neexistuje, avšak je nahrazen funkčností utility EuroView obsažené v balíčku programů EuroTool.

### ↑ 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,
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:

- Jména souborů určených k překladu, k inkludování a k linkování mohou být specifikována jen částečně, s použitím žolíkových znaků `* ?`, například `INCLUDE "Win*.inc"`.
- Nejste-li si jisti, zda určitý soubor nebyl již jednou inkludován, použijte `INCLUDE1 file` místo `INCLUDE file` a €ASM se o to postará.
- Můžete používat symboly a struktury dříve než byly definovány pomocí `EQU` nebo `STRUC`.
- Můžete definovat a referovat datové položky v jedné instrukci s použitím literálů, jako třeba `FLD ST0,[=Q 1.234]`.
- Vzdálenost cíle instrukcí předání zpracování JrCXZ, LOOPcc, Jcc není omezena na 127 bajtů. €ASM v případě potřeby kóduje NEAR nebo FAR proxy-skoky. Není to sice doporučeníhodná technika pokud jde o rychlost programu, ale nemuset se starat o vzdálenost cíle umožňuje sestavovat programové prototypy rychleji.
- Interakce s operačním systémem, zejména v 64bitovém módu, je v asembleru pracná. Programátor musí předávat parametry zásobníkem nebo v registrech s respektováním volacích konvencí. Některé asemblery vyvinuly speciální direktivy (INVOKE, PROTO atd.), které obalují volání OS. EuroAssembler odkládá podobné detaily do maker. Volací konvence nejsou do euroasm.exe pevně vestavěny a mohou tak být operativně přizpůsobeny modifikací maker API.

#### ↑ 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ů:

- jména segmentů jsou vždy v hranatých závorkách `[]`,
- návěstí a další symboly lze rozpoznat podle zakončující dvojtečky `:`,
- speciálním floating-point konstantám je předřazen znak `#`.
- za operátory atributů je připojen znak `#`.
- preprocesním %proměnným a pseudoinstrukcím předchází znak procenta `%`.

### ↑ 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, projděte si tutoriál a prohlédněte si vzorové projekty. Mnoho štěstí!

▲Zpět na začátek▲