Kompiuterių architektūra/Antroji praktinė užduotis/Žodžių rikiavimas abėcėles tvarka
Iš MIF SA Wiki.
Parašykite programą, kurios pirmasis parametras raidžių intervalas (pavyzdžiui, a-f), o visi kiti - failų vardai. Programa skaito parametrais nurodytus failus ir rezultatų faile išveda sąrašą žodžių, prasidedančių raidėmis iš nurodyto intervalo. Viename rezultatų faile pateikiamas sąrašas žodžių iš visų failų be pasikartojimų ir išrūšiuotas abėcėlės tvarka. Šalia kiekvieno žodžio turi būti atspausdinamas skaičius, reiškiantis, kiek kartų žodis pasikartojo visuose nurodytuose failuose kartu. Taip pat rezultatų faile turi būti pateiktas ir antras žodžių ir jų pasikartojimų skaičiaus sąrašas, tik antrą kartą sąrašas pateikiamas išrūšiuotas pasikartojimų mažėjimo tvarka.
Tikiu, kad programos kodas nėra idealus, tačiau tikiuosi, kad tam tikros programos vietos bus naudingos.
;Markas Sislo ;PS-05, 2 Uzdruotis, 19 Numeris ;Parasykite programa, kurios pirmasis parametras raidziu intervalas (pavyzdziui, a-f), o visi kiti - failu vardai. Programa skaito parametrais nurodytus failus ir rezultatu faile isveda sarasa zodziu, prasidedanciu raidemis is nurodyto intervalo. Viename rezultatu faile pateikiamas sarasas zodziu is visu failu be pasikartojimu ir isrusiuotas abeceles tvarka. Salia kiekvieno zodzio turi buti atspausdinamas skaicius, reiskiantis, kiek kartu zodis pasikartojo visuose nurodytuose failuose kartu. Taip pat rezultatu faile turi buti pateiktas ir antras zodziu ir ju pasikartojimu skaiciaus sarasas, tik antra karta sarasas pateikiamas isrusiuotas pasikartojimu mazejimo tvarka. sseg segment stack db 256 dup (?) sseg ends dseg segment abcStart db 0 ;pirma raide abcEnd db 0 ;paskutine raide zodis db 19 dup (0),'$' ;tarpinis kintamasis, naudojamas surasto zodzio ir jo pasikartojimu kiekio reiksmem saugoti failas db 80 dup (0) ;tarpinis kintamasis, naudojamas failo vardasm saugoti skaitliukas db 4 dup (0) ;kiek raidziu rasta duomenis db 10240 dup ('$') ;visu failu duomenis doleris db '$' tarpas db ' ' nuliukas db 15 dup ('0') ;nuliuku eilute naudojama panauduotu raidziu apnulinimui tarpai db 19 dup (0) ;eilute naudojama arsekantis db 0 ;ar sekanti sutampa su tikrinamu zodziu raidS dw 0 ;nuo kur prasideda duomenis su tam tikra raide zing db 19 ;vieno duomenu masyvo elemento baitu kiekis pagalbinis db 10240 dup (0) ;pagalbinis duomenu buferis, naudojamas rikiavime abceles tvarka rezultatu db 20240 dup(0),'$' ;buferis, kuriame yra saugomas zodziu ir ju kiekiu reiksmes (keikvienas zodis uzima max.-15 baitu, o kiekis max.-4 baitus enteris db 13,10,13,10 ;naudojama norint pereiti i kita eilute rasant i faila rezD dw 0 ;rezultatu failo "handle"'as bufINPUT db 80,0,78 dup (?),'$';bufeis, naudojamas, ivedant parametrus is standartinio ivedimos stauto msg1 db 'Iveskite duomenis is standartinio ivedimo srauto:',13,10,'$' msg2 db 'Zodziu atrinkimas yra atliktas. Rezultatai patalpinti REZ.TXT faile.','$' klaida1 db 'Virsytas maksimalus vieno zodzio sutapimu kiekis:','$' klaidaD db 'Blogai ivestas duomenu failas','$' klaidaR db 'Neteisingai ivestas raidziu diapazonas','$' pagalba db '=== Programa skaito parametrais arba is standartinio ivedimo srauto nurodytus failus ir rezultatu faile (REZ.TXT) isveda sarasa zodziu, prasidedanciu raidemis is nurodyto intervalo.',13,10,13,10,'=== Bendras duomenu failu dydis neturi virsyti 10 KB.',13,10,13,10,'=== Parametru ivedimo pavyzdys: u2 a-g duom1.txt duom2.txt',13,10,13,10,'=== Programa nereaguoja i didziasias ir mazasias raides. Zodziai negali buti ilgesni uz 15 simboliu.',13,10,13,10,'=== Zodziai duomenu faile turi buti atskirti tarpais. Korekriskiems rezultatams gauti, reikia nauduoti duomenu faile TIK RAIDES ir TARPUS',13,10,13,10,'=== Duomenu failo turinio pavyzdys: Man labai patinka dalykas Kompiuteriu Architektura.','$' filename db 'rez.txt' ;rezultatu failo vardas dseg ends cseg segment assume ds:dseg,ss:sseg, cs : cseg; main proc far pradzia: ;===nusakome duomenu segmento pradzia=== mov ax, dseg mov ds,ax ;===ivedame parametra is standartinio ivedimo srauto=== mov cl,ES:[81h] cmp cl,0Dh jne parametras mov ah,09h lea dx, msg1 int 21h mov ah,0Ah lea dx,bufINPUT int 21h mov ES:[81h],byte ptr 0 xor cx,cx mov cl,bufINPUT[1] inc cl mov ES:[80h],byte ptr cl lea si,bufINPUT add si,2 mov di,82h rep movsb ;===apdorojame parametrus=== parametras: MOV SI, 82h call trinti_tarpus ;===jeigu ivestas pagalbos pranesimas=== mov dx,word ptr es:[si] cmp dx,3F2Fh je pagalbos_pranesimas jmp toliau pagalbos_pranesimas: mov ah,09h lea dx,pagalba int 21h jmp pabaiga toliau: XOR CX, CX MOV CL, ES:[SI] ; ES=DS po programos uzkrovimo mov abcStart,cl add si, 2h mov ch, es:[si] mov abcEnd,ch call raidziu_tikrinimas add si, 2h call trinti_tarpus xor cx,cx mov di,0 lea bx, failas mov ax, 0 ;==irasome failo vardus i buferi failas== vcyklas: MOV CL, ES:[SI] ;parametro skaitliukas cmp cl,0Dh ;jei ne parametru eilutes pabaiga je icyklas cmp cl,20h je icyklas mov [bx],cl inc si inc bx jmp vcyklas ;==atveriame failus=== icyklas: mov dx, offset failas add dx,ax mov al, 0 mov ah, 3dh int 21h jc klaida jmp toliau2 klaida: call klaidaF toliau2: ;==paruosimas skaitymui is failo== xor ch,ch push cx xor cx, cx push bx lea dx,duomenis add dx,di cmp di,0 je ibuferi mov duomenis[di],' ' ;padedame tarpa tarp duomenu ivestu is skirtinu failu inc dx inc di ibuferi: ;=== duomenis skaitome is failo i buferi=== mov bx,ax mov ah,3Fh mov cx,1000 int 21h jc klaida add di,ax mov ah,3Eh ;uzdariome faila int 21h pop bx xor ax,ax mov cx,offset failas ;pereiname prie kito failo mov ax,bx sub ax,cx pop cx cmp cl,0Dh ;jeigu beigeme skatyti parametrus je antra_dalys inc si call trinti_tarpus cmp [si],byte ptr 0Dh je antra_dalys jmp vcyklas ;============================================== ;= Antra programos dalys - darbas su buferiu = ;============================================== antra_dalys: mov ax, dseg mov es, ax xor ax,ax lea si, rezultatu mov raidS,si mov si, offset duomenis xor ax,ax ;==Ieskome zodziu kuriuose yra nurodyta raide== zodziu_paieska: mov arsekantis,0 mov al,byte ptr abcStart cmp byte ptr[si],24h je tarpinis cmp al,60h ja mazoji jb didzioji mazoji: mov cl,al sub cl,byte ptr 20h cmp byte ptr [si],cl je radome_raide jmp toliau4 didzioji: mov cl,al add cl,byte ptr 20h cmp byte ptr [si],al je radome_raide toliau4: cmp byte ptr [si],al je radome_raide inc si jmp zodziu_paieska ;==Rade zodzius kuriuose yra nurodyta raide patiktiname ar ji yra pirma== radome_raide: cmp si, offset duomenis ;jei pirmas zodis buferyje je radome_zodi mov cl,[si-1] cmp cl,tarpas je radome_zodi inc si jmp zodziu_paieska ;==Jeigu radome zodi kuris prasideda is nurodytos raides== radome_zodi: lea di,zodis xor cx,cx xor bx,bx ;==Nuskaitome si zodi i tarpini kintamaji ZODIS== zodzio_irasimas: movsb mov cl,[si] cmp cl,tarpas je fiksuojame_vieta cmp cl,doleris je fiksuojame_vieta jmp zodzio_irasimas fiksuojame_vieta: mov cx,si add cx,1 push cx ;irasome pirmo rasto zodzio vieta ;==Nuo uzfiksuotojos vietos atliekame sutampanciu zodziu paieska== sutampanciu_paieska: lea di,zodis ;zodzio raide inc si mov ax,si jmp raidziu_palyginimas tarpinis: jmp apdorota_raide ;==Atliekame paieska palygindmi paraidziui atsizvelgdami i didziasias ir mazasias raides== raidziu_palyginimas: mov cl,[si] ;buferio raide cmp cl,60h ja mazoji_raideB ;mazoji raide buferyje jb didzioji_raideB ;didzioji raide buferyje mazoji_raideB: ;tikriname didziasias ir mazasias raides CMP [di],byte ptr 60h ja mazoji_raideZ1 jb didzioji_raideZ1 mazoji_raideZ1: cmp cl,[di] jne outcycle jmp toliau3 didzioji_raideZ1: add [di],byte ptr 20h cmp cl,[di] jne outcycle jmp toliau3 didzioji_raideB: CMP [di],byte ptr 60h ja mazoji_raideZ2 jb didzioji_raideZ2 mazoji_raideZ2: sub [di],byte ptr 20h cmp cl,[di] jne outcycle jmp toliau3 didzioji_raideZ2: add [di],byte ptr 20h sub [di],byte ptr 20h cmp cl,[di] jne outcycle toliau3: inc si inc di jmp raidziu_palyginimas ;==Apdorojame palyginimo rezultatus outcycle: mov cl,[si] mov ch,[di] cmp ch,0 jne jeigu_nesutampa cmp cl,tarpas je sutampantis cmp cl,doleris je paskutinis_sutampantis ;==Jeigu zodziai nesutampa "praleidziame" nesutampancius simbolius, kol nepasibaigs zodis == jeigu_nesutampa: mov arsekantis,1 ;ar sekantis sutampa su einamu 1, jei nesutampa "arseknatis" = 1 mov al,' ' mov di,si mov cx,15 repne scasb dec di mov cl,[di] cmp cl,'$' je vieno_zodzio_sutapimai mov si,di jmp sutampanciu_paieska ;==Jeigu yra ne vienas sutampantis == sutampantis: mov cx,si sub cx,ax mov di,ax push si lea si,nuliukas rep movsb pop si cmp arsekantis,0 inc bx call virsija_riezius jmp sutampanciu_paieska ;==Jeigu yra vienas sutampantis, arba sutampantis yra paskutinis zodis duomenu buferyje == paskutinis_sutampantis: inc bx call virsija_riezius mov cx,si sub cx,ax mov di,ax push si lea si,nuliukas rep movsb pop si ;==Irasydami nauja zodi i rezultatu faila atliekame rikiavima abceles tvarka== vieno_zodzio_sutapimai: ;=Konvertuojame sutapimu kieki is 16-aines i 10-aine skaiciavimo sistema= xor ax,ax inc bx mov ax,bx lea si,zodis add si,15 call hex2dec mov al,skaitliukas mul zing ;kiek yra vienos raides zodziu baitu mov dx,offset rezultatu add dx,ax sub dx,raids add skaitliukas,1 ;didiname elementu kieki rezultatu buferyje xor ax,ax lea di,zodis mov si,raidS inc di inc si ;==Lyginame paraidziui (kol sutampa) jau esamus "reikalingus" zodzius rezultatu buferyje su nauju rastu zodziu == lygu: inc ax cmp ax,dx ja irasome_kaip_paskutini cmpsb je lygu ja keiciame sub si,ax add si,13h mov cl,[si-1] cmp cl,0 je irasome_kaip_paskutini dec di sub dx,13h xor ax,ax jmp lygu ;==Jeigu naujo elemnto pirmos ,nelygios palyginamam zodziui, raides ASCII kodas yra mazesnis... ;..tai nauja elenta parasome i palyginamo vieta, o palyginamaji elemneta nustumiamiame i desine per 1 pozicija keiciame: push si push di dec si sub si,ax ;iskeliame i pagalbini buferi lea di,pagalbinis mov cx,dx rep movsb ;i palyginamo vieta pop di pop si dec di dec si sub si,ax mov di,si lea si,pagalbinis add di,13h mov cx,dx rep movsb ;i pagalbini kintamaji likusi buferio dalis sub di,dx sub di,13h lea si,zodis mov cx,13h rep movsb ;o palyginamaji elemneta nustumiamiame i desine per 1 pozicija jmp porikiavimo ;== Kitu atveju irasome elementa i rezultato buferio gala == irasome_kaip_paskutini: dec di dec si mov cx,13h mov di,si lea si,zodis ;mov di,[raids] rep movsb ;== Po rikiavimo apnuliname tarpinio kintamojo, kur saugojome, einamaji zodi, reiksmes.== ;== pereiname prie kito zodzio apdorojimo == porikiavimo: lea di,zodis lea si,tarpai mov cx,13h rep movsb pop si jmp zodziu_paieska ;== Jeigu apdorojome visus vienos raides zodzius - pereiname prie sekancios (padidiname ASCII koda vienetu) == apdorota_raide: mov cl, AbcEnd cmp AbcStart,cl jbe raides_keitimas jmp failo_sukurimas raides_keitimas: inc AbcStart mov si, offset duomenis mov al,skaitliukas ;nurodome kur yra duomenis su nauja raide mul zing lea bx,rezultatu add ax,bx mov raidS,ax jmp zodziu_paieska ;=== Irasome zodziu surikiuotu abceles tvarka sarasa i faila REZ.TXT === failo_sukurimas: mov ah,3Ch ;sukuriame rez faila lea dx, filename xor cx, cx int 21h mov ah,3dh ;atveriame rez faila mov al,1 lea dx, filename int 21h mov bx,ax mov rezd,bx ;rezd - rezultato failo "handle"'as mov al,skaitliukas ;nustatome kiek irasyti mul zing mov cx,ax mov ah,40h ;irasome lea dx,rezultatu int 21h mov ah,40h ;pereiname i kita eilute mov cx,4 lea dx,enteris int 21h ;== Sukuriame antra sarasa, rikiuojame zodzius mazejanciai, pagal pasikartojimu skaiciu call rikiavimas ;rikiuojame mazejanciai ;= Irasome antro saraso duomenis i rezultatu faila mov al,skaitliukas mul zing mov cx,ax ;skaiciuojame kiek irasyti mov bx,rezd lea dx,rezultatu mov ah,40h ;irasome int 21h mov ah,3Eh ;uzdarome int 21h mov ah,09h ;pranesimas apie sekminga darbo atlikima lea dx,msg2 int 21h pabaiga: ;Perduodame valdyma DOS operacinei sistemai mov ah,4Ch int 21h main endp ;==Duomenu failo klaidos apdorojimas == klaidaF proc near mov ah,09h lea dx,klaidaD int 21h jmp pabaiga ret endp klaidaF ;Procedura tikrina ar teisingai ivestas raidziu diapazonas parametre raidziu_tikrinimas proc near cmp cl,ch ja reziai cmp cl,122 ja reziai cmp cl,65 jb reziai cmp cl,90 ja pap_rez jmp galas2 pap_rez: cmp cl,97 jb reziai jmp galas2 reziai: mov ah,09h lea dx,KlaidaR int 21h jmp pabaiga galas2: ret endp raidziu_tikrinimas ;Jeigu vieno zodzio pasikartojimu kiekis virsija riezius virsija_riezius proc near push ax push dx cmp bx,270Fh ja pranesimas jmp galas1 pranesimas: mov ah,09h lea dx,klaida1 int 21h jmp pabaiga galas1: pop dx pop ax ret endp virsija_riezius ;Procedura kuri praleidzia tarpus, parametru pradziuoje trinti_tarpus proc near triname_tarpus: cmp ES:[si],byte ptr 20h jne pasibaige_tarpai inc si jmp triname_tarpus pasibaige_tarpai: ret endp trinti_tarpus ;=16-ainio skaiciaus konvertacija i 10-aini hex2dec proc near xor ax,ax ;apnuliname ax registq xor dl,dl xor cx, cx ;apnuliname regista cx (jame saugosime rezultato skaitmenu kieki) mov ax,bx ;priskiriame registrui AL ilgiausio zodzio kieki (nes reg. Al saugosime dalybos rezultata, o liekana AH) mov dl,10 ;reg. DL saugome dalykli cycle2: div dl ;daliname registra al is dl reiksmes; inc cx ;didiname skaitmenu kieki vienetu cmp al,0 ;tikriname ar liko tik 1 skaimuo je skait1 ;jei 1 skaitmuo, tai pereiname i slait1 zyme xor bx,bx ;jei ne, tai daliname kol dalybos rezultatas netaps lygys nuliui mov bl,ah ;liekana ikarauname BL registra push bx ;liekana ikeliame i steka xor ah,ah jmp cycle2 ;griztame prie zyme "cycle2" skait1: xor bx,bx mov bl,ah push bx ;paskutini skaitmeni ikeliame i steka ivedimas: cmp cx,4 ;ar FFFF? je irasome mov byte ptr[si],'0' inc si cmp cx,3 ;ar FFF? je irasome mov byte ptr[si],'0' inc si cmp cx,2 ;ar FF? je irasome mov byte ptr[si],'0' inc si irasome: cmp cx,0 ;tikriname ar neisvestu skaitmenu kiekis lygus nuliui je galas ;jei taip, tai baigiame programa pop bx add bx,30h ;pridedame 30h, kad gautumeme korektiskai atvaizuota skaiciaus simbli mov byte ptr[si],bl dec cx inc si jmp irasome galas: ret hex2dec endp ;==Masyvo elementu rikiavimas mazejanciai rikiavimas proc near lea bx,rezultatu ; masivo adresas ;mov cx,word ptr skaitliukas-1 ; elementu kiekis - 1 mov ch,byte ptr skaitliukas-1 mov cl,byte ptr [skaitliukas+1]-1 cyc1: push cx mov si,15 ;nustatome einamo elemento indeksa mov di,34 xor ax,ax mov ch,byte ptr skaitliukas-1 mov cl,byte ptr [skaitliukas+1]-1 ;lyginame tukstanciu ir simtu skaiciu cyc2: mov ax,word ptr [bx+si] ; imame elementa mov dx,word ptr [bx+di] ; ir sekanti cmp ax,dx ; lyginame juos ja _end_if ; jeigu pirmas didesnis sukeiciame juose je part2 jmp exchange ;lyginame desimciu ir vienetu skaiciu part2: mov ax,word ptr [bx+si+2] mov dx,word ptr [bx+di+2] cmp ax,dx jae _end_if ;=Elementu sukeitimas vietomis= exchange: push si ;perkeliame elementa i tarpini kintamaji push di push cx lea di,zodis ;i tarpinis sub si,15 add si,bx mov cx,13h rep movsb mov di,si ;2-as i 1-o vieta sub di,13h mov si,di add si,13h mov cx,13h rep movsb mov di,si ;tarpinis i 2 vieta sub di,13h lea si,zodis mov cx,13h rep movsb pop cx pop di pop si _end_if: add si,19 ; nurodome i kita elementa add di,19 loop cyc2 ; kartojame cikla pop cx loop cyc1 ; kartojame isorinis cikla ret rikiavimas endp cseg ends end main