Kompiuterių architektūra/Antroji praktinė užduotis/Žodžių rikiavimas abėcėles tvarka

Iš MIF SA Wiki.

Peršokti į: navigaciją, paiešką

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
Asmeniniai įrankiai