Prostředí a architektura

Assembler

Assembler je nízkoúrovňový programovací jazyk, který umožňuje psát programy přímo ve strojovém kódu procesoru. Program napsaný v assembleru se skládá z instrukcí. Jedna instrukce je jakýmsi povelem pro procesor, aby vykonal určitou činnost. Programy psané v assembleru není možné přenést na jiný procesor, než pro který byl napsán, pokud oba jsou procesory vyrobeny jinou architekturou. Program napsaný pro procesor Intel Pentium je například možné spustit na procesorech AMD odpovídající řady, ale nikoliv už na procesorech Motorola nebo Power PC. Blízkost assembleru s procesorem umožňuje velice dobrou optimalizaci programu, a to jak ve velikosti, tak v rychlosti. Nevýhodou assembleru je zdlouhavost psaní rozsáhlejších programů a také již uváděná nepřenositelnost mezi procesory (Programy napsané v C/C++ po překompilování přenositelné jsou).

Instrukce procesoru

Instrukce procesoru se dají zhruba rozdělit na

Registry procesoru

32bitové procesory X86 obsahují 10 32bitových registrů, které se běžně používají za běhu programu. Jsou to procesory

Jména registrů pocházejí z dob 16bitových procesorů, vyjadřovaly jejich časté použití. Registry EAX, EBX, ECX a EDX mají ještě spodní 16bitovou část, označenou AX, BX, CX, DX. Tato spodní část se dále dělí na horní byte (registr AH, BH, CH, DH) a spodní byte (registry AL, BL, CL, DL). Celkový přehled ukazuje na příkladu registru EAX obrázek vpravo.

První program v assembleru

Programy budeme psát a kompilovat v prostředí Microsoft Visual Studio, verze 6.0. Kostru programu převezmeme z článku Použití prostředí Visual Studio pro vývoj programů v assembleru, kde si můžete stáhnout kompletní příklad včetně projektu pro Visual Studio. Na tomto jednoduchého programu si postupně probereme všechny typy instrukcí. Nejsnadněji spustíte Visual Studio stlačením klávesy Enter nebo dvojitým kliknutím myší na souboru s příponou .dsw

Vstupním bodem programu bude pro nás funkce WinMain, podobně jako v C/C++. Není to sice nezbytně nutné (vstupní bod se může jmenovat jakkoliv), ale když jsme na to zvyklí z C/C++, tak není důvod zavádět odlišnosti. Kód funkce WinMain smažeme, ponecháme pouze kostru funkce:

WinMain PROC    hInstance    :HANDLE,
                hPrevInstance:HANDLE,
                lpszCmdParam :LPSTR,
                nCmdShow     :WORD

WinMain ENDP

Instrukce pro naplnění regustru hodnotou

Základní instrukce pro naplnění registru se nazývá mov. Zápis této instrukce je následující

       mov   cíl, zdroj

Pomocí této instrukce můžete naplnit registr číselnou hodnotou, hodnotou uloženou v jiném registru nebo i hodnotou uloženou v paměti. Není možné naplnit registr EIP ani EFLAGS, dále vřele nedoporučuji měnit obsah registru ESP (a to nejen v tomto příkladu, ale i ve všech, které budou následovat). Pomocí instrukce mov není možné kopírovat hodnotu z paměti do paměti ani kopírovat hodnotu mezi registry různé velikosti (např. AL a BX). Zde je příklad programu, používající několika instrukcí mov:

.data

dwValue    dd      12345678h            ; Proměnná o velikosti 32 bitů

.code

WinMain PROC    hInstance    :HANDLE,
                hPrevInstance:HANDLE,
                lpszCmdParam :LPSTR,
                nCmdShow     :WORD

        mov     eax, 1                  ; Naplní registr EAX hodnotou 1
        mov     ebx, eax                ; Zkopíruje obsah registru EAX do registru EBX
        mov     ecx, dword ptr dwValue  ; Naplní obsah registru ECX hodnotou uloženou
                                        ; v proměnné dwValue
        mov     ah, al
        mov     ch, cl
        mov     bx, ax
        ret
WinMain ENDP

Spouštíme program

Tento program nevytváří žádný viditelný výstup, spustíme jej tedy v krokovacím režimu (debug mode) klávesou F10. Klávesou Alt+5 zobrazíme okno "Registers", ukazující obsahy registrů. Opakovaným stlačením klávesy F10 projděte program krok po kroku a sledujte, jak se obsahy registrů mění.