%include "rw32-2015.inc" ; ; windows extern hack - "_" verze jsou cdecl ; macro pod windowsem vymeni standardni nazvy sa "_" nazvy a deklaruje existenci spravnych symbolu ; %ifnmacro CEXTERN %define CEXTERN extern %endif ; funkce pro otevreni a uzavreni souboru CEXTERN fopen CEXTERN fclose ; funkce pro nacteni a spracovani dat CEXTERN qsort CEXTERN fscanf ; funkce pro dynamicky alokovanou pamet CEXTERN malloc CEXTERN free ; maximalni delka nacteneho radku ze souboru %define ROW_LEN 80 %defstr ROW_LEN_STR ROW_LEN ; maximalni delka cesty k souboru %define FILENAME_LEN 32 ; ; datovy segment ; section .data rezim_souboru db "r",0 format_pocet db "%u",0 format_radku db "%u;%",ROW_LEN_STR,"[^",13,10,"]",0 ; chybove hlasky re_otevreni db "Nepodarilo se otevrit soubor",EOL,0 re_precteni db "Neplatny format souboru",EOL,0 re_alokace db "Nepodarilo se alokovat pamet",EOL,0 section .bss ; misto pro nazev souboru, vcetne ukoncovaci nuly nazev_souboru resb FILENAME_LEN+1 ; ; kodovy segment ; section .text ; Funkce main vyuziva knihovnu jazyka C k nacteni souboru, manipulaci s daty a jejich vypsani. ; Po precteni prvniho radku, na kterem je pocet zbyvajicich radku je alokovana potrebna pamet. ; Pote je cely obsah souboru nacten, pricemz vstup se sklada z bezznamenkoveho cisla a retezce. ; Toto cislo udava pozici, na ktere by radek mal byt. Tzn. serazenim a vypsanim vysledku je ; obdrzen vysledek. ; ; Priklad vstupniho souboru: ; 2 ; 5;aa ; 3;bb ; ; Vystup pro dany vstup: ; bb ; aa ; ; Jak je mozne videt, vstupni radky jsou serazeny podle cisla na jejich zacatku, ktery slouzi jako ; klic. Toto cislo neni soucasti vystupu. Delka retezce za oddelovacem ';' je limitovana makrem ; ROW_LEN vyse. main: ; vytvorime si misto pro lokalni promenne ; [ebp- 4] soubor -- FILE* (fopen) ; [ebp- 8] pocet_radku -- unsigned int, 4B siroky ; [ebp-12] data -- void* (malloc) push ebp mov ebp,esp sub esp,12 ; nacteme nazev souboru pomoci ReadString v rw32 mov ebx,FILENAME_LEN mov edi,nazev_souboru call ReadString .otevri_soubor: ; otevreme soubor ; FILE *fopen(const char *path, const char *mode); push rezim_souboru push nazev_souboru call fopen add esp,8 mov [ebp-4],eax ; ulozeni vysledku ; kontrola navratove hodnoty a osetreni chyb test eax,eax jnz .nacti_pocet_radku ; chyba - nepodarilo se otevrit soubor mov esi, re_otevreni call WriteString jmp .konec .nacti_pocet_radku: ; nacteme pocet radku, tato informace se nachazi na prvnim radku souboru ; int fscanf(FILE *stream, const char *format, ...); lea ebx,[ebp-8] push ebx ; &pocet_radku push format_pocet ; formatovaci retezec push dword [ebp-4] ; soubor call fscanf add esp,12 ; kontrola navratove hodnoty a osetreni chyb cmp eax,1 ; fscanf vraci pocet uspesne nactenych promennych je .spocti_potrebnou_pamet ; chyba - nepodarilo se nacist pocet radku v souboru mov esi, re_precteni call WriteString jmp .uzavri_soubor .spocti_potrebnou_pamet: ; na kazdy radek potrebujeme 4 (cislo) + ROW_LEN (max. delka retezce) bajtu mov eax,4+ROW_LEN ; velikost jednoho radku mul dword [ebp-8] ; vynasobime poctem radku ; vysledek v edx:eax, kontrola preteceni test edx,edx jz .alokuj ; chyba - pocet radku je prilis velky, nestaci nam 4GB pameti mov esi, re_precteni call WriteString jmp .uzavri_soubor .alokuj: ; v registru eax mame ulozenou potrebnu velikost ; void *malloc(size_t size); push eax ; alokovana pamet call malloc add esp,4 mov [ebp-12],eax ; ulozeni vysledku - ukazatel na ziskanou pamet ; kontrola navratove hodnoty a osetreni chyb test eax,eax jnz .nacti_radky ; chyba - nepovedlo se nam alokovat pamet mov esi, re_alokace call WriteString jmp .uzavri_soubor .nacti_radky: ; ukol 1: dopiste kod pro nacteni radku zo souboru do alokovane pameti ; ; [ebp-4] - FILE* soubor ; [ebp-8] - pocet radku (a iteraci cyklu) ; [ebp-12] - ukazatel na alokovanou pamet ; format_radku - formatovaci retezec ; ; Z kazdeho radku souboru je nacteno 4B cislo bez znamenka (unsigned int) a retezec, ktereho ; delka je maximalne ROW_LEN. Ulozte tyto data do pameti jako pole struktur, tzn. ;