m drugim ne zanyat; v sleduyushchem budet pokazano kak vypolnit' tu zhe zadachu, kogda komp'yuter zanyat drugoj rabotoj. Kogda komp'yuter nichem drugim ne zanyat, to mozhno vyvodit' melodiyu ili proizvodit' special'nye zvukovye effekty; kogda zhe komp'yuter zanyat drugoj rabotoj, to nel'zya proizvodit' zvukovye effekty. Sozdanie zvukovyh strok yavlyaetsya odnoj iz moshchnejshih vozmozhnos- tej, predostavlyaemyh Bejsikom. Postroenie zhe strok zvukov v as- semblere trebuet bol'shoj raboty. Mozhet byt' ispol'zovan lyuboj iz dvuh metodov generacii zvuka, predlozhennyh v [2.2.2] i [2.2.3]. Dlya oboih metodov nado prosto generirovat' odin ton v techenii zadannogo vremeni, zatem sleduyushchij i t.d. Kazhdaya zvukovaya stroka formiruetsya iz dvuh strok dannyh, odna iz kotoryh soderzhit chasto- ty posledovatel'nyh tonov, a drugaya hranit ih dlitel'nosti (pri uslovii, chto trebuyutsya raznye dlitel'nosti). Prodolzhitel'nost' zvuchaniya opredelyaetsya s ispol'zovaniem schetchika vremeni sutok BIOS [2.1.6]. Vysokij uroven'. Opreator Bejsika PLAY predostavlyaet bol'shie vozmozhnosti. Ope- rator soprovozhdaetsya strokoj not, peremeshannyh s informaciej o tom, kak eti noty dolzhny byt' ispolneny. Noty zapisyvayutsya bukva- mi A - G i posleduyushchimi znakami dlya diezov i bemolej. Diezy oboz- nachayutsya znakami # ili +, a bemoli minusom (-). Operatory PLAY "CC#D" i PLAY "CD-D" ekvivalentny, no nel'zya ispol'zovat' diezy i bemoli dlya oboznacheniya belyh klavish. Vtoroj sposob zadaniya not sostoit v vychislenii kodovogo nomera ot 0 do 84, prichem 0 soot- vetstvuet otsutstviyu zvuchaniya, a chisla ot 1 do 84 sootvetstvuyut 84 vozmozhnym notam semi oktav, nachinaya snizu. Nomeru dolzhna pred- shestvovat' bukva N: PLAY "N3N72N44". Dopustimyj diapazon - sem' oktav, vnutri kazhdoj mogut byt' noty ot C(do) do B(si). Oktavy pronumerovany ot 0 do 6 i nota do pervoj oktavy sootvetstvuet oktave 3. Tekushchaya oktava mozhet byt' izmenena v lyuboj moment, za schet vstavki v stroku bukvy O, za kotoroj sleduet nomer oktavy. Esli ne bylo nachal'noj ustanovki, to ispol'zuetsya oktava 4. Operator PLAY "O3CO4CO5CO6C" vyvodit noty do posledovatel'nyh oktav vverh. Drugoj sposob izmeneniya oktavy sostoit vo vklyuchenii v stroku simvolov > ili <, kotorye pereklyuchayut ton vverh i vniz na oktavu, sootvetstvenno. Operator PLAY "O3C>C>C>C" privodit k tomu zhe rezul'tatu, chto i predydushchij. Dlitel'nost' ispolneniya not takzhe mozhet byt' izmenena za schet vstavki kodovogo nomera, kotoromu predshestvuet bukva L. Vse pos- leduyushchie noty budut ispolnyat'sya s etoj dlitel'nost'yu do teh por, poka ne vstretitsya drugoj kod dliny. Kod - eto chislo ot 1 do 64, prichem 1 sootvetstvuet celoj note, a 64 - 1/64. Zapis' L4 soot- vetstvuet chetverti. Temp s kotorym ispolnyayutsya noty reguliruetsya kodom tempa, kotoryj sostoit iz bukvy T, za kotoroj sleduet chislo ot 32 do 255, dayushchee chislo chetvertej, ispolnyaemyh v minutu. Esli eti parametry ne ukazany, to po umolchaniyu beretsya dlitel'nost' L4 i temp 120. Dlya izmeneniya dlitel'nosti tol'ko odnoj noty nado pomestit' znachenie dliny posle noty i bez bukvy L. Operator PLAY "L4CDE16FG" ispolnit E kak shestnadcatuyu, a vse ostal'nye noty kak chetverti. Dlitel'nost' pauz beretsya takoj zhe, kak i dlitel'nost' not. Pomestite nomer ot 1 do 64 posle bukvy P dlya pauzy. P1 de- laet pauzu intervalom v celuyu, a P64 - v 1/64. Pomeshchenie tochki posle noty imeet tot zhe effekt, kakoj on imeet v obychnoj muzy- kal'noj notacii: dlitel'nost' noty uvelichivaetsya napolovinu. Vtoraya tochka prodolzhit dlitel'nost' eshche napolovinu. Po umolchaniyu noty igrayutsya 7/8 ukazannoj dlitel'nosti. CHtoby oni ispolnyalis' polnuyu dlitel'nost' (legato), pomestite v stroku ML. CHtoby oni ispolnyalis' 3/4 dlitel'nosti (stakkato), pomestite v stroku MS. CHtoby vernut'sya k normal'nomu stilyu nado ukazat' MN. Obychno, vsya prochaya deyatel'nost' programmy prekrashchaetsya do teh por, poka ne budet sygrana stroka. Dlya togo chtoby vypolnyalis' operatory, sleduyushchie za operatorom PLAY, a stroka ispolnyalas' v fonovom rezhime, pomestite v stroku MB. Dlya vosstanovleniya nor- mal'noj situacii napishite MF. Nakonec, operator PLAY pozvolyaet ispolnyat' podstroki vnutri dlinnoj stroki. Imeetsya v vidu, chto chast' ispolnyaemoj stroki mozhet byt' vvedena kak obychnaya strokovaya peremennaya, a zatem eta peremennaya mozhet byt' vyzvana iz stroki sformirovannoj v operato- re PLAY. Naprimer, esli S$ = "EEEEE", to v operatore PLAY "CDXS$;FG" nota E budet povtorena 5 raz. Otmetim, chto imeni pere- mennoj dolzhna predshestvovat' bukva X, a za imenem sledovat' tochka s zapyatoj (;). (Dlya kompiliruemyh programm primenyaetsya drugoj metod, ispol'zuyushchij peremennuyu VARPTR$ - detali sm. v rukovodstve po Bejsiku). V privedennom primere ispolnyaetsya znakomyj boj dedushkinyh chasov. V stroke snachala ustanavlivaetsya stil' ispolneniya legato, zatem temp i nachal'naya oktava, i, nakonec, chetyre noty, pauza, i te zhe samye chetyre noty, no v obratnom poryadke. Probely v stroke vklyucheny isklyuchitel'no dlya udobstva programmista - Bejsik ignori- ruet ih. 100 PLAY "ML T40 O3 ECD<G P32 G>DEC" Blagodarya nalichiyu generatora zvuka PCjr dobavlyaet k operatoru PLAY dve vozmozhnosti. Vo-pervyh, dopuskaetsya parametr V, ustanav- livayushchij gromkost'. Vyrazhenie V5 ustanavlivaet (ili izmenyaet) gromkost' na uroven' 5. Dopustimyj diapazon ot 0 do 15, prichem po umolchaniyu beretsya 8. 0 polnost'yu podavlyaet zvuk. Vo-vtoryh, s pomoshch'yu operatora PLAY mozhno odnovremenno ispolnyat' tri zvukovyh stroki. Pomestite vse tri stroki v odnu programmnuyu stroku, raz- delyaya ih zapyatymi. Dlya togo chtoby imet' vozmozhnost' ispol'zovat' eti special'nye svojstva, Vy dolzhny predvaritel'no razreshit' vneshnij dinamik s pomoshch'yu operatora SOUND ON. 100 SOUND ON 110 PLAY "...........","..........","............" Nizkij uroven'. V primere dlya generacii zvuka ispol'zuetsya mikroshema tajmera 8253. Zdes' prosto ispolnyayutsya 8 not, no nebol'shaya modifikaciya mozhet sil'no rasshirit' vozmozhnosti etoj procedury. Imeetsya tri stroki dannyh. Pervaya ustanavlivaet dlitel'nost' kazhdoj noty, kak kratnoe proizvol'nogo perioda zaderzhki (izmenyaya etot period za- derzhki, mozhno izmenyat' temp). Vtoraya stroka soderzhit chastoty kazhdoj iz 8 not; eti znacheniya dolzhny byt' pomeshcheny v registr zadvizhki kanala 2 mikroshemy 8253 dlya ispolneniya zhelaemyh tonov. Tret'ya stroka soderzhit melodiyu v vide kodovyh nomerov ot 1 do 8, kotorye sootvetstvuyut vos'mi chastotam. |ta stroka zavershaetsya kodom 0FFH, kotoryj sluzhit priznakom konca melodii. Procedura prosto chitaet ocherednuyu notu melodii, nahodit sootvetstvuyushchuyu chastotu i pomeshchaet ee v kanal 2. Zatem dlitel'nost' dlya etoj noty pomeshchaetsya v schetchik cikla zaderzhki, kotoryj ispol'zuet schetchik vremeni sutok, a kogda zaderzhka konchaetsya, to perehodim k obra- botke sleduyushchej noty. Na ris. 2-5 pokazana rabota etoj procedury. ;---v segmente dannyh BEAT DB 10,9,8,7,6,5,4,3,2 ;dlitel'nost' not FREQUENCY DW 2280,2031,1809,1709 ;tablica chastot DW 1521,1353,1207,1139 ; MELODY DB 1,2,3,4,5,6,7,8,0FFH ;nomer chastoty noty ;---inicializaciya PORT_B EQU 61H COMMAND_REG EQU 43H LATCH2 EQU 42H IN AL,PORT_B ;poluchaem tekushchij status OR AL,00000011B ;razreshaem dinamik i tajmer OUT PORT_B,AL ;zamenyaem bajt MOV SI,0 ;inicializiruem ukazatel' MOV AL,0B6H ;ustanovka dlya kanala 2 OUT COMMAND_REG,AL ;posylaem v komandnyj registr ;---smotrim notu, poluchaem ee chastotu i pomeshchaem v kanal 2 NEXT_NOTE: LEA BX,MELODY ;berem smeshchenie dlya melodii MOV AL,[BX][SI] ;berem kod n-noj noty stroki CMP AL,0FFH ;proverka na konec stroki JE NO_MORE ;esli konec, to na vyhod CBW ;perevodim v slovo ;poluchenie chastoty MOV BX,OFFSET FREQUENCY ;smeshchenie tablicy chastot DEC AX ;nachinaem otschet s 0 SHL AX,1 ;umnozhaem na 2, t.k. slova MOV DI,AX ;adresuem cherez DI MOV DX,[BX][DI] ;poluchaem chastotu iz tablicy ;nachinaem ispolnenie noty MOV AL,DL ;gotovim mladshij bajt chastoty OUT LATCH2,AL ;posylaem ego MOV AL,DH ;gotovim starshij bajt chastoty OUT LATCH2,AL ;posylaem ego ;---sozdanie cmkla zaderzhki MOV AH,0 ;nomer funkcii chteniya schetchika INT 1AH ;poluchaem znachenie schetchika MOV BX,OFFSET BEAT ;smeshchenie tablicy dlin MOV CL,[BX][SI] ;berem dlinu ocherednoj noty MOV CH,0 ; MOV BX,DX ;berem mladshee slovo schetchika ADD BX,CX ;opredelyaem moment okonchaniya STILL_SOUND: INT 1AH ;berem znachenie schetchika CMP DX,BX ;sravnivaem s okonchaniem JNE STILL_SOUND ;neravny - prodolzhaem zvuk INC SI ;perehodim k sleduyushchej note JMP NEXT_NOTE ; ;---zavershenie NO_MORE: IN AL,PORT_B ;poluchaem status porta B AND AL,0FCH ;vyklyuchaem dinamik OUT 61H,AL ;zamenyaem bajt 2.2.6 Generaciya stroki tonov, odnovremenno s drugimi operaciyami. Hotya v Bejsike eto delaetsya ochen' prosto, na samom dele eto netrivial'nyj tryuk programmirovaniya v real'nom vremeni. Dlya reshe- niya etoj zadachi nuzhno ispol'zovat' generaciyu zvuka cherez mikros- hemu 8253 [2.2.3], tak kak metod, ispol'zuyushchij mikroshemu 8255 [2.2.2], zanimaet processor. Sootvetstvenno, tol'ko stroki chistyh muzykal'nyh tonov mogut proizvodit'sya takim metodom - vsyakogo roda zvukovye effekty pri etom nedostupny. Osnovnaya tehnika prog- rammirovaniya v real'nom vremeni pokazana v [2.1.7]. Programmy, rabotayushchie v real'nom vremeni, modificiruyut preryvanie tajmera, kotoroe ostanavlivaet processor 18.2 raz v sekundu, chtoby izme- nit' pokazanie schetchika vremeni sutok. Rasshirenie procedury pre- ryvaniya sravnivaet novoe znachenie schetchika vremeni sutok so zna- cheniem, pokazyvayushchim vremya zaversheniya generacii tona, i kogda eto znachenie dostignuto, preryvaet zvuk, nachinaet generaciyu drugogo tona i ustanavlivaet vremya ego okonchaniya. Vysokij uroven'. Generaciya stroki zvukov odnovremenno s drugimi operaciyami yavlyaetsya odnoj iz vozmozhnostej ochen' moshchnogo operatora PLAY, kotoryj detal'no obsuzhdalsya v [2.2.5]. Nado prosto dobavit' v nachalo upravlyayushchej stroki MB. |to sokrashchenie ot Music Background (fonovaya muzyka); dlya togo chtoby zastavit' PLAY prekratit' vse drugie operacii, poka generaciya zvukovoj stroki ne budet zavershe- na, vstav'te MF. V nizheprivedennom primere vo vremya risovaniya i zapolneniya ramki ispolnyaetsya gamma (dlya ego raboty trebuetsya nalichie graficheskih vozmozhnostej). 100 PLAY "MB T100 O3 L4;CDEFG>ABC" 'ispolnyaem nabor not 110 LINE (10,10)-(80,80),1,BF 'odnovremenno risuem ramku Nizkij uroven'. Privedennaya procedura yavlyaetsya razvitiem procedury, pokazannoj v predydushchem razdele, na sluchaj real'nogo vremeni. Ona trebuet ponimaniya, kak pereprogrammirovat' preryvanie tajmera, chto obsuzh- dalos' v [2.1.7]. Na etu proceduru dolzhen ukazyvat' vektor prery- vaniya i togda ona budet vypolnyat'sya 18.2 raza v sekundu, v te momenty, kogda budet obnovlyat'sya znachenie schetchika vremeni sutok BIOS. Obychno, budut vypolnyat'sya tol'ko neskol'ko strochek, kotoryh dostatochno, chtoby opredelit', chto vremya izmeneniya zvuka eshche ne nastupilo, - i procedura osvozhdaet processor dlya resheniya drugih zadach. Schetchik vremeni sutok BIOS ispol'zuetsya dlya izmereniya dlitel'- nosti kazhdoj noty. Pri perehode ot odnoj noty k drugoj, dlitel'- nost' novoj noty vychislyaetsya kak chislo impul'sov schetchika i eto znachenie dobavlyaetsya k tekushchemu ego znacheniyu. Kazhdyj raz pri vyzove procedury proveryaetsya tekushchee znachenie schetchika vremeni sutok, i kogda ozhidaemoe vremya nakonec nastupaet, to vypolnyaetsya nabor operacij po poisku novoj noty, programmirovaniyu ee chastoty v kanale 2 mikroshemy 8253 i ustanovleniyu novogo schetchika dli- tel'nosti. Dobavochnyj kod trebuetsya dlya obrabotki special'nyh sluchaev pervoj i poslednej not v stroke. ;---v segmente dannyh BEAT DB 10,9,8,7,6,5,4,3,2 ;dlitel'nost' not FREQUENCY DW 2280,2031,1809,1709 ;tablica chastot DW 1521,1355,1207,1139 ; MELODY DB 1,2,3,4,5,6,7,8,0FFH ;nomer chastoty v tablice HOLDIP DW 0 ;zapominaem original'nyj HOLDCS DW 0 ;vektor preryvaniya SOUND_NOW? DB 1 ;zvuk vklyuchen? FIRST_NOTE? DB 1 ;pervaya nota? END_NOTE DW 0 ;schetchik konca noty WHICH_NOTE DW 0 ;ukazatel' na tekushchuyu notu ;---inicializaciya vektora preryvaniya ;izmenenie vektora PUSH DS ;sohranyaem registr MOV AX,SEG MELODY2 ;segment procedury MOV DS,AX ;pomeshchaem v DS MOV DX,OFFSET MELODY2 ;smeshchenie procedury MOV AL,1CH ;nomer vektora preryvaniya MOV AH,25H ;funkciya ustanovki vektora INT 21H ;izmenenie vektora POP DS ;vosstanovlenie registra ; ;---programma rabotaet dal'she, postoyanno vyzyvaya proceduru ; ;---v konce programmy vosstanavlivaem vektor preryvaniya MOV DX,0FF53H ;vosstanavlivaem original'nye MOV AX,0F000H ;znacheniya dlya vektora 1CH MOV DS,AX ; MOV AL,1CH ;nomer preryvaniya MOV AH,25H ;funkciya ustanovki vektora INT 21H ;vosstanavlivaem vektor RET ; ;---eto samo preryvanie MELODY2 PROC FAR PUSH AX ;sohranyaem izmenyaemye registry PUSH BX ; PUSH CX ; PUSH DX ; PUSH DI ; PUSH SI ; PUSH DS ; MOV AX,SS:[114] ;berem nachal'nyj DS so steka MOV DS,AX ;vosstanavlivaem ego CMP SOUND_NOW?,1 ;nuzhen li zvuk? JE PLAY_IT ;esli net, to vyhod iz preryvaniya JMP NOT_NOW ; PLAY_IT: CMP FIRST_NOTE?,0 ;eto pervaya nota? JE TIME_CHECK ;esli net, to na ustanovku vremeni ;---inicializaciya PORT_B EQU 61H ;opredelyaem imena portov COMMAND_REG EQU 43H ; LATCH2 EQU 42H ; IN AL,PORT_B ;berem status porta B OR AL,00000011B ;razreshaem dinamik i tajmer OUT PORT_B,AL ;posylaem bajt obratno MOV SI,0 ;ukazatel' na stroki MOV AL,0B6H ;inicializaciya kanala 2 tajmera OUT COMMAND_REG,AL ;posylaem v komandnyj registr MOV FIRST_NOTE?,0 ;sbrasyvaem flag pervoj noty ;---ishchem notu, poluchaem ee chastotu, posylaem v kanal 2 NEXT_NOTE: LEA BX,MELODY ;berem smeshchenie stroki melodii MOV SI,WHICH_NOTE ;ukazatel' na tekushchuyu notu MOV AL,[BX][SI] ;kod tekushchej noty stroki CMP AL,0FFH ;proveryaem priznak konca JE NO_MORE ;esli da, to na konec CBW ;inache v slovnyj format ;poluchaem chastotu MOV BX,OFFSET FREQUENCY ;smeshchenie tablicy chastot DEC AX ;nachinaem otschet s nulya SHL AX,1 ;umnozhaem na 2, t.k. slovnaya MOV DI,AX ;adresuemsya cherez DI MOV DX,[BX][DI] ;poluchaem chastotu iz tablicy ;nachinaem ispolnenie noty MOV AL,DL ;gotovim mladshij bajt chastoty OUT LATCH2,AL ;posylaem v registr zadvizhki MOV AL,DH ;gotovim starshij bajt OUT LATCH2,AL ;posylaem ego ;---pustoj cikl, opredelyayushchij dlitel'nost' not TIME_IT: MOV AH,0 ;fnukciya chteniya schetchika INT 1AH ;poluchaem znachenie schetchika MOV BX,OFFSET BEAT ;smeshchenie stroki dlin not MOV CL,[BX][SI] ;dlitel'nost' tekushchej noty MOV CH,0 ; MOV BX,DX ;mladshee slovo znacheniya schetchika ADD BX,CX ;dobavlyaem dlinu v impul'sah MOV END_NOTE,BX ;zapominaem vremya okonchaniya TIME_CHECK: MOV AH,0 ;funkciya chteniya schetchika INT 1AH ;chitaem schetchik CMP DX,END_NOTE ;sravnivaem s nuzhnym JNE NOT_NOW ;esli neravno, to vyhodim MOV SI,WHICH_NOTE ;inache, berem sleduyushchuyu notu INC SI ;uvelichivaem nomer noty MOV WHICH_NOTE,SI ;zapominaem ego JMP NEXT_NOTE ;nachinaem sleduyushchuyu notu ;---zavershenie procedury NO_MORE: IN AL,PORT_B ;berem status porta B AND AL,0FCH ;vyklyuchaem dinamik OUT 61H,AL ;vozvrashchaem bajt MOV SOUND_NOW?,0 ;vosstanavlivaem peremennye MOV FIRST_NOTE?,1 ; NOT_NOW: POP DS ;vosstanavlivaem registry POP SI ; POP DI ; POP DX ; POP CX ; POP BX ; POP AX ; IRET ;vozvrat iz preryvaniya MELODY2 ENDP 2.2.7 Sozdanie plavnogo perehoda tonov. Plavnye perehody tonov proizvodyatsya za schet nepreryvnogo izme- neniya chastoty. |togo mozhno dostignut' kak v Bejsike, tak i prog- rammiruya na nizkom urovne. |tot zvukovoj effekt mozhno sdelat' bolee vyrazitel'nym, esli nemnogo umen'shat' dlitel'nost' kazhdogo segmenta tona pri povyshenii zvuka ili slegka uvelichivat' dlitel'- nost' pri ponizhenii. Vysokij uroven'. V Bejsike nado prosto pomestit' operator SOUND [2.2.2] v cikl, ispol'zuya ochen' malye dliny tonov. Pri kazhdom novom prohode cikla nado uvelichivat' chastotu. Smotrite [2.2.8], gde priveden primer ispol'zovaniya operatora PLAY dlya bolee bystryh perehodov. 100 FOR N = 1 TO 500 STEP 15 110 SOUND 400 + N,1 120 NEXT Nizkij uroven'. Proshche vsego ispol'zovat' metod generacii zvuka, upravlyaemyj mikroshemoj interfejsa s periferiej 8255. Prosto menyajte znachenie bita 1 porta B mezhdu 0 i 1, ispol'zuya dlya otscheta vremeni pustoj cikl, kak pokazano v [2.2.2]. Pri nachale kazhdogo novogo pustogo cikla, zaschet zasylki znacheniya v CX, slegka izmenyajte eto znache- nie. Zdes' ton povyshaetsya: ;---zapret mikroshemy tajmera PB EQU 61H ;adres porta B mikroshemy 8255 IN AL,PB ;poluchaem iz nego bajt OR AL,1 ;sbrasyvaem bit 0 OUT PB,AL ;vozvrashchaem bajt v port ;---ustanovka chastoty i dlitel'nosti zvuka MOV BX,9000 ;nachal'noe znachenie schetchika MOV DX,3000 ;dlitel'nost' zvuka 3000 ciklov REPEAT: ;syuda vozvrashchaemsya posle cikla ;---ustanovka bita dinamika OR AL,00000010B ;ustanavlivaem bit 1 OUT PB,AL ;posylaem bajt v port B MOV CX,BX ;ustanovka schetchika dlya 1/2 cikla CYCLE1: LOOP CYCLE1 ;pustoj cikl na 1000 povtorov ;---sbros bita dinamika AND AL,11111101B ;sbrasyvaem bit 1 OUT PB,AL ;posylaem bajt v port MOV CX,BX ;ustanovka schetchika CYCLE2: LOOP CYCLE2 ;pustoj cikl ;---perehod k sleduyushchemu ciklu DEC BX ;uvelichivaem chastotu, umen'shaya DEC BX ;schetchik DEC DX ;umen'shaem ostavshuyusya dlitel'nost' JNZ REPEAT ;esli DX ne 0, to novyj cikl |tot prostoj metod privodit k tomu, chto vysokie tona prohodyat znachitel'no bystree, chem nizkie. Dlya korotkih intervalov takoj effekt mozhet byt' zhelatel'nym, a kogda on ne nuzhen, nado dobavit' kod, kotoryj pri povyshenii tona peresylaet v DX bol'shie znacheniya na sleduyushchem cikle. 2.2.8 Sozdanie zvukovyh effektov. Zvukovye effekty obychno dostigayutsya nepreryvnym izmeneniem chastoty tona. Tol'ko PCjr dostatochno horosho oborudovan dlya etoj celi (sm. obsuzhdenie v [2.2.1]). Na drugih mashinah nel'zya proiz- vodit' zvukovye effekty odnovremenno s drugimi operaciyami. Vysokij uroven'. Blagodarya moshchnosti svoih operatorov SOUND i PLAY Bejsik pozvo- lyaet dostatochno legko sozdavat' slozhnye zvukovye effekty. No vse dolzhno byt' skonstruirovano iz chistyh muzykal'nyh tonov, a eto znachit, chto effekt distorcii zvuka dolzhen dostigat'sya za schet takogo bystrogo izmeneniya tona, chto uho ne uspevaet razdelit' tona. Naprimer, dusherazdirayushchee "chirikan'e" mozhet byt' polucheno pri bystrom pereklyuchenii mezhdu odnim i tem zhe tonom, otstoyashchim na neskol'ko oktav: 100 FOR N = 1 TO 100 'ustanovka dlitel'nosti 110 PLAY "L64 T255" 'samyj bystryj temp 120 PLAY "O1A" 'vydaem nizkoe A 130 PLAY "O5A" 'vydaem vysokoe A 140 NEXT 'povtor Pri izmenenii chastoty vsego na neskol'ko gerc poluchaem vibraciyu: 100 FOR N = 1 TO 100 'ustanovka dlitel'nosti 110 SOUND 440,1 'vydaem notu A 120 SOUND 445,1 'nemnogo menyaem chastotu 130 NEXT 'povtor Drugaya tehnika zaklyuchaetsya vo vlozhenii plavno menyayushchihsya tonov vnutr' posledovatel'nosti, kotoraya sama gulyaet po chastotam vverh ili vniz. Na ris. 2-6 pokazana dvizhushchayasya vverh posledovatel'- nost'. Mnogie igry s labirintami ispol'zuyut etu tehniku: 100 FOR I = 1 TO 10 'chislo povtorenij 110 FOR J = 1 TO 6 'chislo raznyh oktav 120 PLAY "MBL64T255O=J;BA#AG#GF#FED#DC#CC#DD#EFF#GG#AA#B" 130 NEXT 'povtor v bolee vysokoj oktave 140 NEXT 'povtor vsej posledovatel'nosti PCjr znachitel'no bolee moshchnyj, chem ostal'nye mashiny, blagodarya special'noj mikrosheme generatora zvuka. Operator NOISE mozhet proizvodit' mnozhestvo zvukov, format etogo operatora takoj: NOISE istochnik, gromkost', dlitel'nost' Istochnik - eto chislo ot 0 do 7, znachenie kotorogo privedeno v tablice: 0 periodicheskij shum v vysokom diapazone 1 periodicheskij shum v srednem diapazone 2 periodicheskij shum v nizkom diapazone 3 periodicheskij shum, diapazon menyaetsya s kanalom 3 4 belyj shum v vysokom diapazone 5 belyj shum v srednem diapazone 6 belyj shum v nizkom diapazone 7 belyj shum, diapazon menyaetsya s kanalom 3 Gromkost' zadaetsya chislom ot 0 do 15, gde 0 sootvetstvuet ot- sutstviyu zvuka. Dlitel'nost' ukazyvaetsya chislom impul'sov schetchi- ka vremeni sutok, kotorye otschityvayutsya 18.2 raza v sekundu. Nizkij uroven'. Lyuboj iz sposobov, pokazannyh na Bejsike mozhet byt' realizovan na assemblere, hotya, kak vidno iz predydushchih razdelov, eto tre- buet zatrat na programmirovanie. Krome togo, assembler pozvolyaet generirovat' nechistye tona, kogda interval, v techenie kotorogo dinamik vklyuchen, ne raven intervalu, v techenie kotorogo on vyklyu- chen. Takoe narushenie simmetrii mozhet privodit' k zhuzhzhashchim i brya- kayushchim zvukam. Kogda otnoshenie etih intervalov sostavlyaet, skazhem 50 k 1, to poluchaem zhuzhzhanie. Esli uvelichit' otnoshenie eshche v 10 - 20 raz, to zhuzhzhanie perehodit v otdel'nye bryakayushchie zvuki. V lyubom sluchae zvuk generiruetsya mikroshemoj interfejsa s perife- riej 8255, s pomoshch'yu tehniki pokazannoj v [2.2.2]. Vot primer zhuzhzhaniya: NUMBER_CYCLES EQU 300 ;chislo pereklyuchenij dinamika FREQUENCY1 EQU 50 ;vremya, kogda dinamik vklyuchen FREQUENCY2 EQU 3200 ;vremya, kogda dinamik vyklyuchen PORT_B EQU 61H ;adres porta B mikroshemy 8255 CLI ;zapret preryvanij MOV DX,NUMBER_CYCLES;DX schitaet dlinu tona IN AL,PORT_B ;poluchaem status porta AND AL,11111110B ;otklyuchaem dinamik ot tajmera NEXT_CYCLE: OR AL,00000010B ;vklyuchaem dinamik OUT PORT_B,AL ;posylaem komandu MOV CX,FREQUENCY1 ;zaderzhka dlya pervoj chasti FIRST_HALF: LOOP FIRST_HALF ; AND AL,11111101B ;vyklyuchaem dinamik OUT PORT_B,AL ;posylaem komandu MOV CX,FREQUENCY2 ;zaderzhka dlya vtoroj chasti SECND_HALF: LOOP SECND_HALF ; DEC DX ;umen'shaem chislo ciklov JNZ NEXT_CYCLE ;esli 0, to pora konchat' STI ;razreshaem preryvaniya Dlya sozdaniya bryakayushchih zvukov mozhno ispol'zovat' etot zhe kod, no nado zamenit' znachenie FREQUENCY2 na velichinu okolo 40000. 2.2.9 Odnovremennaya generaciya raznyh zvukov. Tol'ko mikroshema generatora zvuka, imeyushchayasya v PCjr, pozvo- lyaet odnovremenno generirovat' raznye zvuki (sm. obsuzhdenie v [2.2.1]). Odnako assembler pozvolyaet ob®edinit' dva sposoba gene- racii zvuka, chto sozdaet imitaciyu odnovremennoj generacii dvuh raznyh zvukov. Interferenciya etih dvuh signalov privodit k slozh- noj forme zvukovoj volny. Kazhdyj iz dvuh zvukov imeet men'shuyu gromkost', poetomu v rezul'tate poluchaetsya skoree zhuzhzhanie, chem dva raznyh golosa. |tot priem real'no polezen tol'ko dlya sozdaniya zvukovyh effektov. Nizkij uroven'. Nado prosto ob®edinit' dva metoda generacii zvuka, pokazannye v [2.2.2] i [2.2.3]. Nachnite zvuk cherez kanal 2 mikroshemy tajme- ra. Zatem modulirujte vyhod dinamika, za schet bita 1 porta B mikroshemy interfejsa s periferiej. Vtoroe dejstvie opredelyaet prodolzhitel'nost' zvuka. Ne zabud'te vyklyuchit' mikroshemu tajmera pri zavershenii. ;---nachinaem generaciyu zvuka cherez kanal 2 tajmera IN AL,61H ;poluchaem bajt iz porta B OR AL,3 ;ustanavlivaem mladshie dva bajta OUT 61H,AL ;posylaem bajt obratno MOV AL,10110110B ;cepochka dlya komandnogo registra 8253 OUT 43H,AL ;posylaem v registr MOV AX,600H ;schetchik dlya kanala 2 OUT 42H,AL ;posylaem mladshij bajt MOV AL,AH ;gotovim starshij bajt OUT 42H,AL ;posylaem starshij bajt ;---generiruem vtoruyu chastotu mikroshemoj 8255 NUMBER_CYCLES EQU 9000 ;chislo pereklyuchenij FREQUENCY EQU 150 ;zaderzhka dlya poloviny cikla CLI ;zapret preryvanij MOV DX,NUMBER_CYCLES ;DX schitaet dlinu tona IN AL,61H ;poluchaem status porta AND AL,11111111B ;otklyuchaem dinamik ot tajmera NEXT_CYCLE: OR AL,00000010B ;vklyuchaem dinamik OUT 61H,AL ;posylaem nazad v port MOV CX,FREQUENCY ;zaderzhka na 1/2 cikla FIRST_HALF: LOOP FIRST_HALF ; AND AL,11111101B ;vyklyuchaem dinamik OUT 61H,AL ;posylaem komandu v port MOV CX,FREQUENCY ;zaderzhka na 1/2 cikla SECOND_HALF: LOOP SECOND_HALF ; DEC DX ;menyaem schetchik ciklov JNZ NEXT_CYCLE ;esli 0, to pora konchat' STI ;razreshaem preryvaniya ;---vyklyuchenie kanala 2 mikroshemy tajmera IN AL,61H ;poluchaem status porta AND AL,11111100B ;sbrasyvaem 2 mladshih bita OUT 61H,AL ;posylaem bajt obratno Glava 3. Klaviatura. Razdel 1. Upravlenie klaviaturoj. Klaviatura soderzhit intelevskij mikroprocessor, kotoryj vosp- rinimaet kazhdoe nazhatie na klavishu i vydaet skan-kod v port A mikroshemy interfejsa s periferiej [1.1.1], raspolozhennoj na sistemnoj plate. Skan-kod eto odnobajtnoe chislo, mladshie 7 bitov kotorogo predstavlyayut identifikacionnyj nomer, prisvoennyj kazhdoj klavishe. Tablica skan-kodov privedena v [3.3.2]. Na vseh mashinah, krome AT, starshij bit koda govorit o tom, byla li klavisha nazhata (bit = 1, kod nazhatiya) ili osvobozhdena (bit = 0, kod osvobozhde- niya). Naprimer, 7-bitnyj skan-kod klavishi B - 48, ili 110000 v dvoichnoj sisteme. Kogda eta klavisha nazhimaetsya, to v port A posy- laetsya kod 10110000, a kogda ee otpustili - kod 00110000. Takim obrazom, kazhdoe nazhatie na klavishu dvazhdy registriruetsya v mik- rosheme 8255. I kazhdyj raz mikroshema 8255 vydaet podtverzhdenie mikroprocessoru klaviatury. AT rabotaet nemnogo po-drugomu, posy- laya v oboih sluchayah odin i tot zhe skan-kod, no predvaryaya ego kodom F0H, kogda klavisha otpuskaetsya. Kogda skan-kod vydaetsya v port A, to vyzyvaetsya preryvanie klaviatury (INT 9). Processor momental'no prekrashchaet svoyu rabotu i vypolnyaet proceduru, analiziruyushchuyu skan-kod. Kogda postupaet kod ot klavishi sdviga ili pereklyuchatelya, to izmenenie statusa zapisyvaetsya v pamyat'. Vo vseh ostal'nyh sluchayah skan-kod trans- formiruetsya v kod simvola, pri uslovii, chto on podaetsya pri nazha- tii klavishi (v protivnom sluchae, skan-kod otbrasyvaetsya). Konech- no, procedura snachala opredelyaet ustanovku klavish sdviga i perek- lyuchatelej, chtoby pravil'no poluchit' vvodimyj kod (eto "a" ili "A"?). Posle etogo vvedennyj kod pomeshchaetsya v bufer klaviatury, kotoryj yavlyaetsya oblast'yu pamyati, sposobnoj zapomnit' do 15 vvo- dimyh simvolov, poka programma slishkom zanyata, chtoby obrabotat' ih. Na ris. 3-1 pokazan put', kotoryj prohodit nazhatie na klavishu pered tem, kak pokast' v Vashu programmu. Imeetsya dva tipa kodov simvolov, kody ASCII i rasshirennye kody. Kody ASCII - eto bajtnye chisla, kotorye sootvetstvuyut ras- shirennomu naboru kodov ASCII dlya IBM PC, kotoryj priveden v [3.3.3]. Dlya IBM PC etot nabor vklyuchaet obychnye simvoly pishushchej mashinki, a takzhe ryad special'nyh bukv i simvolov psevdografiki. ASCII kody vklyuchayut takzhe 32 upravlyayushchih koda, kotorye obychno ispol'zuyutsya dlya peredachi komand periferijnym ustrojstvam, a ne vyvodyatsya kak simvoly na ekrane; odnako kazhdyj iz nih imeet soot- vetstvuyushchij simvol, kotoryj mozhet byt' vyveden na displej, s ispol'zovaniem pryamoj adresacii displejnoj pamyati [4.3.1]. (Stro- go govorya, tol'ko pervye 128 simvolov yavlyayutsya nastoyashchimi simvo- lami ASCII, tak kak ASCII - eto abbreviatura ot Amerikanskij standartnyj kod dlya obmena informaciej. No programmisty obychno govoryat o kodah ASCII, chtoby otlichit' ih ot drugih chisel. Napri- mer, "ASCII 8" otnositsya k klavishe "Backspace", v to vremya kak "8" - eto cifra, kotoroj sootvetstvuet ASCII 56). Vtoroj nabor kodov, rasshirennye kody, prisvoen klavisham ili kombinaciyam klavish, kotorye ne imeyut predstavlyayushchego ih simvola ASCII, takim kak funkcional'nye klavishi ili kombinacii s klavishej Alt. Rasshirennye kody imeyut dlinu 2 bajta, prichem pervyj bajt vsegda ASCII 0. Vtoroj bajt - nomer rasshirennogo koda, spisok kotoryh priveden v [3.3.5]. Naprimer, kod 0:30 predstavlyaet Alt-A. Nachal'nyj nol' pozvolyaet programme prinadlezhit li dannyj kod naboru ASCII ili rasshirennomu naboru. Imeetsya neskol'ko kombinacij klavish, kotorye vypolnyayut spe- cial'nye funkcii i ne generiruyut skan-kody. |ti kombinacii vklyu- chayut <Ctrl-Break>, <Ctrl-Alt-Del> i <PrtSc>, plyus <SysReq> dlya AT i <Ctrl-Alt-strelka vlevo, -strelka vpravo, -CapsLock, -Ins> dlya PCjr. |ti isklyucheniya privodyat k zaranee predopredelennym rezul'- tatam [3.3.2]. Vse ostal'nye nazhatiya klavish dolzhny interpretiro- vat'sya Vashej programmoj i esli oni imeyut special'noe naznachenie, skazhem sdvinut' kursor vlevo, to Vasha programma dolzhna soderzhat' kod, obespechivayushchij dostizhenie etogo effekta. K schast'yu operacionnaya sistema predostavlyaet razlichnye proce- dury dlya chteniya kodov iz bufera klaviatury, vklyuchaya sredstva dlya polucheniya srazu celoj stroki. Poskol'ku eti procedury pozvolyayut delat' prakticheski vse, chto Vy mozhete pozhelat', to prakticheski bessmyslenno pisat' svoi procedury obrabotki vvoda s klaviatury i poetomu v dannoj glave imeetsya ochen' malo primerov programmirova- niya na nizkom urovne. Odnako soderzhitsya obsuzhdenie voprosa o tom, kak pereprogrammirovat' preryvanie klaviatury. 3.1.1 Ochistka bufera klaviatury. Programma dolzhna ochistit' bufer klaviatury, pered tem, kak vydat' zapros na vvod, isklyuchaya tem samym postoronnie nazhatiya klavish, kotorye mogut k tomu vremeni nakopit'sya v bufere. Bufer mozhet nakaplivat' do 15 nazhatij na klavishu, nezavisimo ot togo, yavlyayutsya li oni odnobajtnymi kodami ASCII ili dvuhbajtnymi rasshi- rennymi kodami. Takim obrazom, bufer dolzhen otvesti dva bajta pamyati dlya kazhdogo nazhatiya na klavishu. Dlya odnobajtnyh kodov pervyj bajt soderzhit kod ASCII, a vtoroj - skan-kod klavishi. Dlya rasshirennyh kodov pervyj bajt soderzhit ASCII 0, a vtoroj nomer rasshirennogo koda. |tot kod obychno sovpadaet so skan-kodom klavi- shi, no ne vsegda, poskol'ku nekotorye klavishi mogut kombiniro- vat'sya s klavishami sdviga dlya generacii razlichnyh kodov. Bufer ustroen kak ciklicheskaya ochered', kotoruyu nazyvayut takzhe buferom FIFO (pervyj voshel - pervyj ushel). Kak i lyuboj bufer on zanimaet nepreryvnuyu oblast' adresov pamyati. Odnako ne imeetsya opredelennoj yachejki pamyati, kotoraya hranit "nachalo stroki" v bufere. Vmesto etogo dva ukazatelya hranyat pozicii golovy i hvosta stroki simvolov, nahodyashchejsya v bufere v tekushchij moment. Novye nazhatiya klavish zapasayutsya v poziciyah, sleduyushchih za hvostom (v bolee starshih adresah pamyati) i sootvetstvenno obnovlyaetsya ukaza- tel' hvosta bufera. Posle togo, kak izrashodovano vse bufernoe prostranstvo, novye simvoly prodolzhayut vstavlyat'sya, nachinaya s samogo nachala bufernoj oblasti; poetomu vozmozhny situacii, kogda golova stroki v bufere imeet bol'shij adres, chem hvost. Posle togo kak bufer zapolnen, novye vvodimye simvoly ignoriruyutsya, pri etom preryvanie klaviatury vydaet gudok cherez dinamik. Na ris. 3-2 pokazany nekotorye vozmozhnye konfiguracii dannyh v bufere. V to vremya kak ukazatel' na golovu ustanovlen na pervyj vve- dennyj simvol, ukazatel' na hvost ustanovlen na poziciyu za pos- lednim vvedennym simvolom. Kogda oba ukazatelya ravny, to bufer pust. CHtoby razreshit' vvod 15 simvolov trebuetsya 16-ya pustaya poziciya, 2 bajta kotoroj vsegda soderzhat kod vozvrata karetki (ASCII 13) i skan-kod klavishi <Enter>, ravnyj 28. |ta pustaya poziciya neposredstvenno predshestvuet golove stroki simvolov. 32 bajta bufera nachinayutsya s adresa 0040:001E. Ukazateli na golovu i hvost raspolozheny po adresam 0040:001A i 0040:001C, sootvetstven- no. Hotya pod ukazateli otvedeno 2 bajta, ispol'zuetsya tol'ko mladshij bajt. Znacheniya ukazatelej menyayutsya ot 30 do 60, chto soot- vetstvuet poziciyam v oblasti dannyh BIOS. Dlya ochistki bufera nado prosto ustanovit' znachenie yachejki 0040:001A ravnym znacheniyu yachej- ki 0040:001C. Otmetim, chto programma imeet vozmozhnost' vstavlyat' simvoly v bufer, zavershaya stroku simvolom vozvrata karetki i sootvetstvenno menyaya znacheniya ukazatelej. Esli eto prodelat' pravil'nym obrazom pered zaversheniem programmy, to pri vozvrate upravleniya v MS DOS eti simvoly budut schitany i mozhet byt' avtomaticheski zagruzhena drugaya programma. Nizkij uroven'. V Bejsike dlya polucheniya i izmeneniya znachenij ukazatelej bufera ispol'zuyutsya operatory PEEK i POKE: 100 DEF SEG = &H40 'ustanavlivaem znachenie segmenta 110 POKE &H1C, PEEK(&H1A) 'vyravnivaem ukazateli |tot metod ne samyj luchshij. Nekotorye programmy mogut sozdavat' bufer gde-nibud' v drugom meste pamyati, a krome togo, vsegda sushchestvuet vozmozhnost', chto posredi stroki 110 proizojdet prery- vanie klaviatury, kotoroe izmenit ukazatel' hvosta. Po etim pri- chinam luchshe ostavit' ukazateli bufera v pokoe. Vmesto etogo, luchshe chitat' iz bufera do teh por, poka ne budet vozvrashchen simvol ASCII 0, pokazyvayushchij, chto bufer pust: 100 IF INKEY$<>"" THEN 100 'berem sleduyushchee esli ne nul' Srednij uroven'. Funkciya 0C preryvaniya 21H vypolnyaet lyubuyu iz funkcij vvoda s klaviatury 1, 6, 7, 8 i A (opisannyh v etoj glave), no pered etim chistit bufer klaviatury. Nado prosto pomestit' nomer funkcii vvoda v AL (v etom primere - 1): ;---ochistka bufera pered ozhidaniem nazhatiya klavishi MOV AH,0CH ;vybiraem funkciyu DOS 0CH MOV AL,1 ;vybiraem funkciyu vvoda simvola INT 21H ;chistim bufer, zhdem vvoda Nizkij uroven'. Kak i v primere vysokogo urovnya delaem znachenie ukazatelya na hvost ravnym znacheniyu ukazatelya na golovu. Dlya izbezhaniya vliyaniya preryvaniya klaviatury zapreshchaem preryvaniya na vremya modifikacii ukazatelya: ;---vyravnivaem znacheniya ukazatelej na golovu i hvost CLI ;zapreshchaem preryvaniya SUB AX,AX ;obnulyaem registr MOV ES,AX ;dobavochnyj segment - s nachala pamyati MOV AL,ES:[41AH] ;berem ukazatel' na golovu bufera MOV ES:[41CH],AL ;posylaem ego v ukazatel' hvosta STI ;razreshaem preryvaniya 3.1.2 Proverka simvolov v bufere. Vy mozhete proverit' byl li vvod s klaviatury, ne udalyaya simvol iz bufera klaviatury. Bufer ispol'zuet dva ukazatelya, kotorye otmechayut golovu i hvost ocheredi simvolov, nahodyashchihsya v bufere v tekushchij moment. Kogda znacheniya etih ukazatelej ravny, to bufer pust. Nado prosto sravnit' soderzhimoe yacheek pamyati 0040:001A i 0040:001C. (Nel'zya prosto proverit' simvol, nahodyashchijsya v golove ocheredi, poskol'ku bufer organizovan v vide ciklicheskoj ocheredi i poziciya ee golovy postoyanno menyaetsya [3.1.1].) Vysokij uroven'. Nado prosto ispol'zovat' operator PEEK dlya polucheniya znachenij, a zatem sravnit' ih: 100 DEF SEG = &H40 'ustanavlivaem segment na nachalo pamyati 110 IF PEEK(&H1A)<>PEEK(&H1C) THEN ... '...to bufer ne pust Srednij uroven'. Funkciya 0BH preryvaniya 21H vozvrashchaet znachenie 0FFH v registre AL, kogda bufer klaviatury soderzhit odin ili bolee simvolov i znachenie 0, kogda bufer pust: ;---proverka nalichiya simvola v bufere MOV AH,0BH ;nomer funkcii INT 21H ;vyzyvaem preryvanie 21H CMP AL,0FFH ;sravnivaem s 0FFH JE GET_KEYSTROKE ;perehod esli bufer ne pust Funkciya 1 preryvaniya BIOS 16H predostavlyaet tu zhe vozmozhnost', no, krome togo, pokazyvaet kakoj simvol v bufere. Flag nulya (ZF) sbrasyvaetsya, esli bufer pust, i ustanavlivaetsya, esli v bufere imeetsya simvol. V poslednem sluchae kopiya simvola, nahodyashchegosya v golove bufera, pomeshchaetsya v AX, no simvol iz bufera ne udalyaetsya. V AL vozvrashchaetsya kod simvola dlya odnobajtnyh simvolov ASCII, inache ASCII 0 dlya rasshirennyh kodov, i togda nomer koda - v AH. ;---proveryaem nalichie simvola v bufere MOV AH,1 ;nomer funkcii INT 16H ;proverka nalichiya simvola JZ NO_CHARACTER ;perehod esli ZF = 1 ;---imeetsya simvol - smotrim kakoj CMP AL,0 ;eto rasshirennyj kod? JE EXTENDED_CODE ;esli da, to na druguyu vetku Nizkij uroven'. Kak i v primere vysokogo urovnya prosto sravnivaem ukazateli: ;---sravnivaem ukazateli na golovu i hvost MOV AX,0 ;ustanavlivaem dobavochnyj segment MOV ES,AX ;na nachalo pamyati MOV AL,ES:[41AH] ;berem odin ukazatel' MOV AH,ES:[41CH] ;berem drugoj ukazatel' CMP AH,AL ;sravnivaem ih JNE GET_KEYSTROKE ;esli neravny, to k procedure vvoda 3.1.3 Ozhidat' vvod simvola i ne vyvodit' ego na ekran. Obychno vvodimye simvoly vyvodyatsya na ekran, chtoby bylo vidno, chto napechatano. No inogda avtomaticheskoe eho na ekrane nezhela- tel'no. Naprimer, vybor punkta menyu po nazhatiyu klavishi. Inogda nado snachala proverit' vvodimye simvoly na oshibku pered vyvodom na ekran. V chastnosti, lyubaya programma, obrabatyvayushchaya rasshiren- nye kody, dolzhna izbegat' avtomaticheskogo eha, tak kak pri etom pervyj bajt etih kodov (ASCII 0) budet vyvodit'sya na ekran, vstavlyaya probely mezhdu simvolami. Vysokij uroven'. Funkciya Bejsika INKEY$ ne daet eho na terminal. Ona vozvrashchaet stroku dlinoj 1 bajt dlya simvolov ASCII i dlinoj 2 bajta dlya rasshirennyh kodov. INKEY$ ne ozhidaet nazhatiya klavishi, do teh por, poka ona ne pomeshchena v cikl, v kotorom ozhidaetsya nazhatie klavishi. Cikl rabotaet, obrashchayas' k INKEY$, a zatem prisvaivaya vozvrashchae- muyu im stroku peremennoj, v dannom sluchae C$. Esli klavisha ne byla nazhata, to INKEY$ vozvrashchaet nulevuyu stroku, t.e. stroku dlinoj nol' simvolov, kotoraya oboznachaetsya dvumya znakami kavychek, mezhdu kotorymi nichego net (""). Do teh por poka INKEY$ vozvrashchaet "" - cikl povtoryaetsya: 100 C$=INKEY$:IF C$="" THEN 100. V nizheprivedennom primere predpolagaetsya, chto vvodimye simvoly vybirayut odnu iz vozmozhnostej menyu i kazhdyj vybor privodit k vypolneniyu opredelennoj procedury programmy. Vybor mozhet byt' sdelan za schet nazhatiya klavish A, B, C ... (davaya 1-bajtnye kody ASCII) ili Alt-A, Alt-B, Alt-C ... (davaya 2-bajtnye rasshirennye kody). Dlya ih raspoznavaniya ispol'zuetsya funkciya LEN, kotoraya opredelyaet byla li stroka dlinoj v 1 ili 2 bajta. V slucha