Obsah
1. Instrukční sada v režimu ARM
2. Instrukce podmíněného i nepodmíněného skoku
3. Výpočet konstanty uložené do instrukčního slova skoku
4. Skok do podprogramu a návrat z podprogramu
5. Aritmetické a logické instrukce
6. Aritmetické a logické instrukce podrobněji
7. Problematika načtení 32bitové konstanty do registrů
1. Instrukční sada v režimu ARM
V předchozí části seriálu o architekturách počítačů jsme si řekli základní informace o mikroprocesorech ARM z pohledu programátora. Zaměřili jsme se přitom především na situaci, kdy mikroprocesor pracuje v režimu, v němž načítá a zpracovává původní RISCové instrukce s pevnou šířkou 32 bitů. Víme již, že v tomto režimu mají všechny instrukce v nejvyšších čtyřech bitech zakódovánu podmínku určující, zda se má tato instrukce vykonat či nikoli. Díky existenci těchto čtyř bitů bylo možné eliminovat některé podmíněné skoky, jejichž vykonání je (stále) problematické, a to prakticky na všech typech mikroprocesorů vybavených instrukční pipeline. Dále bylo díky použití instrukcí pevné šířky 32 bitů umožněno, aby některé typy instrukcí obsahovaly i bitové pole využívané barrel shifterem, jenž je zapojen před aritmeticko-logickou jednotku takovým způsobem, aby bylo možné provést bitový posun či rotaci druhého operandu vstupujícího do ALU. Díky tomu neobsahuje původní instrukční sada ARM žádné specializované instrukce pro bitový posun či rotaci (viz též pátou kapitolu).
Připomeňme si ještě, jak vypadá formát bitových polí většiny instrukcí v režimu ARM. Některé instrukce mají odlišný formát; například se jedná o instrukce pro práci s koprocesory či o instrukci pro vyvolání programového přerušení (software interrupt):
Instrukce load a store, aritmetické operace atd.: 31 27 15 0 +------+--------------------------------+ | cond | opkód | Rn | Rd | operand 2 | +------+--------------------------------+ Instrukce používající násobičku: 31 27 15 0 +------+--------------------------------+ | cond | opkód | Rn | Rd | Rs | op.| Rm | +------+--------------------------------+ Instrukce load a store s offsetem: 31 27 15 0 +------+--------------------------------+ | cond | opkód | Rn | Rd | offset | +------+--------------------------------+ Instrukce LDM a STM: 31 27 15 0 +------+--------------------------------+ | cond | opkód | Rn | bitové pole reg. | +------+--------------------------------+ Instrukce skoku: 31 27 23 0 +------+--------------------------------+ | cond |opkód| offset skoku | +------+--------------------------------+
2. Instrukce podmíněného i nepodmíněného skoku
Podobně jako u dalších instrukčních sad (ISA), najdeme i v instrukčním souboru mikroprocesorů ARM několik instrukcí skoku. Tyto instrukce lze (poněkud zjednodušeně řečeno) považovat za instrukce, které do registru PC/R15 vloží novou konstantu, popř. navíc uloží původní obsah registru PC/14 do registru LR/R14 (v tomto případě je však situace komplikovanější, protože obsah registru PC se již kvůli posunu instrukce v pipeline zvýšil o hodnotu 8; podrobnosti si řekneme v dalším textu). Základní instrukcí skoku je instrukce pojmenovaná jednoduše B od slova branch. 32bitové slovo této instrukce je rozděleno na tři části. V nejvyšších čtyřech bitech se nachází kód podmínky, což v důsledku znamená, že jediná instrukce B může nahradit všechny formy podmíněných skoků (přesněji řečeno čtrnáct typů podmíněných skoků a jeden skok nepodmíněný). Za těmito čtyřmi bity následuje taktéž čtyřbitový operační kód 1010 a ve zbylých 24 bitech je pak uložena konstanta, z níž se vypočítá offset skoku:
31 27 23 0 +------+------+--------------------------+ | cond | 1010 | offset skoku | +------+------+--------------------------+
Vzhledem k tomu, že všechny instrukce jsou v operační paměti zarovnány na adresu dělitelnou čtyřmi, je před provedením skoku 24bitová konstanta obsažená v instrukci posunuta o dva bity doleva. Výsledkem je 26bitová konstanta (mající dva nejnižší bity nulové), která je při provádění skoku přičtena k aktuální hodnotě registru PC. Jednoduše lze spočítat, že díky použití 26bitové konstanty lze provést podmíněný či nepodmíněný skok v rozsahu ±32 MB. Důležité je, že se při překladu programu z assembleru musí při výpočtu offsetu odečíst od aktuální hodnoty registru PC hodnota osm, a to z toho důvodu, že se skok provádí až ve fázi execute, tj. ve chvíli, kdy se již v instrukční pipeline nachází další dvě instrukce: jedna ve fázi decode (ta byla přečtena z adresy původní PC+4) a druhá teprve ve fázi fetch a registr PC již obsahuje adresu této nejpozději načtené instrukce (původní PC+8). Pozdější varianty mikroprocesorů ARM sice již mají pipeline s jiným počtem řezů, ovšem toto chování zůstalo kvůli zpětné kompatibilitě zachováno.
3. Výpočet konstanty uložené do instrukčního slova skoku
Nyní si můžeme zkusit provést jednoduchý výpočet skutečného offsetu uloženého do 32bitového slova obsahujícího instrukci skoku. Předpokládejme následující program napsaný v assembleru, kde se na adrese 0×0004 nachází skok na adresu 0×0010 (ve skutečnosti by všechny adresy měly být 32bitové, zde si však pro přehlednost dovolím vynechat počáteční nuly). Program by mohl vypadat následovně:
0x0004 b cil 0x0008 libovolná instrukce 0x000c libovolná instrukce 0x0010 cil: libovolná instrukce
24bitová konstanta, která se má uložit do instrukčního kódu, se vypočítá takto:
constant = (cil - PC) / 4 (dělíme čtyřmi kvůli tomu, že spodní dva bity=00) cil = 0x0010 PC = 0x004 + 8 = 0x0000c (změna PC kvůli načtení dalších dvou instrukcí do pipeline) constant = (0x0010-0x000c) / 4 = 4/4 = 1
32bitové slovo skoku tedy bude složeno ze tří bitových polí:
Bity | Obsah (bin) | Význam |
---|---|---|
31–28 | 1110 | podmínkový kód AL=always (viz též předchozí díl seriálu) |
27–24 | 1010 | kód instrukce skoku |
23–00 | 0..01 | konstanta, z níž se vypočítá offset |
Dohromady tedy získáme hexadecimální hodnotu instrukce: 0×ea000001.
Poznámka: provedení skoku znamená vyprázdnění instrukční pipeline, což na původní architektuře ARM s třířezovou pipeline znamená zdržení o dva takty, protože instrukce umístěná v cíli skoku musí projít všemi třemi fázemi: fetch, decode, execute
4. Skok do podprogramu a návrat z podprogramu
Další důležitou instrukcí mikroprocesorů ARM je instrukce sloužící pro skok do podprogramu. Zatímco na mnoha jiných architekturách mikroprocesorů se ukládá návratová adresa do zásobníku, na mikroprocesorech ARM je pro uložení návratové hodnoty použit pracovní registr R14 nazývaný z tohoto důvodu taktéž link register. Pro skok do podprogramu se používá instrukce BL, neboli branch and link. Při provádění této instrukce provede mikroprocesor ve skutečnosti dvě operace: vypočítá adresu skoku stejným způsobem, jako tomu bylo u instrukce B (branch) a uloží tuto adresu do registru R15/PC. Současně však taktéž vloží adresu aktuální PC-4 do registru R14/LR, protože právě hodnota aktuální PC-4 je adresou instrukce ležící těsně ZA instrukcí skoku (nesmíme zapomenout na to, že se při provedení skoku ve skutečnosti již obsah registru PC stačil dvakrát zvýšit o hodnotu 4). Formát instrukce BL se až na odlišný opkód neliší od instrukce B:
31 27 23 0 +------+------+--------------------------+ | cond | 1011 | offset skoku | +------+------+--------------------------+
Jak se však provede návrat z podprogramu? Zajímavé je, že ve skutečnosti žádná speciální instrukce typu RET nebo RETURN na mikroprocesorech ARM neexistuje. Vše, co musí programátor udělat, je obnovit obsah registru R15/PC z registru R14, a to prostým přesunem dat:
MOV PC, LR
Jak při skoku do podprogramu, tak i při výskoku z něho (obecně při změně PC) dojde k vyprázdnění instrukční pipeline a tedy pozdržení vykonávání následující instrukce.
U mikroprocesorů ARM podporujících instrukční sadu Thumb, popřípadě i technologii Jazelle (bajtkód JVM) existují kromě výše zmíněné dvojice skokových instrukcí i instrukce další, které dokážou na základě hodnoty adresy přepnout instrukční sady (adresa je uložena v pracovním registru a testuje se jeho nejnižší bit). Pro přehlednost jsou všechny skokové instrukce vypsány v následující tabulce:
# | Instrukce | Význam |
---|---|---|
1 | B | prostý skok |
2 | BL | skok + uložení návratové hodnoty do link registru |
3 | BX | skok + přepnutí do režimu Thumb či zpět |
4 | BLX | kombinace instrukcí BL+BX |
5 | BXJ | skok + přepnutí do režimu Jazelle |
5. Aritmetické a logické instrukce
Velkou skupinu instrukcí v instrukčním souboru mikroprocesorů ARM představují aritmetické a logické instrukce. Většina těchto instrukcí obsahuje v instrukčním slově bitové pole pro tři operandy: cílový registr, zdrojový registr (první operand) a druhý operand. Zatímco prvním operandem je vždy pracovní registr, druhým operandem může být buď jeden z pracovních registrů, nebo též osmibitová konstanta. Druhý operand je navíc před vstupem do aritmeticko-logické jednotky zpracován v barrel shifteru, který může provést buď bitovou rotaci nebo bitový posun. Navíc je možné počet míst, o něž se rotace či posun provede, určit buď pětibitovou konstantou nebo obsahem dalšího pracovního registru. Obecný formát aritmetických a logických instrukcí je následující:
31 27 15 0 +------+--------------------------------+ | cond | opkód | Rn | Rd | operand 2 | +------+--------------------------------+
Flexibilita aritmetických a logických instrukcí však jde ještě dále, protože u každé instrukce lze pomocí nejvyšších čtyř bitů zvolit, za jakých podmínek se instrukce provede (to již známe z předchozího textu). Navíc většina těchto instrukcí ještě obsahuje S-bit určující, zda má instrukce nastavit příznaky ALU (N, V, Z, C) na základě výsledku operace. Jediné instrukce, u nichž je tento bit nastaven stále, jsou instrukce provádějící porovnání bez uložení výsledku operace. Jak podmínka určující provedení/neprovedení instrukce, tak i bit S a samozřejmě taktéž specifikace rotace/bitového posunu, se zapisuje do jediné instrukce, takže například instrukce pro součet může mít mnoho formátů a ve skutečnosti nemusí provádět pouhý součet, ale například i součin:
ADD r0, r1, r2 r0:=r1+r2 (běžný součet bez nastavení příznaků) ADDEQ r0, r1, r2 if (Z==1) r0:=r1+r2 ADDS r0, r1, r2 r0:=r1+r2 a nastav příznaky N, V, Z, C ADDEQS r0, r1, r2 jako ADDEQ + nastavení příznaků ADD r0, r1, r1, LSL#2 r0:=r1*5
6. Aritmetické a logické instrukce podrobněji
Mezi základní aritmetické instrukce patří samozřejmě instrukce součtu a rozdílu. U instrukcí rozdílu je zajímavé, že existují ve dvou variantách podle toho, zda se odečítá první operand od druhého nebo naopak. Motivace je zřejmá – pro oba operandy existují odlišná pravidla:
# | Instrukce | Význam |
---|---|---|
1 | ADD | operand1+operand2 |
2 | ADC | operand1+operand2+carry |
3 | SUB | operand1-operand2 |
4 | SBC | operand1-operand2+carry-1 |
5 | RSB | operand2-operand1 |
6 | RSC | operand2-operand1+carry-1 |
Další skupinou instrukcí jsou instrukce provádějící nějakou aritmetickou či logickou operaci. Ovšem výsledek této operace se nikam neuloží, pouze se nastaví příznakové bity (navíc se tyto bity nastaví vždy, není zde možnost volby bitu S):
# | Instrukce | Význam |
---|---|---|
1 | CMP | operand1-operand2 |
2 | CMN | operand1+operand2 (compare negative) |
3 | TST | operand1 and operand2 |
4 | TEQ | operand1 xor operand2 |
Nesmíme samozřejmě zapomenout ani na logické operace prováděné bit po bitu:
# | Instrukce | Význam |
---|---|---|
1 | AND | operand1 and operand2 |
2 | ORR | operand1 or operand2 |
3 | EOR | operand1 xor operand2 |
4 | BIC | operand1 and not operand2 |
Na závěr této kapitoly si ještě uvedeme seznam operací prováděných barrel shifterem se druhým operandem vstupujícím do aritmeticko-logické jednotky. Nejedná se o samostatné instrukce, ale o modifikátory zapisované za vlastní ALU instrukci (viz příklad uvedený v šesté kapitole):
# | Instrukce | Význam |
---|---|---|
1 | ASR | aritmetický posun doprava (kopie nejvyššího bitu) |
2 | LSL | logický posun doleva (zprava se nasouvá nula) |
3 | LSR | logický posun doprava (zleva se nasouvá nula) |
4 | ROR | rotace doprava, nejnižší bit se kopíruje do C |
5 | RRX | rotace doprava přes C (rotuje tedy 33 bitů) |
Trošku stranou stojí instrukce využívající násobičku (tyto instrukce mají i jiný formát). Instrukcí tohoto typu existuje větší množství a záleží na konkrétním typu jádra, které z instrukcí jsou podporovány:
# | Instrukce | Význam |
---|---|---|
1 | MUL | násobení 32×32 bitů : 32bitů |
2 | MLA | násobení + součet |
3 | UMULL | násobení 32×32 bitů : 64bitů unsigned |
4 | UMLAL | násobení + součet |
5 | SMULL | násobení 32×32 bitů : 64bitů signed |
6 | SMLAL | násobení + součet |
Navíc ještě existují instrukce SMULxx pro násobení 16bitových slov atd.
7. Problematika načtení 32bitové konstanty do registrů
Již několikrát jsme se zmínili o tom, že kvůli konstantní šířce všech instrukcí může být problematické uložení konstanty do některého pracovního registru. Problém je to logický a vlastně shodný pro všechny „klasické“ RISCové mikroprocesory: šířka pracovních registrů je 32 bitů a současně je šířka instrukcí taktéž 32 bitů, tudíž není možné, aby se v instrukci vedle operačního kódu nacházela i 32 bitová konstanta. Tvůrci dalších RISCových mikroprocesorů se s touto problematikou snažili vypořádat různým způsobem, například zavedli speciální instrukci pro naplnění horních šestnácti bitů registru, zatímco pro naplnění spodních šestnácti bitů bylo možné použít například instrukci ADD s konstantou a nulovým registrem R0 (zhruba takovýmto způsobem je tato problematika řešena na mikroprocesorech MIPS). U mikroprocesorů ARM se zdá, že jeho konstruktéři nechtěli „obětovat“ další tranzistory na podobné typy instrukcí, takže se pro načtení konstanty používá dvojice instrukcí se stejným formátem, jako mají ostatní aritmetické a logické instrukce:
# | Instrukce | Význam |
---|---|---|
1 | MOV | načtení osmibitové konstanty 0..255 |
2 | MVN | načtení osmibitové konstanty s negací –1..-256 |
To je samozřejmě pro mnoho účelů zcela nedostatečné, ovšem ve skutečnosti je možné tuto konstantu pomocí barrel shifteru posunout o sudý počet míst 0, 2, 4, .. 30, takže se ve skutečnosti celkový počet konstant zvyšuje na hodnotu 8192 z celkového množství kombinací 232. Aby programátoři mohli relativně snadno načíst libovolnou konstantu do zvoleného registru, nabízí většina assemblerů pro mikroprocesory ARM pseudoinstrukci LDR ve tvaru:
LDR Rx, =konstanta
Podle hodnoty použité konstanty se tato instrukce buď převede na instrukci MOV, alternativně MVN, nebo na instrukci LDR načítající konstantu uloženou někde v programovém kódu (například za tělem subrutiny, kde lze vyhradit prostor pomocí direktivy LTORG). Tato konstanta je potom adresována relativně k hodnotě registru PC, pouze je nutné dát pozor na to, že offset pro relativní adresování má pouze dvanáct bitů, takže tato konstanta nemůže být uložena příliš „daleko“ (na to ostatně upozorní assembler).
8. Instrukční sada Thumb
Již v předminulé části tohoto seriálu jsme si řekli, že moderní verze mikroprocesorů ARM kromě původní instrukční sady podporují i instrukční sadu nazvanou Thumb. Tato instrukční sada byla zavedena v jádru ARMv4T a posléze byla rozšířena na Thumb2 v jádru ARMv6T2. V případě Thumb se jedná o instrukční sadu obsahující podmnožinu instrukcí vybranou na základě analýzy strojových programů generovaných překladači jazyků C a C++. Dále se v této instrukční sadě již neobjevují bity určené pro podmíněné provádění instrukcí, což znamená, že je nutné se vrátit k použití podmíněných skoků. Ostatně i spolukonstruktérka procesorů ARM Sophie Wilson se sama vyjádřila v tom smyslu, že podmínkové kódy měly v minulosti svůj velký význam a splnily svoji roli, ovšem v embedded systémech a taktéž na strojích s velmi rychlými CPU a pomalými DRAM se již jejich význam poněkud snížil a důležitějším faktorem se stává hustota kódu.
Obecně je možné říci, že se instrukce Thumb relativně jednoduchým způsobem transformují na původní instrukce ARM, ovšem zpětně to neplatí, tj. existují takové instrukce ARM, které nelze převést na jedinou instrukci Thumb (to je však logické, vždyť z původních 232 kombinací se v Thumb používá jen 216 kombinací). Na druhou stranu se však délka všech instrukcí mohla zkrátit na šestnáct bitů, což dovoluje dosažení větší „hustoty“ kódu.
Programátorům, kteří mají znalosti instrukční sady jiných typů mikroprocesorů, se bude instrukční sada Thumb zdát blízká, protože se namísto tříadresových instrukcí s podmínkovými kódy, S-bitem a případnou rotací:
ADDEQ r0, r1, r1, LSL#2
setkají s instrukcemi jednoduššími, tj. například s „běžným“ součtem ADD, nepodmíněným skokem B (s dvanáctibitovým offsetem), podmíněným skokem BEQ (jen s devítibitovým offsetem) či se samostatnou instrukcí logického posunu LSL. Navíc se kvůli užšímu instrukčnímu slovu muselo zavést větší množství formátů bitových polí, takže zatímco v případě původní instrukční sady používala většina instrukcí jeden z pěti formátů, je u instrukční sady Thumb použito celkem devatenáct různých formátů, což však naprostou většinu programátorů nemusí trápit (pokud se tedy nezabývají studiem vygenerovaných binárních souborů).
Jak je tomu s proklamovanou větší hustotou kódu v reálných aplikacích si řekneme v navazující části tohoto seriálu.
9. Odkazy na Internetu
- Introduction to ARM thumb
http://www.eetimes.com/discussion/other/4024632/Introduction-to-ARM-thumb - ARM, Thumb, and ThumbEE instruction sets
http://www.keil.com/support/man/docs/armasm/armasm_CEGBEIJB.htm - An Introduction to ARM Assembly Language
http://dev.emcelettronica.com/introduction-to-arm-assembly-language - Processors – ARM
http://www.arm.com/products/processors/index.php - The ARM Instruction Set
http://simplemachines.it/doc/arm_inst.pdf - ARM Architecture (Wikipedia)
http://en.wikipedia.org/wiki/ARM_architecture - BBC BASIC
http://www.bbcbasic.co.uk/bbcbasic.html - BBC BASIC
http://mdfs.net/Software/BBCBasic/ - BBC BASIC (Z80) for the ZX Spectrum
http://mdfs.net/Software/BBCBasic/Spectrum/ - BBC BASIC (Wikipedia CZ)
http://en.wikipedia.org/wiki/BBC_BASIC - MIPS-3D® ASE
http://www.mips.com/products/architectures/mips-3d-ase/ - An introduction to SPARC's SIMD offerings
http://mikeburrell.wordpress.com/2007/12/14/an-introduction-to-sparcs-simd-offerings/ - MIPS64TM Architecture for Programmers Volume IV-c: The MIPS-3DTM Application-Specific Extension to the MIPS64TM
http://www.weblearn.hs-bremen.de/risse/RST/docs/MIPS/MD00099–2B-MIPS3D64-AFP-01.11.pdf - Visual Instruction Set
http://www.enotes.com/topic/Visual_Instruction_Set - NEON
http://www.arm.com/products/processors/technologies/neon.php - Architecture and Implementation of the ARM Cortex-A8 Microprocessor
http://www.design-reuse.com/articles/11580/architecture-and-implementation-of-the-arm-cortex-a8-microprocessor.html - Multimedia Acceleration eXtensions (Wikipedia)
http://en.wikipedia.org/wiki/Multimedia_Acceleration_eXtensions - AltiVec (Wikipedia)
http://en.wikipedia.org/wiki/AltiVec - Visual Instruction Set (Wikipedia)
http://en.wikipedia.org/wiki/Visual_Instruction_Set - MAJC (Wikipedia)
http://en.wikipedia.org/wiki/MAJC - MDMX (Wikipedia)
http://en.wikipedia.org/wiki/MDMX - MIPS Multiply Unit
http://programmedlessons.org/AssemblyTutorial/Chapter-14/ass14_3.html - Silicon Graphics Introduces Enhanced MIPS Architecture
http://bwrc.eecs.berkeley.edu/CIC/otherpr/enhanced_mips.html - MIPS-3D (Wikipedia)
http://en.wikipedia.org/wiki/MIPS-3D - MIPS Technologies, Inc. announces new MIPS-3D technology to provide silicon-efficient 3D graphics acceleration
http://www.design-reuse.com/news/2057/mips-mips-3d-technology-silicon-efficient-3d-graphics-acceleration.html - MIPS-3D Built-in Function (gcc.gnu.org)
http://gcc.gnu.org/onlinedocs/gcc/MIPS_002d3D-Built_002din-Functions.html - Baha Guclu Dundar:
Intel MMX, SSE, SSE2, SSE3/SSSE3/SSE4 Architectures - SSE (Streaming SIMD Extentions)
http://www.songho.ca/misc/sse/sse.html - Timothy A. Chagnon: SSE and SSE2
http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf - Intel corporation: Extending the Worldr's Most Popular Processor Architecture
http://download.intel.com/technology/architecture/new-instructions-paper.pdf - SIMD architectures:
http://arstechnica.com/old/content/2000/03/simd.ars/ - Intel MMXTM Technology Overview
Intel corporation, 1996 - MultiMedia eXtensions
http://softpixel.com/~cwright/programming/simd/mmx.phpi - AMD K5 („K5“ / „5k86“)
http://www.pcguide.com/ref/cpu/fam/g5K5-c.html - Sixth Generation Processors
http://www.pcguide.com/ref/cpu/fam/g6.htm - Great Microprocessors of the Past and Present
http://www.cpushack.com/CPU/cpu1.html - Very long instruction word (Wikipedia)
http://en.wikipedia.org/wiki/Very_long_instruction_word - Tour of the Black Holes of Computing!: Floating Point
http://www.cs.hmc.edu/~geoff/classes/hmc.cs105…/slides/class02_floats.ppt - 3Dnow! Technology Manual
AMD Inc., 2000 - CPU design (Wikipedia)
http://en.wikipedia.org/wiki/CPU_design - Control unit (Wikipedia)
http://en.wikipedia.org/wiki/Control_unit - Cray History
http://www.cray.com/About/History.aspx?404;http://www.cray.com:80/about_cray/history.html - Cray Historical Timeline
http://www.cray.com/Assets/PDF/about/CrayTimeline.pdf - Computer Speed Claims 1980 to 1996
http://homepage.virgin.net/roy.longbottom/mips.htm - Superpočítače Cray
http://www.root.cz/clanky/superpocitace-cray/ - Superpočítače Cray (druhá část)
http://www.root.cz/clanky/superpocitace-cray-druha-cast/ - Superpočítače Cray (třetí část)
http://www.root.cz/clanky/superpocitace-cray-treti-cast/ - Superpočítače Cray (čtvrtá část)
http://www.root.cz/clanky/superpocitace-cray-ctvrta-cast/ - Superpočítače Cray (pátá část): architektura Cray X-MP
http://www.root.cz/clanky/superpocitace-cray-pata-cast-architektura-pocitace-cray-x-mp-a-jeho-pouziti-ve-filmovem-prumyslu/