Assebler pro blbe
Transkript
Assebler pro blbe
Assembler pro blbe Neda vno jsem narazil na perfektnıtext o assembleru a grafice. Prokousal jsem se tım a naucil se to. Myslım, z e to bude zajımat vıce lidı, takz e z toho vyrobım seria l na pokracova nı. Ra d bych upozornil, z e jsem taky zaca tecnık. Prosım tedy stare zkus ene Assemblerovske psy aby neva hali a radili a kritizovali. C asto pouz iju dvř instrukce mısto jedne, a o spoustř fint nema m urcitř ani tus enı. Oceka va m taky, z e mi va z enıctena ri budou psa t maily s poz adavky co nepochopili tak docela uplnř. Ra d svou rychlost prizp˚sobım vas emu cha pa nı. Takz e mř klidnř brzdřte. Popoha nřnı asi budete mıt marne, protoz e jsem docela blbej a nem˚z u va m to vysvřtlovat rychleji, nez se to stacım ucit. Takz e do toho skocıme rovnyma nohama: Registry Registry jsou nřco jako promřnne ve vys s ıch programovacıch jazycıch. Pr˚ser je ovs em v tom, z e je jich dost ma lo. Registry jsou vřts inou 16 bitove. Nřktere se dajı rozdřlit na dva 8mi bitove. Treba 16ti bitovy registr AX muz ete pouz ıvat jako dva 8mi bitove jmenem AL a AH. Kdyz vrazım do registru AX treba hodnotu 0ABCDh (zvyknřte si psa t pred hexa cıslici nulu, pokud to je pısmeno), bude AL obsahovat 0CDh a AH bude obsahovat 0ABh, jasan? Jestli ne, tak pis te, pis te. Takto m˚z ete rozp˚lit kaz dy registr, ktery koncıiksem. Dostenete potom dva kousky jeden H a jeden L Podıva me se, co tu ma me: AX - Takovy jeden nejpouzıvane jsıregistr. BX - Dalsıpodobny CX - Umıto co ti nad nım, ale navıc se pouzı va jako c ı tac ve smyc ce. DX - Poslednız třto c tverice DS, ES, CS, SS - Segmentovř registry. Viz da le SI, DI - Indexovř registry, pouzıvajıse pro pra ci s rete zci a poli. A pak je tu jes tř pa r dals ıch, ty si necha me az napak (az je pochopım) Segment & Offset: Kdyz kdysi da vno (kdyz na zemi vla dli dinosauri) pa ni na vrha ri vynalezali procesor Intel 8086, rozhodli se, z e ho vynaleznou tak, aby mřl 16ti bitove registry a aby s ırka jeho adresove sbřrnice byla 20 bit˚. Chvıli jen tak sedřli a byli ze sve geniality uplnř paf a pak se jeden z nich pos kra bal na hlavř a povıda : "Toz chlapi, sak to je na kř divnř ne?" "Esli ma me 20bitovu adresu, toz to mozeme mıt prı stup k jednřmu megabajtovi, fı ııha toz to ja." "Ale chlapi esli ma me v jednřm registru enřm 16 bitu, tak sa k temu nemozeme nijak dostaŠ. S ak 16bitu to stac ıenřm na 64 kilobajtu." Tak zase chvilku sedřli, nervoznř krcili pocıtacove sjetiny, az jeden na to ka pnul: "Ja to ma m, na prı stup k pame ti pouzijeme registry dva!" Jak rekli, tak udřlali, ale udřlali sloz itř. Predstavte si pamřň jako radu pamřň ovych bunřk. Tyto bunky jsou ocıslova ny od 0 po 0FFFFFh, je to celkem megabajt. Pokud chcete zjistit hodnotu, ktera je uloz ena na nřktere adrese, m˚z ete rıct treba, z e chcete hodnotu z ad resy 1ABCh. To m˚z ete rıct vy, ale ne procesor. Ten ma celou pamřň rozdřlenou na kusy o velikosti s estnacti bajtu. Kdyz pristupujete na nřjakou adresu uda te nejdrıve cıslo one s estna ctice. To je tzv Segment, jako druhy udaj doda te offset, coz je posunutı od zaca tku va mi zadaneho segmen tu. Sıla co? Takz e treba adresa 0000:0000 (Segment a Offset se od sebe oddřlujıdvojteckou) je vlastnř adresa 0. Adresa 0000:0100h, je totez jako "prıma adresa 0100h. Ovs em tuto adresu m˚z ete zapsat take jako 0001:00F0h a nebo 000A:0060h, vs echny tyto adresy ukazujı na stejne mısto, tedy na 0100h bunku pamřti. Skutecnou adresu zıska te takto: 16*Segment+Offset Naucte se tyto adresy neprepocıta vat, naucte se myslet v segmentech a offsetech. Toto je ta nejtřz s ı ca st strojoveho programova nı. Takz e prvnıch par instrukcı: MOV AX, 0FFFFh Do registru AX uloz ı hodnotu 0FFFFh MOV AX, BX Hodnotu,ktera je v registru BX, zkopıruje do AX (AX = BX) MOV AX, [0000:1234] Hodnota ktera je uloz ena v pamřti na adrese 0000:1234 se zkopıruje do AX (AX=Mem[0000:1234]) MOV AX, [1234] Je to totez jako vys e, ale nenı zde zada n segment. V takovem prıpadř se segmentova ca st adresy vezme z registru DS (Data Segment) (AX=Mem[DS:1234]) MOV AX, [CS:1234] Opřt stejne, ale tentokra t jsem prımo uvedl, z e segmentovou ca st chci vzıt z registru CS (Code Segment) MOV AX, [DS:SI] Jasne z e? Segmentova ca st je v DS a offset je v SI. Vs imnřte si, z e AX je 16bitovy registr. Obsahem pamřň oveho mısta je ovs em bajt, tedy 8 bit˚, takz e takoveto prirazenı nacte bajt ze zadane adresy ten uloz ıdo AL a nacte bajt z adresy+1 a uloz ıjej do AH. TeÍ si predvedeme hra tky s registrem CX. Tento registr se kromř jineho pouz ıva jako cıtac. Existuje instrukce LOOP, ktera zmens ı CX o jednicku a pokud nenı nulovy, skocına zadane na vřs tı, takz e treba: mov SMYCKA: cx, 100 ;Smycku budu opakovat stokrat. ;Navestı, sem se budu vrhat ;Tady neco pocıtam, atd... ble, ble, ble ble ble ble, ble a furt pryc loop SMYCKA ;A znova dokola, stokrat. A co treba indexove registry: Budu chtıt znulovat oblast pamřti velkou 100 bajt˚ od adresy 100:200h mov ax, 100h ;Do DS nemuzu priradit hodnotu primo mov ds, ax ;musim pres druhy registr mov di, 200h ;ted mi DS:DI ukazuje na prvnı bajt ; nulovanů oblasti mov ax, 0 ;Nuluju, tak je to nula mov cx, 100 ;Nuluju 100 bajtu Nuluj: mov [ds:di], ax ;Vrazim nulu na adresu DS:DI inc di ;A posunu se na dalsı adresu loop Nuluj ;To celů stokrat Jasan? Indexovy registr je vlastnř ukazatel v ra mci jednoho segmentu. Dıky tomu, z e je to registr a jeho hodnota se tedy m˚z e mřnit, m˚z u stejnym programem adresovat r˚zna mısta. C asem pozna te i vykonřjs ı instrukce, ktere dřlajı hromadu vřcına jeden prıkaz. Mym dnes nım za mřrem je uka zat, z e je stroja k rychlejs ı nez cokoliv, takz e zkusme vyrobit stras nř rychle presouva nı pamřti. ============================================================= .MODEL SMALL .CODE .386 Obrazovka dw 0B800h ;adresa bloku v pameti Kusanec dw 1000 ;Kolik 4bajtu b udu presouvat Kus2 dw 2000 ;Kolikrat budu sunout START: ;Tady zacina program mov cx, [cs:Kus2] mov ds, [cs:Obrazovka] mov es, [cs:Obrazovka] Smycka: push cx mov si, 2 ;DS:SI odkud presouvam mov di, 0 ;ES:DI kam presouvam mov cx, [cs:Kusanec] ;Kolik presouvam rep movsd ;CXkrat presunu [ES:DI] = [DS:SI] pop cx loop Smycka mov ax, 4c00h ;Konec programu, navrat do DOSu int 21h END START ===================================================================== Tu cast, ktera je mezi rovnitkovymi carami, vykopirujte do samostatneho fajlu. Dejte mu priponu ASM a predhodte jej assemblerovi. TASM.EXE nazev TLINK.EXE nazev.OBJ A je z toho EXE. Udelejte si batak, ktery tento program spusti alespon desetkrat. Ted si napiste ve vasem oblibenem vyssim programovacim jazyku program, ktery presune 2000krat 4000bajtu z adresy 0B800:0002 na adresu 0B800:0000. To je to, co dela programek nahore. Vyrobte batak na 100 opakovani a merte. Takze co to vlastne dela. .MODEL SMALL Podle toho, jak velky bude vas program, reknete kopileru jaky ma pouzit pametovy model. Pouzivame model SMALL. To znamena, ze budu pouzivat po jednom segmentu pro kod a pro data. .CODE Takto je oznacen zacatek CS. DOS pri spusteni programu nastavi CS, aby ukazoval zde. .386 Budou se pouzivat instrukce pro procesor 386 a vyse. Je to tam kvuli instrukci MOVSD. Tuto instrukci nizsi procesory neumi. Pokud nezadate tuto direktivu, predpoklada kompilator, ze se preklada pro 8086 a na radku s instrukci MOVSD oznami, ze procesor, ktery je nyni zvolen tuto instrukci neumi. Obrazovka Kusanec Kus2 dw dw dw 0B800h 1000 2000 ;adresa bloku v pameti ;Kolik 4bajtu budu presouvat ;Kolikrat budu sunout Toto je definice pametovych promennych. Vyrabim tri promenne. Obrazovka, Kusanec a Kus2. Zaroven jim prirazuji misto v pameti a pocatecni hodnotu. DW znamena Define Word, promenne je vyhrazen jeden word, tedy dva bajty. Do techto dvou bajtu se ulozi hodnota uvedena za dw. START: Misto odkud ma zacit vykonavani programu, se oznacuje takto. Ted trochu predbehnu. Nejdrive si vysvetleme jak funguje instrukce MOVSD. Tato instrukce presouva v pameti jeden Double Word, tedy ctyri bajty. Presouva se z adresy urcene DS:SI na adresu v ES:DI. Jako pomucka pro zapamatovani je tu SI - Source Index (zdrojovy index) a DI - Destination Index (cilovy index). Po presunu tato instrukce posune oba ukazatele dale prave o ctyri bajty. Opakovanim teto instrukce muzete tedy presouvat souvisly usek pameti. Opakovani zajistuje instrukce REP. Ta provede instrukci uvedenou jako argument, snizi CX o jednicku, je-li CX <> 0, opakuje cely postup, provede, snizi, atd.. Takze danou instrukci provede tolikrat, kolik je zadano v registru CX. Krome MOVSD, existuje i MOVSB - presouva jeden bajt, a MOVSW - presouva Word, neboli dva bajty. Tyto instrukce posouvaji ukazatele o jeden, nebo dva bajty. Zbytek programu slouzi pouze pro naplneni registru spravnymi hodnotami. Program ma postupne odrolovat celou textovou obrazovku po jednom znaku. Textova obrazovka obsahuje 80x25 znaku. To je celkem 2000 znaku. Znaky jsou ulozeny jako ASCII hodnoty ve videopameti v segmentu 0B800h. Za ASCII hodnot ou kazdeho znaku nasleduje jeden bajt, ktery obsahuje informace o barve daneho znaku. Pro kazdy znak vychazi tedy dva bajty. Znaku je 2000. Tedy pujde o 4000 bajtu. Posun musime provadet o dva bajty. Pokud bychom posouvali o bajt, posun uli bychom ASCII na barvu a barvu na ASCII. mov cx, [cs:Kus2] Jak jsme si rekli MOVSD presouva CXkrat, takze do CX si dame pocet znaku na obrazovce, abychom odscrolovali prave vsechny znaky. mov mov ds, es, [cs:Obrazovka] [cs:Obrazovka] Presouvame z 0B800:0002 na 0B800:0000, tyto dve hodnoty musime nacpat do ES:DI a DS:SI. Zde plnim DS a ES, oba stejne hodnotou 0B800h. Smycka: Takto se oznacuje navesti, tedy misto, na ktere se budu v programu odkazovat. Treba sem budu skakat odjinud. push cx Registr CX ulozim do zasobniku, protoze budu jeho hodnotu menit. mov si, 2 ;DS:SI odkud presouvam mov di, 0 ;ES:DI kam presouvam Toto jsou ona dve posunuti ve zdrojove a cilove adrese. Ted uz mam v DS:SI = 0B800:0002 a v ES:DI = 0B800:0000. mov cx, [cs:Kusanec] Uvnitr hlavni smycky, ktera zajistuje, ze probehne 2000krat scroll, je jeste druha ktera zajistuje, ze kazdy scroll se sklada z 1000 presunu ctyr bajtu. Ted tedy zahajuji tuto vnitrni smycku. Proto jsem si pred chvili ulozil CX na zasobnik abyc h neprisel o pocitadlo z vnejsi smycky. Az skonci vnitrni smycka, vytahnu si pocitadlo ze zasobniku abych mohl odpocitat vnejsi smycku. rep movsd A uz to frci. 1000 presunu ctyr bajtu pamet-pamet. pop cx Vytahuju pocitadlo pro vnejsi smycku ze zasobniku. loop Smycka prikaz LOOP funguje podobne jako REP. Snizi CX o jednicku a pokud neni CX=0, skoci na zadane navesti. mov int ax, 21h 4c00h Tyto dve instrukce jsou standardni konec, kazdeho EXE. Budou soucasti kazdeho vaseho programu. END START Konec casti START. Minule jsem zacal trosku slozitejsim prikladem, takze ted se vratime zpatky na zem a zacnu klasickym Hello World. Tedy programem, ktery na obrazovce vypise napis "Hello World". MODEL SMALL .STACK 200 .DATA Napis db 'Hello World$' .CODE START: mov ax, seg Napis ;DS:DX ukazuje na napis mov ds, ax mov dx, offset Napis ;DS:DX ukazuje na text mov ah, 9 ;funkce zobraz retezec int 21h mov ax, 4c00h ;Konec programu, navrat do DOSu int 21h END START Objevuje se nam tu poprve volani sluzby DOSu. To je to int 21h. Je to vyvolani preruseni cislo 21h. Muzete si to predstavit jako vyvolani nejake procedury cislo 21h. Tato procedura potrebuje parametry, aby vedela co ma delat. V nasem pripade jsou to parametry dva. V AH zadame cislo sluzby. V nasem pripade 9 coz znamena vystup retezce. V DS:DX je ulozena adresa tohoto retezce. Retezec se ukoncuje znakem $. Prikaz mov ax, seg Napis ulozi do ax segmentovou cast adresy promenne Napis. mov dx, offset Napis ulozi do dx cast offsetovou. Preruseni int 21h umi spoustu veci, ktere by se musely jinak programovat rucne. Umi to napriklad otevirat, cist a zapisovat soubory. Spoustet dalsi programy. Cist klavesnici, psat po obrazovce, atd... Toto preruseni se vyvolava vzdy s cislem sluzby v AH a dalsimi parametry v ostatnich registrech. Ukazeme si napriklad vyuziti sluzby cislo 30h (Zjisti verzi DOSu) MODEL SMALL .STACK 200 .DATA Napis db 'Cislo verze DOSu je: $' .CODE START: mov ax, seg Napis ;DS:DX ukazuje na napis mov ds, ax mov dx, offset Napis ;DS:DX ukazuje na text mov ah, 9 ;funkce zobraz retezec int 21h mov ah, 30h ;funkce 30, zjisti verzi int 21h ;Hlavni cislo verze je ted v al add al, 48 ;prictu 48, abych dostal ascii kod cisla mov dl, al mov ah, 2 ;funkce tisk jednoho znaku z DL int 21h mov ax, 4c00h ;Konec programu, navrat do DOSu int 21h END START Sezente si nekde program jmenem SYSMAN, to je hypertext prave o takovych vecech. Mimo jine je tu i seznam vsech techto preruseni. Dozvite se, co musite kam strcit a co, po skonceni INT, kde hledat. Muzeme se treba podivat na praci se souborem: Odkazy na soubor probihaji pomoci veci, ktera se jmenuje FileHandle. Je to 16-ti bitove cislo. DOS ma nekde v pameti tabulku ve ktere ma ulozeny vsechny dulezite udaje o souboru. Aktualni pozici, jeho velikost, atd... FileHandle je potom ukazatel do teto tabulky. Zadate-li v CONFIG.SYS FILES=20, rikate tim dosu, aby si v pameti vyhradil misto na tabulku pro 20 souboru. OTEVRENI SOUBORU: Vstup: AH = 3Dh AL = mod otevreni bity 7-3 = Nezajimave veci bity 2-0 = Zpusob pristupu 000 jen pro cteni 001 jen pro zapis 010 cteni i zapis DS:DX = ukazatel na jmeno souboru v ASCIIZ ASCIIZ je text v normalnim ASCII ukonceny bajtem 0. Vystup: CF = 1 chyba AX = cislo chyby, nam staci, ze pokud je nastaveno carry, nepodarilo se otevrit soubor CF = 0 bez chyby AX = FileHandle, toto si nekam ulozte, to je jedina cesta jak muzete pracovat s timto souborem! UZAVRENI SOUBORU Vstup: AH = 3Eh BX = FileHandle Vystup: CF = 1 Chyba CTENI SOUBORU Vstup: AH = BX = CX = DS:DX = Vystup: 3Fh FileHandle Pocet nacitanych bajtu. Ukazatel do pameti, kam maji byt umistena nactena data. AX = Kolik bajtu bylo nacteno. ZAPIS DO SOUBORU Vstup: AH = BX = CX = DS:DX = Vystup: 40h FileHandle Kolik bajtu zapsat Kde jsou v pameti data, ktera maji byt zapsana na disk. AX = Kolik bajtu bylo zapsano, jestli se to lisi od pozadovaneho poctu, mame nekde chybu. VYTVORENI SOUBORU Vstup: AH = 3Ch CL = atribut souboru bit bit bit bit bit bit bit 0: read-only 1: hidden 2: system 3: volume label 4: sub directory 5: Archive 6&7: nepouzivat DS:DX= ukazatel na ASCIIZ nazev vytvareneho fajlu Vystup: CF = 1 chyba AX = kod chyby CF = 0 bez chyby AX = FileHandle SMAZANI SOUBORU Vstup: AH = 41h DS:DX = ukazatel ne ASCIIZ jmeno fajlu Vystup: CF = 1 chyba AX = kod chyby 2 = file not found, 3 = path not found 5 = access denied CF = 0 bez chyby, soubor je pryc PRESUN UKAZATELE V SOUBORU Vstup: AH = 42h BX = FileHandle CX:DX = 32 bit ukazatel do souboru, kam se bude sunout. AL = 0 CX:DX je posun od zacatku fajlu. = 1 CX:DX je posun od aktualni pozice. = 2 CX:DX je posun od konce souboru. Vystup: CF = 1 chyba AX = chybovy kod CF = 0 bez chyby, posunuto. DX:AX soucasna pozice v souboru. ZMENA ATRIBUTU Vstup: AH = 43h DS:DX = ukazatel na jmeno souboru v ASCIIZ AL = 0 v CX vrati aktualni atributy. AL = 1 nastavi atributy podle CX Vystup: CF = 1 chyba AX = Chybovy kod 2 = file not found, 3 = path not found. 5 = access denied CF = 0 bez problemu Jak jsem minule slıbil, zkusıme si vyrobit program pro konverzi ces tiny. Prvnı na vrh vypadal asi takto: MODEL SMALL .STACK 200 .DATA FTabulka db 'TABULKA.TAB',0 ;nazev prev. tabulky FVstup db 'VSTUP.TXT',0 ;nazev vstupniho fajlu FVystup db 'VYSTUP.TXT',0 ;nazev vystupniho fajlu FH2 dw 0 ;filehandle vstupniho FH2 dw 0 ;filehandle vystupniho MTabulka db 256 DUP (0) ;sem se nacte tabulka Buffer db 30000 DUP (0) ;buffer pro nacitana data .CODE START: Tabulka ;Nactu prevodni tabulku Otevri ;Otevru zdroj Vytvor ;Vytvorim cil Smycka: Nacti ;Nactu do bufferu kus textu Preved ;Prevedu jej Zapis ;Zapisu prevedeny text do fajlu jne Smycka ;a furt dokola, cely soubor Zavri1 ;Zavru zdrojovy Zavri2 ;Zavru cilovy mov ax, 4c00h ;Konec programu, navrat do DOSu int 21h END START Je to vlastnř hruby na vrh. Vypada to, z e by to takto mohlo fungovat, teÍ zbyva "jenom" naprogramovat jednotlive procedury. Procedura je kus kodu zacınajıcı prıkazem PROC. Za nım je uveden na zev procedury, pak na sledujı norma lnı assemblerovske prıkazy a cele to koncı prıkazem ENDP a za nım opřt na zev procedury. Takz e treba procedura, ktera pricte jednicku k AX (mimochodem přkna kravina). PROC Pricti inc ax ret ENDP Pricti Potom m˚z ete uvest v hlavnım programu prıkaz call Pricti, ktery zp˚sobı zvys enıax o jednicku. Prıkaz call je vola nı procedury. D˚lez ita je instrukce ret, ktere zp˚sobına vrat z procedury. Jes tř bych mřl vysvřtlit co dřla DUP. MTabulka db 256 DUP (0) zp˚sobı, z e promřnna MTabulka bude zpoca tku obsahovat 256 nul. Zacneme vyrobou procedury Tabulka, ta ma za ˚kol nacıst ze souboru prevodnıtabulku do pamřti. Takz e otevrenı souboru, nactenı 256 bajt˚ (to je cela tabulka) a uzavrenısouboru. PROC Tabulka mov ax, mov dx, int 21h mov push mov mov mov int bx, bx ah, cx, dx, 21 3D00h offset FTabulka ;Otevreni sou boru, read only ;DS:DX ukazuje na nazev fajlu ax ;filehandle do bx ;uschovat na pozdeji ;cteni souboru ;FF bajtu (256) ;DS:DX kam nacist 3Fh 0FFh offset MTabulka pop bx mov ah, 3Eh int 21 ret ENDP Tabulka Dals ıje Otevri a Vytvor, mřlo by to byt lehke. PROC Otevri mov ax, 3D00h mov dx, offset FVstup int 21h mov FH1, ax ret ENDP Otevri ;vyndat uschovane filehandle ;zavre ni souboru ;Otevreni souboru, read only ;DS:DX ukazuje na nazev fajlu ;schovat filehandle PROC Vytvor mov ah, 3Ch ;Vytvoreni souboru mov cl, 0 ;Zadny specialni atribut mov ds offset FVystup ;DS:DX jmeno vyrabeneho fajlu int 21h mov FH2, ax ;Schovat filehandle ret ENDP Vytvor Procedura Nacti by mřla vz dy nacıst do bufferu bajty ze vstupnıho souboru. Kdyz jich nactu menř, nez jsem zadal, znamena to, z e jsem na konci souboru. PROC Nacti mov bx, FH1 ;filehandle do bx mov ah, 3Fh ;cteni souboru mov cx, 30000 ;30000 bajtu, cely buffer mov dx, offset Buffer ;DS:DX kam nacist int 21 push ax ;ulozit kolik bajtu bylo nacteno ret ENDP Nacti Dalsi procedura, prevadi podle tabulky. Tabulka je vlastnř 256 cısel. Jestliz e ma treba AL hodnotu 15, najde se v tabulce 15-ty udaj a ten se uloz ı do AL. Takz e tabulka, ktera neprova dı z a dny prevod, bude obsahovat postupku 0,1,2,3,4,5,6,7,8,9,10,11,....255. PROC Preved cld ;Ukazatele se budou zvysovat mov bx, offset MTabulka ;Ukazatel do tabulky mov si, offset Buffer ;Ukazatel do bufferu (cteni) mov di, si ;Ukazatel do bufferu (zapis) mov cx, ax ;Kolik bajtu budu prevadet xor ah, ah ;Znuluju AH Kolco: push bx ;Schovam si zacatek tabulky lodsb ;AL = [DS:SI] add bx, ax ;Posunu se v tabulce mov al, [ds:bx] ;Prevedu stosb ;Zapisu zpatky do bufferu pop bx ;Zase uk azuji na zacatek tab. loop Kolco ;a dalsi bajt bafru ret ENDP Preved Dals ıvřc je opřt jednoducha , za pis prevedeneho bufferu do fajlu. PROC Zapis mov ah, 40h ;Zapis fajlu mov bx, FH2 ;filehandle pop cx ;kolik bajtu zapsat push cx ;jeste se to bude hodit mov dx, offset Buffer ;Kde jsou zapisovana data int 21h ret ENDP Zapis Takz e to sepıs u dohromady a vykas lu se na procedury, jelikoz z a dnou z nich nevykona va m vıckra t, nemajısmysl a navıc jes tř prida vajı ret, coz je malilinkata ztra ta casu. MODEL SMALL .STACK 200 .DATA FTabulka db 'TABULKA.TAB',0 ;nazev prev. tabulky FVstup db 'VSTUP.TXT',0 ;nazev vstupn iho fajlu FVystup db 'VYSTUP.TXT',0 ;nazev vystupniho fajlu FH1 dw 0 ;filehandle vstupniho FH2 dw 0 ;filehandle vystupniho Buffer db 30000 DUP (0) ; buffer pro nacitana data MTabulka db 256 DUP (0) .CODE START: mov ax, seg FTabulka ;Nejdrive nastavim DS mov ds, ax mov es, ax ;A ES mov mov int ax, dx, 21h 3D00h offset FTabulka ;Otevreni souboru, read only ;DS:DX ukazuje na nazev fajlu mov push mov mov mov int bx, bx ah, cx, dx, 21h ax 3Fh 0FFh offset MTabulka ;filehandle do bx ;uschovat na pozdeji ;cteni souboru ;FF bajtu (256) ;DS:DX kam nacist pop mov int bx ah, 21h 3Eh ;vyndat uschovane filehandle ;zavreni souboru mov mov int mov ax, dx, 21h FH1, 3D00h offset FVstup ;Otevreni souboru, read only ;DS:DX ukazuje na nazev fajlu mov mov mov int mov ah, cl, dx, 21h FH2, 3Ch 0 offset FVystup ;Vytvoreni souboru ;Zadny specialni atribut ;DS:DX jmeno vyrabeneho fajlu ax ;S chovat filehandle FH1 3Fh 30000 offset Buffer ;filehandle do bx ;cteni souboru ;30000 bajtu, cely buffer ;DS:DX kam nacist ax ;schovat fil ehandle Smycka: mov bx, mov ah, mov cx, mov dx, int 21h push ax cld mov bx, mov si, mov di, mov cx, xor ah, Kolco: push bx lodsb add bx, mov al, ;ulozit kolik bajtu bylo nacteno offset MTabulka offset Buffer si ax ah ;Ukazatel do ;Ukazatel do ;Ukazatel do ;Kolik bajtu ;Znuluju AH tabulky bufferu (cteni) bufferu (zapis) budu prevadet ax [ds:bx] ;Schovam si zacatek tabulky ;AL = [DS:SI] ;Posunu se v tabulce ;Prevedu stosb pop bx loop Kolco mov mov pop push mov int ah, bx, cx cx dx, 21h pop ax cmp ax, jnb Smycka ;Zapisu zpatky do bufferu ;Zase ukazuji na zacatek tab. ;a dalsi bajt bafru 40h FH2 offset Buffer ;Zapis fajlu ;filehandle ;kolik b ajtu zapsat ;jeste se to bude hodit ;Kde jsou zapisovana data 30000 ;vytahnu si pocet nactenych bajtu ;byl to cely bafr? ;a furt dokola, cely soubor mov mov int ah, bx, 21h 3Eh FH1 ;zavreni fajlu ;filehandle mov mov int ah, bx, 21h 3Eh FH2 ;zavreni fajlu ;filehandle mov ax, 4c00h ;Konec programu, navrat do DOSu int 21h END START Vřts inu třchto instrukcızna te, zbyva vysvřtlit tri nove: LODSB NaplnıAL hodnotou, kterou vezme z [DS:SI], potom posune SI, tak, aby ukazoval na dals ı bajt. BuÍto jej zvys ı, nebo snız ı o jednicku. Jestli se bude zvys ovat, nebo sniz ovat, za lez ına nastavenı DF (Direction Flag), DF je prıznak, kterym smřrem probıhajı takoveto operace. STOSB Obra cena instrukce k LODSB. Uloz ı AL do pamřti na adresu urcenou ES:DI a pote opřt upravıukazatel (v tomto prıpadř DI), buÍ jej zvys ı, nebo snız ı. CLD Tohle je pra vř to co urcuje, jestli se ukazatele budou zvys ovat, nebo sniz ovat. Tımto prıkazem nastavıte DF, tak, aby se ukazatel zvys oval. Pro nastavenına sniz ova nıje instrukce STD. Aha jak se tak dıva m, tak ono je tu novřjs ıch vřcı vıc, takz e: ZA SOBNI K Za sobnık je kus pamřti slouz ıcık odkla da nı udaj˚. Hlavnı pouz itı bude asi pro uchova va nı na vratovych adres pri skoku do podprogramu. Jestliz e je nřkde v programu instrukce CALL (vola nıpodprogramu) provede procesor na sledujıcı akce: 1. 2. 3. Uloz ı si do za sobnıku na vratovou adresu, tedy adresu instrukce, ktera na sleduje po instrukci call. Skocı do podprogramu, tento prova dı, az narazı na instrukci RET Vyta hne ze za sobnıku na vratovou adresu a skocı na ni, tedy pokracuje ve vykona va nıza instrukcı call. Za sobnık je pamřň typu LIFO (Last In First Out), to znamena , z e, to co tam da te naposledy vyta hnete jako prvnı. Predstavte si to jako hromadu hlinřnych desticek. Tu kterou poloz ıte jako poslednına hromadu, musıte zvednout jako prvnı. V pamřti je to ale tak, z e desticky prida va te dospodu stohu. Takto vypada zjednodus enř Stack Segment (SS) tedy ca st pamřti, kde se nacha zı za sobnık. Na vrs ek hromady ukazuje SP (Stack Pointer). FFFFh X5 nejstarsı polozka zasobnıku X4 druha nejstarsı X3 X2 X1 <---- Sem ukazuje SP 0000 Jestliz e nřco do za sobnıku prida te, vrazı se to dospodu a SP se SNIZI. Po vytaz enıze za sobnıku se SP opřt ZVYSI. Pro uloz enı hodnoty na za sobnık slouz ıinstrukce PUSH. Jejım argumentem je vřts inou s estna ctibitovy registr. Takz e treba PUSH AX uloz ıobsah AX do za sobnıku. opakem PUSH je POP, ktera hodnotu vyjme, takz e POP AX vezme poslednı hodnotu, ktera byla uloz ena na za sobnık a uloz ı ji do AX. Takz e finta pro prohozenı dvou registr˚: PUSH AX ;na vrsku zasobniku je AX PUSH BX ;na vrsku zasobniku je BX POP AX ;BX z vrsku jsem presunul do AX POP BX ;vyjmutim BX se na vrsek dostalo AX a to dam do BX Za sobnık je svinř a pokud s nım chcete kouzlit, buÍte hodnř opatrnı, je to jedna z lehcıch cest, jak si resetnout pocıtac. Uffff!!!