••• Assembler pro začátečníky ][ •••
(Proč používáme assembler - základy optimalizace)
V první části mojí miniučebnice assembleru, jsem vás seznámil
se základy programovaní v assembleru. Ale asi uznáte, že psát všechny
programy kompletně v assembleru je velice neefektivní a mnohdy
zbytečné. Proto většina z nás využívá vymožeností hi-level jazyků.
Chci se proto zaměřit na použití assembleru v hi-level jazycích, tedy
hlavně pro low-level optimalizaci programů. Základem efektivního
využívaní optimalizace je přibližná představa o tom, jak kompilátor,
kterým svůj program kompilujete, generuje výsledný kód. Pokud jste
provedli všechny hi-level optimalizace jako odstranění zbytečných
volání funkcí ve výkonné smyčce a nahradili časově náročné funkce
předpočítanými tabulkami, je na řadě přepsat časově kritická místa do
assembleru. Prvním krokem optimalizace je vyloučit zbytečné přístupy
do paměti a všechny potřebné konstanty a výpočty provádět pomocí
registrů procesoru. Dalším, výrazně urychlujícím krokem je nahrazení
časově náročné instrukce jako například mul a div instrukcemi jako
shl, shr nebo xchg. Jejich taktování je o proti mul a div až 30x
menší. Používají se především v případech, kdy se nějaká proměnná
násobí konstantou.
Y:=2*X
Pascal (8-bit) Assembler (8-bit)
mov al,2 {04} mov al,X {08}
mov bl,X {08} shl ax,1 {02}
mul bl {72} mov Y,ax {09}
mov Y,al {09}
------ -----
93 19
Tímto způsobem se dají velice rychle vynásobit proměnné
hodnotami 2^n tedy (2,4,16,32,64,...). Pokud není konstanta mocninou
2, je třeba použít dvou instrukcí. Pro příklad uvedu násobení 320,
které se hojně používá v režimu 320x200x256.
Y:=320*X
Pascal (16-bit) Assembler (16-bit)
mov ax,320 {004} mov ax,X {08}
mov bx,X {008} xchg al,ah {04}
mul bx {124} mov bx,ax {02}
mov Y,ax {009} shr bx,2 {16}
add bx,ax {03}
mov Y,bx {09}
------ -----
145 42
Násobení 320 lze také provést například instrukcemi shl ax,6 a
shl bx,8 pokud pracujete s proměnnými typu integer. Z obou příkladů
je vidět, že takováto optimalizace dokáže urychlit výsledný průběh
programu až pětkrát, takže pokud se vám ve vnitřní smyčce vyskytují
podobné konstanty, nahraďte je výše zmíněnými instrukcemi a získáte
tak cenné takty pro časově náročné mul a div, které už jen tak
neodstraníte. Za zmínku stojí i fakt, že v současné době už většina
programátorů optimalizuje pro Pentium, protože má jednu výbornou
vlastnost pokud mu pošlete ke zpracování po sobě jdoucí stejné
instrukce, vykoná je najednou, takže pokud se ve vaší smyčce
vyskytuje například více mul a div instrukcí je dobré je pokud možno
zařadit za sebe. Další výrazné urychlení docílíte vhodným použitím
instrukcí typu movs a stos. Používají se při hromadném přesouvání dat
nebo vyplňování paměťových oblastí stejnou hodnotou. Používejte
instrukce s největším objemem dat jako movsd a stosd, pokud nejste
omezeni procesorem. Při přepisování si ani neuvědomíte, že už vlastně
optimalizujete, protože Pascal některé části programu generuje velice
obecně, takže pokud využijete například hodnoty v registru ax pro tři
operace získáte tím až 20 taktové urychlení. Dále je velice výhodné
(pokud to jde) optimalizovat v každé situaci, takže notoricky známe
xor ax,ax místo mov ax,0 nebo inc ax, inc ax místo add ax,2 se určitě
vyplatí. Problematika low-level optimalizace je velice zajímavá věc a
určitě stojí za to se jí více zabývat. V následujících příkladech vám
přináším ukázku, jak by asi měla vypadat optimalizace jednoduché
funkce na kreslení čáry pomocí Bresenhamova algoritmu. Nejdříve
uvádím její hi-level podobu a následuje vysoce optimalizovaná
procedura pro speciální případ horizontální čáry a pak pro čáru
nakreslenou mezi dvěma obecnými body [x1,y1] a [x2,y2]. Takže si je
pilně prostudujte a možná přijdete i na to, jak by se daly ještě více
zoptimalizovat, je to jen otázka nápadu. Na úplný závěr přikládám
malý rezidentní prográmek v Pascalu, který má jednu zajímavou
vlastnost, pokud jej spustíte, asi si už nezahrajete nějakou hru
běžící v režimu 320x200x256. Je to docela dobrý joke pro notorické
hráče, zkuste jej nenápadně vepsat do autoexecu nějakému vašemu
známému, který tráví většinu svého volného času hraním her,
pravděpodobně mu tím způsobíte abstinenční záchvat.
ReDox
-> příklady <-
no13h.pas
výheň