Zde se nachazi spravna reseni testu z dnes jiz historickeho predmetu 36SOJ, vcetne zduvodneni. Ano, testy nebyly lehke, ale lehky test by pro mne mel pramalou vypovidaci hodnotu. Pokud mate pres ta vsechna zduvodneni stale neodbytny pocit, ze je nektera odpoved nespravna, klidne se zeptejte. TEST 1-A -------- 1) Procesor i8086 je sestnactibitovy, protoze: b) - umi najednou pracovat s sestnactibitovym slovem. Sirka datove sbernice nehraje roli (napr. i80386SX20 je 32-bitovy procesor a ma sestnactibitovy databus), offset adresy take ne (Z-80 je osmibitovy a adresuje 16-bitove), segmentove registry tez nehraji roli (urcuji jen pristupny adresovy prostor a zpracovani dat senijak netykaji). Nekteri studenti znaji z prumyslovek poveru, ze bitovost procesoru je dana sirkou jeho datove sbernice, coz evidentne neni pravda, za to body nedavejte ;). 2) Instrukce i8086 MOV AL,[ES:BX] vykona operaci: c) - AL <- bajt z fyzicke adresy (16*ES+BX) and 0FFFFFh. And zohlednuje zrcadlici chovani i8086, ktery ma pouze 20-bitovou adresovou sbernici. Toto zrcadleni byva jeste i pro nastupce i8086 stale platne diky A20gate hardwarove uprave (vypinatelne). Vzhledem k tomu, ze je uveden vyslovne i8086, jsou zbyle odpovedi spatne, ale studenti se radi hadaji, i kdyz slyseli nejmene 5x, ze i8086 ma dvacetibitovou sbernici, a oadresuje tak pouze 1M pameti ;). 3) Program ve formatu *.com neni mozne v zadnem pripade ukoncit pomoci: d) - RET far. Pomoci MOV AX,4C00h; INT 21h nebo INT 20h resp. prostym RET near ukoncujeme *.com naprosto bezne. RET far by sel pouzit pouze v umelem pripade, kdy by navrat smeroval na INT 20h (pocatek PSP), nebo na obsluhu ukonceni DOSu, nebo podobne chutovky, ale to je filozoficky problem univerzality instrukce RET, pouzite misto skoku. Zde takova praktika nedava dobry smysl, ale pokud si nekdo takovou odpoved obhaji, budiz. 4) Instrukce LODSB provede AL <- [DS:SI], a registr SI nasledne: c) - zvetsi nebo zmensi o 1, podle obsahu FLAGS. Ve FLAGS je typ operace urcen jedinym bitem, proto jsou zbyle odpovedi spatne, tady neni moc o cem diskutovat. ;) 5) Program XOR CX,CX; MOV DL,'*'; MOV AH,2; LABEL: INT 21h; LOOP LABEL vytiskne: c) - 65536 hvezdicek. Vynulovane CX se po prvnim pruchodu zdekrementuje na 0FFFFh, a tedy provede se jeste 65535, dohromady tedy celkem 65536 tisku znaku. Zbyle odpovedi jsou spatne, neni tu co resit. ;) TEST 1-B -------- 1) Procesor i8086 v PC pristupuje k periferiim pomoci: d) - zapisu a cteni z V/V nebo pametoveho prostoru. Mechanismus DMA se totiz tyka jen pameti a komunikujici periferie, obchazi procesor, a proto je tato odpoved chybna. Zbyle odpovedi jsou neuplne. Pokud nekdo zakrouzkuje b) a c), tak neposlouchal, ze pravidlem je jen 1 korektni odpoved, ale uznat to urcite pujde ;). 2) Procesor i8086 ma takto nastavene registry: DS=2000h, ES=0FFFFh, BX=11h. Pak instrukce MOV AL,[ES:BX] nahraje do AL bajt z fyzicke adresy: b) - 000001h. Jde o spodnich dvacet bitu z vyrazu 16*ES+BX, protoze je uveden i8086. Zbyle odpovedi jsou chybne, jde holt o i8086, prapuvodce limitaci realneho rezimu. ;) 3) Program ve formatu *.exe se kdykoli korektne ukonci pouze pouzitim: a) - MOV AX,4C00h; INT 21h. Toto je DOSovske volani na ukonceni procesu, ktere nevyzaduje asi CS=PSP, ani nuly na aktualni polozce zasobniku (spousteni *.exe totiz nezarucuje ani jedno). Samozrejme, opet je mozne pouzit return jako skok na misto, kde se ukonceni jiz korektne provede, ale na to se otazka nepta, ostatne tyto praktiky lze pouzit jen ve specialnich pripadech, ne kdykoliv, takze dohady by zde byt nemely ;) 4) Pouziti instrukci RET far nebo RET near na konci podprogramu: a) - je vzdy dano typem CALLu, jakym podprogram volame. Zde lze opet zasobnikove filozofovat, co s podprogramem, ktery neCALLujeme, ale napr. do nej vskocime, nebo mu umyslne pripravime nejakou navratovou adresu, etc. Pokud si student tyhle extraburty obhaji, ma je mit, je ale potreba rozlisit mezi koderem, co se chce blysknout a nekym, kdo si plete far/near typy volani. ;) 5) Program MOV DL,'*'; MOV AH,2; STC; LABEL: INT 21h; JC LABEL vytiskne: a) - nekonecno hvezdicek, protoze se v cyklu nikdy nevynuluje CARRY. Instrukce INT totiz FLAGS pri volani uklada, a pri navratu zase obnovuje. Pokud DOSova funkce nevraci zadnou navratovou hodnotu nebo priznak (coz dokumentovana 02H zcela jiste nevraci), zustavaji tak FLAGS nativne zachovany a cyklus se nikdy nezastavi. Zbyle odpovedi jsou chybne, protoze CARRY je zpocatku definovano a volani sluzby ho jiz nijak neovlivnuje. Zde take neni co resit. TEST 2-A -------- 1) I8086 ma ES=0FF00h, DS=0FE00h a SI=2000h. Pak LODSB: c) - nahraje bajt z fyzicke adresy 000000h. Jde o hodnotu 16*DS+SI, oriznutou na i8086kovych 20 bitu (pripomenuti z minuleho testu). Zrcadleni kolem 1M je dulezite, viz tahanice kolem HMA, spravy A20ky, a nastavovani vektoru preruseni BIOSem, proto neodpoustet ;). 2) V registru AX mame bezznamenkove kladne cislo 0 .. 65535. Celociselne deleni dvema provedeme: b) - instrukci SHR AX,1. Instrukce RCR by nam totiz do vysledku zavedla CARRY, jehoz hodnotu nikdo nespecifikoval, a instrukce SAR by zase ponechala nastaveni bitu 15. Zbyle odpovedi jsou tedy spatne. ;) 3) Bezznamenkove kladne cislo v registru AX 0..65535 chceme vynasobit 0.75 a ziskat celociselnou cast vysledku. Tuto operaci: c) - provedeme naprilad instrukcemi MOV CX,49152; MUL CX; MOV AX,DX. Desetinne cislo do registru CX nahravat samozrejme nelze, delit konstantou i8086 take neumi, a bezhlave nasazovani FPU na takto trivialni ukony neni nutne (a je neefektivni). Toto reseni povazuje 0.75 za zlomek, tedy 3/4, coz je totez jako 49152/65535. Deleni 65536 je zrealizovano jednoduse odebranim vyssiho slova vysledku. Zbyle odpovedi jsou tedy zcela spatne. ;) 4) V registru AL je nejake bezznamenkove cislo vetsi nez 200. Chceme toto cislo jedinou instrukci zmensit o 5 a nastavit CARRY. Pak pouzijeme: c) - instrukci ADD AL,251. Odcitani petky od tak velkeho cisla by se CARRY nikdy nenastavilo, proto pouzijeme scitani s cislem opacnym (v doplnkovem kodu). Zbyle odpovedi jsou zcela spatne. ;) 5) Program PUSH AX; XOR AL,AL; ADD AL,20h; OUT 20h,AL; POP AX; RETI pro obsluhu i8086 hardwaroveho preruseni IRQ 0 je chybny, protoze: a) - obsahuje neexistujici instrukci. Instrukce se jmenuje IRET, nikoli RETI. Kdo pouziva NASM a takto se splete, nema sanci chybu odhalit, protoze NASm bude zkomolene jmeno instrukce povazovat za navesti, a instrukce tak v tichosti z kodu vypadne. Jinak, program si FLAGS neschovava, protoze to realizuje sam mechanismus INTu. Nenahrava si registr DS, ale ani ho nijak nepouziva, takze to nevadi. A instrukce PUSH/POP jsou v prerusovacich rutinach vic nez potrebne, proto jsou zbyle odpovedi zcela chybne. ;) TEST 2-B -------- 1) I8086 ma ES=0FF00h, DS=0FE00h a DI=2000h. Pak STOSB: d) - ulozi byte na fyzickou adresu 001000h. Jde o evergreen spodnich 20bitu vyrazu 16*ES+DI, kvuli vyslovne uvedene i8086 jsou zbyle odpovedi spatne. ;) 2) V registru AX mame cislo v doplnkovem kodu -32768 .. 32767. Celociselne deleni AX dvema provedeme: d) - zadna z uvedenych instrukci nedeli celociselne cislo v doplnkovem kodu dvema. Skutecne, deleni cisel v doplnkovem kodu nelze realizovat rotacemi ani shifty. SHR nam nezachovava znamenkovy bit, RCR vklada do vysledku nedefinovane CARRY, a SAR AX,1 nedeli cislo presne. -1/2 ma byt 0, nicmene SAR AX,1 udela z 0FFFFh opet 0FFFFh, tedy -1. Shiftem lze tedy delit pouze priblizne, s chybou -1 pro vsechny liche delence. Je to dano tim, ze zatimco shift je symetricky podel nuly, doplnkovy kod ne. Zbyle odpovedi jsou tedy spatne, pokud ale nekdo zatrhne SAR AX,1, a bude si te nepresnosti vedom, lze mu odpoved uznat. ;) 3) Bezznamenkove cislo v registru AX 0..65535 chceme vynasobit 0.25 a ziskat celociselnou cast vysledku. Tuto operaci: c) - provedeme napriklad instrukcemi MOV CL,2; SHR AX,CL. Nasobeni 0.25 je totiz deleni 4mi, a tedy shift vpravo o dva. Delit konstantou i8086 neumi, do registru desetinne cislo nahrat take nelze, a FPU neni na takovouhle trivialitu nutne. Zbyle odpovedi jsou tedy spatne. ;) 4) V registru AL je bezznamenkove cislo mensi nez 50. Chceme jedinou instrukci toto cislo zvetsit o 1 a nastavit CARRY. Pak pouzijeme: c) - instrukci SUB AL,255. Protoze pricitanim bychom CARRY nikdy nedosahli, odecteme opacnou hodnotu druheho scitance. Instrukce INC pak s flagem CF nijak nehyba, ADC by nam do vysledku zaneslo hodnotu minuleho CARRY a aktualni ani spravne nenastavilo. Zbyle odpovedi jsou tedy spatne. ;) 5) Program PUSH AX; XOR AL,AL; OUT 20h,20h; POP AX; IRET pro obsluhu preruseni IRQ 0 je chybny, protoze: d) - obsahuje neexistujici instrukci. Outovat konstantu na i8086 nelze. PUSH a POP pouzivat samozreme muzeme, FLAGS uschova samotny INT, a registr DS nijak nepouzivame, tedy zbyle odpovedi jsou zcela chybne. ;) TEST 3-A -------- 1) VideoRAM textoveho rezimu VGA 80x25 znaku (03h): c) - zacina na fyzicke adrese 0B8000h a je velka 4000 B. Kazdy znak totiz obsazuje 2 byty ve videoram (ASCII a atribut), a je jich celkem 80*25. Pocatek je dany odedavna konstrukci CGA adapteru, kde se tento mod poprve objevil. Zbyle odpovedi jsou tedy spatne. ;) 2) Na fyzickou adresu 0B8000h zapiseme slovo 3031h. V textovem rezimu (03h) uvidime na obrazovce: a) - cernou jednicku na svetlemodrem podkladu. Nizsi byte 31h totiz obsadi ASCII kod, tedy '1', a vyssi 30h definuje jeho atribut (tedy normalne green-blue -> cyan paper, cerny inkoust). Ostatni odpovedi jsou zcela spatne uz kvuli te jednicce, to pokud by nekdo nahodou argumentoval zmenenymi atributovymi registry. ;) 3) Pojem stinova videoRAM znamena: b) - oblast v konvencni RAM velikou jako videoram, kde si nanecisto pripravujeme graficka data. VideoROM shadowing je neco zcela jineho (kopie pomale 150ns EPROM v daleko rychlejsi zastinene RAM), cernobila VRAM tez neni "stinova", a intervence BIOSu do prekreslovani VRAM je leta tradovany nesmysl. Zbyle odpovedi jsou tedy spatne. ;) 4) Nastavena paleta pro rezim 320x200 (13h) dovoluje zobrazit: c) - 256 barev z 262144 moznych. Paleta totiz obsahuje prave 256 polozek, kde kazda je urcena jako 3 byty, definujici jeji RGB slozky. Z kazdeho bytu se bere ale jen spodnich 6 bitu, coz dava (2^6)^3 kombinaci. Zbyle odpovedi jsou spatne. ;) 5) Program MOV AX,0A000h; MOV ES,AX; MOV CX,320*200; XOR DI,DI; REP; STOSW: v grafickem rezimu 320x200 (13h): c) - neni napsan korektne, protoze zapisuje mimo videoRAM. Je totiz pouzito STOSW, a ne STOSB. Proto nemaze obrazovku dle polozky 0 jako by platlo pro STOSB, natoz podle polozky 160 (mame little endian). STOSW v principu sice vytvori svisle prouzky, ale predevsim prepiseme oblast za koncem VRAM, coz konci casto poskozenim ulozenych dat, zatuhnutim systemu, nebo padem pocitace. Kdo bude mit stesti, a takto chybny program mu nahodou nespadne, uvidi zleva prouzky barvy 0 a 160 (little endian), cimz je pojistena chybnost odpovedi b), se kterou by nekdo mohl argumentovat. ;) TEST 3-B -------- 1) Videoram grafickeho rezmu 320x200 bodu (13h): c) - zacina na fyzicke adrese 0A0000h a je velka 64000 B. Kazdy pixel totiz zabira 1B, a je jich celkem 320*200. Pocatek je urcen architekturou 256k VGA adapteru, kde se tento rezim poprve objevil. Zde neni co resit ;). 2) Na fyzickou adresu 0A000h zapiseme slovo 0100h. V rezimu 320x200 (13h) uvidime na obrazovce: d) - dva sousedici body s barvami dle polozek palety 0 a 1. Barva je dana vzdy obsahem palety, a z hodnoty indexu na ni nelze nijak usuzovat, proto jsou zbyle odpovedi chybne. ;) 3) Pojem synchronizace s paprskem znamena: c) - zabraneni vykresleni neuplne napocitaneho snimku pomoci znalosti o poloze paprsku monitoru. Vypinanim jasoveho signalu bychom vse jen zhorsili, zrovnatak podkreslovanim aktivniho paprsku novymi daty. Realny cas pak v PC bezi nezavisle na hodinach graficke karty, a proto zde nemuze byt pouzit. Zbyle odpovedi jsou tedy chybne. ;) 4) Paleta rezimu 320x200 definuje kazdou barvu pomoci: a) - slozek RGB, kde je kazda barva urcena 6 bitovym jasem. Graficky hardware v PC pouziva zasadne RGB model, kazda slozka je urcena 1 bytem, a VGA z nej uvazovalo pouze spodnich 6 bitu. Zbyle odpovedi jsou chybne. 5) Program MOV AX,0B800h; MOV ES,AX; MOV CX,80*25; XOR DI,DI; REP; STOSB v textovem rezimu 80x25 (03h): b) - nastavi horni polovinu obrazovky na cernou barvu. Uklada totiz pomoci STOSB, tedy jeden byte, a tak zaplni jen polovinu ze vsech dvojic [ASCII,atribut] nulami a tim vymaze horni polovinu screenu. Zbyle odpovedi jsou spatne. ;) TEST 4-A -------- 1) Procesor i8086 neprimo explicitne adresuje: c) - pouze pomoci registru BX, SI, DI a BP. Adresace pomoci SP je totiz implicitni (instrukce ji maji primo ve svem opcode), a zbyle odpovedi jsou tez chybne/neuplne. ;) 2) V registru AX mame bezznamenkove kladne cislo 0 .. 65535. Celociselne deleni dvema provedeme: b) - instrukci SHR AX,1. Instrukce RCR by nam do vysledku zavedla CARRY, jehoz hodnotu nikdo nespecifikoval, instrukce SAR by zase ponechala nastaveny bit 15. Zbyle odpovedi jsou tedy spatne. 3) Nastavena paleta pro rezim 320x200 (13h) dovoluje zobrazit: c) - 256 barev z 262144 moznych. Paleta totiz obsahuje 256 polozek, kde kazda je urcena jako 3 byty, definujici jeji RGB. Z kazdeho bytu se bere jen spodnich 6 bitu, coz dava (2^6)^3 kombinaci. Zbyle odpovedi jsou spatne. 4) Bezznamenkove kladne cislo v registru AX 0..65535 chceme vynasobit 0.75 a ziskat celociselnou cast vysledku. Tuto operaci: c) - provedeme naprilad instrukcemi MOV CX,49152; MUL CX; MOV AX,DX. Desetinne cislo do registru CX nahravat nelze, delit konstantou i8086 neumi, a bezhlave nasazovani FPU na takto trivialni ukony neni nutne (a je neefektivni). Toto reseni povazuje 0.75 za zlomek, tedy 3/4, coz je totez jako 49152/65535. Deleni 65536 je zrealizovano odebranim vyssiho slova vysledku. Zbyle odpovedi jsou tedy zcela spatne. ;) 5) Program PUSH AX; MOV DI,FLAG; MOV AL,20h; MOV [CS:DI],AL; OUT 20h,AL; POP AX; IRET pro obsluhu preruseni IRQ 0 je chybny, protoze: d) - nevraci hodnoty v registrech do puvodniho stavu pred prerusenim. Vsecny instrukce existuji, segment DS nikde nepouzivame, a registr CS nam nahral sam INTovy mechanismus podle hodnoty z prerusovaciho vektoru. Zbyle odpovedi jsou tedy spatne. ;) TEST 4-B -------- 1) Procesor i8086 ma takto nastavene registry: DS=2000h, ES=0FFFFh, BX=11h. Pak instrukce MOV AL,[ES:BX] nahraje do AL bajt z fyzicke adresy: b) - 000001h. Jde o spodnich dvacet bitu z vyrazu 16*ES+BX, protoze je uveden i8086. Zbyle odpovedi jsou chybne, jde holt o i8086, prapuvodce limitaci realneho rezimu. ;) 2) Pouziti instrukci RET far nebo RET near na konci podprogramu: a) - je vzdy dano typem CALLu, jakym podprogram volame. Zde lze opet zasobnikove filozofovat, co s podprogramem, ktery neCALLujeme, ale napr. do nej vskocime, nebo mu umyslne pripravime nejakou navratovou adresu, etc. Pokud si student tyhle extraburty obhaji, ma je mit, je potreba rozlisit mezi koderem, co se chce blysknout a nekym, kdo si plete far/near typy volani. ;) 3) V registru AL je nejake bezznamenkove cislo vetsi nez 200. Chceme toto cislo jedinou instrukci zmensit o 5 a nastavit CARRY. Pak pouzijeme: c) - instrukci ADD AL,251. Odcitani petky od tak velkeho cisla by carry nikdy nenastavilo, proto pouzijeme scitani s cislem opacnym (v doplnkovem kodu). Zbyle odpovedi jsou zcela spatne. 4) V registru AX mame cislo v doplnkovem kodu -32768 .. 32767. Celociselne deleni AX dvema provedeme: d) - zadna z uvedenych instrukci nedeli celociselne cislo v doplnkovem kodu dvema. Skutecne, deleni cisel v doplnkovem kodu nelze realizovat rotacemi ani shifty. SHR nezachovava znamenkovy bit, RCR vklada do vysledku nedefinovane CARRY, a SAR AX,1 nedeli presne. -1:2 = 0, nicmene SAR AX,1 udela z 0FFFFh opet 0FFFFh, tedy -1. Shiftem lze tedy delit pouze priblizne, s chybou. Je to dano tim, ze zatimco shift je symetricky podel nuly, doplnkovy kod ne. Zbyle odpovedi jsou tedy spatne, pokud ale nekdo zatrhne SAR AX,1, a bude si nepresnosti vedom, lze mu odpoved uznat. 5) Program PUSH AX; MOV AX,20h; OR [SI],AH; OUT 20h,AX; POP AX; IRET pro obsluhu IRQ 0 je chybny, protoze: b) - nespravne odhlasuje preruseni radici. Sice adresuje registrem SI, ktery ukazuje buhvikam, ale na dane misto v pameti oruje AH, tedy nulu, coz nam v realnem modu nevadi. Proto nam nevadi ani nenahravani registru DS. Vsechny instrukce existuji, nicmene outujeme do radice dvoubytovou hodnotu misto jednobytove, takze si prepiseme i masku preruseni, coz je fatalni chyba. Pokud nekdo bude trvat na chybovosti kvuli nenastaveni DS:SI, musi dokazat, ze existuje pripad, kdy by orovani nuly na urcitou adresu v reanem modu na i8086 vadilo, pak mu lze odpoved uznat. ;) TEST 5-A -------- 1) Pristup OUT DX,AL; INC DX; MOV AL,AH; OUT DX,AL: c) - lze nahradit pomoci OUT DX,AX s vyjimkou urcitych I/O adres a navazujicich pristupu. Kdykoli toto provest nelze - napr. datovy port IDE zarizeni obsazuje bytovou adresu, nicmene nalezneme na ni izolovane 16-bitove slovo (jeho vyssi byte tedy neni k mani o port vyse). Take nekdy vadi paralelismus zapisu, pokud hardware nedokaze zapis slova zpetne rozbit do dvou sekvencnich zapisu bytu, napr. DMA byva na toto hakliva, a zapis slova do dvou registru naraz nezvlada (chipsety Triton). Podobnych prikladu lze najit mnohem vice, a jasou duvodem, proc plati odpoved c). ;) 2) Vazba programu na realny cas se na PC provadi: d) - pomoci preruseni IRQ 0 od prvniho kanalu obvodu citace-casovace 9253-5. Frekvence monitoru byva ruzna, a nelze ji proto pouzit, strukturovanim kodu na takty nelze od dob cachovani vycasovat jiz temer nic (a od dob SDRAM ani pomoci vyplachovani cache skoky), opakovane nacitani RTC je zdlouhave, a poskytuje nam cas v nevhodnem BCD formatu. Proto jsou zbyle odpovedi chybne. ;) 3) AX = cislo N, CF = neznamy bit. Chceme li zachovat CF i AX a nastavit ZF podle N, tak: c) - pouzijeme instrukci INC AX; DEC AX. CMP a AND totiz nezachova CF, a pushovanim FLAGS bychom posleze obnovili zpet i puvodni ZF. Jina odpoved je proto chybna. ;) 4) Nejrychlejsi zapis do videoram provedeme: a) - instrukci STOSD. Uklada naraz cele dvojslovo, vcetne potrebneho posunu ciloveho pointeru. Pokud nekdo lpi na i8086, a bude tvrdit, ze MOV [BX],AX je pro i8086 nejrychlejsi, nema pravdu, v tom pripade by musel totiz zatrhnout STOSW, protoze MOV spolu s nutnou inkrementaci pointeru vychazi vice nez 12T, a STOSW melo na i8086 11T ;). Lidem co uvazovali v ramci i8086 tedu uznavame i STOSW a odpoved c). ;) 5) Program MOV CX,DELKA_POLE; MOV DI,OFFSET POLE; XOR AL,AL; LABEL: ADD AL,[DI]; SHR AL,1; STOSB; LOOP LABEL realizuje: c) - diskretni konvoluci pole s geometrickou radou o kvocientu 0.5. Skutecne. Cyklus totiz vykonava iteraci ve tvaru A[X]=(A[X] + A[X-1])/2 postupne nad vsemi polozkami. Rozepsanim snadno zjistime, ze kazde policko pak obsahuje polovinu sve nekdejsi hodnoty, ctvrtinu nekdejsi hodnoty minuleho policka, osminu z predminuleho, sestnactinu z predpredminuleho. V poli se tedy po vykonani cyklu objevi vysledek diskretni konvoluce jeho puvodniho obsahu s geometrickou radou o koeficientu 0.5. Takovehle smycky se s oblibou pouzivaji pro realizaci temer jakekoli IIR filtrace (vycisteni obrazu/samplu etc.). Je uzitecne je znat, driv nez se zacnou poustet nejake hruzy s kvadratickou slozitosti do humpolackeho FPU. Pro hodnoty >127 v poli by bylo dobre nahradit SHR AL,1 pomoci RCR AL,1. ;) TEST 5-B -------- 1) Instrukce OUT PNUM,AX provede: c) - zapis AL na I/O adresu PNUM, nasledne nebo soucasne zapis AH na I/O adresu PNUM+1. To odpovida klsicke koncepci pametoveho usporadani na PC, a zaroven zohlednuje fakt, ze nektery HW neumi prijmout zapisovane slovo, a vynuti si jeho rozdeleni na dva bytove zapisy (napr. neaktivoval na ISA signal /IOCS16). Zbyle odpovedi jsou tedy spatne. Toto je treba mit neustale na pameti pri programovani I/O, specialne u pristupu typu select register/acces data, jako ma napr. graficka karta nebo nektere FM syntezatory a dalsi. Zbyle odpovedi jsou chybne. 2) Pokud pouzivame vlastni obsluznou rutinu citace-casovace 8253-5, nemusime: b) - odmaskovat preruseni od citace-casovace, tedy IRQ 0. Toto preruseni mel totiz na 100% odmaskovano jiz DOS, ktery jeho vektor pouziva k mereni casu. Spravny beh DOSoveho casu zajistovat musime (jinak po dobu behu nasi aplikace cas v PC zamrzne a po navratu bude opozdeny), nastavovat delitel take, a odhlaseni preruseni radici je hola nutnost. Zbyle odpovedi jsou proto chybne. ;) 3) Po provedeni jedne z instrukci vzdy plati, ze ZF je negaci CF. Je to instrukce: d) - NEG AX. NEG totiz odecita obsah registru od nuly. Proto pouze nulovy registr (ZF=1) nevyvola CARRY, kdezto nenulovy registr (ZF=0) jej vyvola vzdy. Proto plati porad CF = !ZF. Tahle efektivni zamena flagu se obcas pri programovani hodi. Instrukce CMP AX,0000h pro AX=1 ma nulove jak ZF tak CF, AND AX,AX ma rovnez oba flagy nulove, AND AX,0FFFFh zrovnatak, zadani tedy nesplnuji. Proto jsou zbyle odpovedi chybne. ;) 4) Nejrychlejsi predavani parametru do podprogramu zrealizujeme: a) - predavanim parametru v registrech. Lze je pak primo pouzit k pokracovani vypoctu bez zdlouhaveho pristupu do pameti, nebo na zasobnik. Vyssi jazyky casto predavaji parametry prave zasobnikovou cestou, pripadne i pres vyhrazenou oblast v pameti, a proto jsou jiz z principu pomale, ve srovnani s takto optimalizovanym kodem. ;) 5) Program MOV CX,DELKA_POLE; MOV DI,OFFSET_POLE; MOV BL,5; LABEL: MUL BL; INC AX; STOSB; LOOP LABEL realizuje: b) - nastaveni bytoveho pole pseudonahodnymi hodnotami. Jde o podobu iterativniho vyrazu X[i] = (A * X[i-1] + B) mod C, tedy LCG generator pseudonahodnych cisel. Zde je A=5, B=1, C=256. Takovy generator ma periodu 256 hodnot, a tedy plnou rundu. Odpoved a) je proto chybne, protoze se algoritmus o puvodni obsah pole vubec nijak nestara. Exponencialni funkci zase vadi aditivni konstanta B, a o konvoluci take nejde, protoze ta take potrebuje znat puvodni obsah pole. Zbytek odpovedi je tedy spatne. ;)