;14LoadAl.asm ; Program demonstruje funkci instrukce LOADALL v procesoru 80286. ; Pro spravnou funkci programu musi byt zapnuta brana A20. Viz 15A20. ; Program lze spustit na procesoru min. 80286. .286p DATA SEGMENT PUBLIC 'DATA' ; ; Tabulka pro LOADALL 80286 ; LOADALL_Tbl dw 3 dup (0) ; nepouzito ObsahMSW dw 0 dw 7 dup (0) ; nepouzito ObsahTR dw 0 ObsahF dw 0 ObsahIP dw 0 ObsahLDT dw 0 ObsahDS dw 0 ObsahSS dw 0 ObsahCS dw 0 ObsahES dw 0 ObsahDI dw 0 ObsahSI dw 0 ObsahBP dw 0 ObsahSP dw 0 ObsahBX dw 0 ObsahDX dw 0 ObsahCX dw 0 ObsahAX dw 0 ObsahESnev dw 0, 9200h, 0FFFFh ObsahCSnev dw 0, 9200h, 0FFFFh ObsahSSnev dw 0, 9200h, 0FFFFh ObsahDSnev dw 0, 9200h, 0FFFFh ObsahGDTR dw 0, 0, 0 ObsahLDTnev dw 0000h, 0FF0Eh, 88h ObsahIDTR dw 0, 0, 0 ObsahTSSnev dw 0100h, 0FF0Eh, 800h ; Konec tabulky pro LOADALL 80286 Uloz102 db 102 dup(?) ; Oblast pro puvodni obsah 80h:0 ; Pomocne promenne pro instrukce SGDT a SIDT. gdtr_n dq 0 idtr_n dq 0 DATA ENDS ; STKSEG SEGMENT STACK 'STACK' DB 1024 DUP(?) ; Hloubka zasobniku je 1KB. STKSEG ENDS ; CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,SS:STKSEG,DS:DATA PlnNev PROC NEAR ; Podprogram naplni podle obsahu AX (kde je ; segment podle pravidel realneho rezimu) ; bazi neviditelne casti, jejiz adresa je ; ulozena v DS:DI. push AX shl AX,4 mov WORD PTR [DI],AX pop AX shr AX,12 mov BYTE PTR [DI+2],AL ret PlnNev ENDP PlnDT PROC NEAR ; Podprogram naplni podle obsahu 3slovni ; promenne z adresy DS:SI, ziskane instrukci ; SGDT nebo SIDT, polozku tabulky LOADALL ; na adrese DS:DI jako obsah GDT nebo IDT. mov AX,[SI] mov [DI+4],AX ; limit mov AX,[SI+2] mov [DI],AX ; 2 nejnizsi slabiky baze mov AX,[SI+4] xor AH,AH mov [DI+2],AX ; 1 slabika baze a nulova slabika ret PlnDT ENDP PlnTab PROC NEAR ; Podprogram naplni tabulku pro LOADALL 80286 ; podle soucasneho stavu procesoru. pusha ; Uloz vsechny vseobecne registry. push ES push DS mov ObsahAX,AX mov ObsahCX,CX mov ObsahDX,DX mov ObsahBX,BX mov ObsahBP,BP ; SP lze ulozit az v okamziku, kdy je zasobnik prazdny. mov ObsahSI,SI mov ObsahDI,DI mov ObsahES,ES mov ObsahCS,CS mov ObsahSS,SS mov ObsahDS,DS ; Nyni se budou plnit 24bitove baze neviditelnych casti ; segmentovych registru. mov AX,ES mov DI,OFFSET ObsahESnev call PlnNev mov AX,CS mov DI,OFFSET ObsahCSnev call PlnNev mov AX,SS mov DI,OFFSET ObsahSSnev call PlnNev mov AX,DS mov DI,OFFSET ObsahDSnev call PlnNev ; Ulozeni registru priznaku. Musi mit IF=0 - preruseni musi zustat ; po obnoveni registru (po LOADALL) zakazano. cli cld nop nop pushf pop ObsahF sti ; Ulozeni stavoveho registru procesoru (v realnem rezimu!!) s PE=0. smsw AX and AX,0Fh ; Zajimaji nas pouze dolni 4 bity. mov ObsahMSW,AX ; Opiseme soucasny obsah registru GDT. sgdt QWORD PTR gdtr_n mov SI,OFFSET gdtr_n mov DI,OFFSET ObsahGDTR call PlnDT ; Opiseme soucasny obsah registru IDT. sidt QWORD PTR idtr_n mov SI,OFFSET idtr_n mov DI,OFFSET ObsahIDTR call PlnDT pop DS pop ES popa ret PlnTab ENDP Loadall PROC NEAR ; Podprogram podle obsahu DS:SI zkopiruje ; tabulku pro LOADALL a provede LOADALL 80286. cld ; Tabulku pro LOADALL zkopirujeme na spravne misto do pameti. mov AX,80H mov ES,AX xor DI,DI ; ES:DI := 80h:0 cli ; Zakazeme preruseni. mov CX,51 ; Velikost tabulky je 102 slabik. rep movsw ; Zkopirujeme 102 slabik. ; LOADALL db 0Fh, 5 ; Nyni jsme skocili na misto zadane CS:IP v tabulce. Loadall ENDP ; ;********************************************************************** PROCES PROC ; Toto je vstupni bod programu, sem se preda rizeni. ; Uchovejme 102 slabik od adresy 80h:0 na jine misto. mov AX,DATA ; Segmentovy registr ES naplnime segmentovou mov ES,AX ; casti adresy segmentu pojmenovaneho DATA. mov DI,OFFSET Uloz102 ; ES:DI := ukladaci oblast mov AX,80h mov DS,AX xor SI,SI ; DS:SI := 80h:0 mov CX,51 ; CX := 102 slabik rep movsw ; Prenes 102 slabik do ukladaci oblasti. ; Napln DS ukazatelem na data. mov AX,DATA ; Segmentovy registr DS naplnime segmentovou mov DS,AX ; casti adresy segmentu pojmenovaneho DATA. xor BX,BX ; Citac a offset vypisovanych znaku. DalsiZnak: ; Napln tabulku pro LOADALL soucasnym stavem procesoru. call PlnTab ; Proved korekce. mov AX,OFFSET PoLOADALL1 mov ObsahIP,AX ; Kam skocit po LOADALL. mov ObsahSP,SP ; Jaky stav zasobniku po LOADALL. mov BX,OFFSET ObsahESnev mov BYTE PTR [BX+0],00h mov BYTE PTR [BX+1],00h mov BYTE PTR [BX+2],11h ; Napln neviditelnou cast ; reg. ES bazi 110000h ; Proved LOADALL mov si,OFFSET LOADALL_Tbl ; Offset tabulky pro LOADALL. call LOADALL ; CALL nebo JMP - to je jedno. PoLOADALL1: ; Sem se preda rizeni po LOADALL. mov AL,ES:[BX] ; Vezmi znak z adresy 110000h:[BX] cmp AL,31 ; Je vetsi nez mezera? ja ZnakOK ; Ano, vypiseme jej. mov AL,' ' ; Neni, nahradime jej mezerou. ZnakOK: inc BX ; Zvys citac a ukazatel. mov AH,14 ; Vypis znak na obrazovku. int 10h ; Tato sluzba provedla jiste instrukce ; PUSH ES ; POP ES ; cimz (pri POP ES) byla naplnena jeho neviditelna ; cast podle realneho rezimu. Takze nyni tam jiz ; hodnota 110000h NENI !! mov AH,1 ; Byl stisknut nejaky znak? int 16h jz NeniZnak; Nebyl, pokracuj. mov AH,0 ; Byl, odeber jej. int 16h mov AH,0 ; A cekej na pokracovani (na stisk dalsiho znaku). int 16h NeniZnak: cmp BX,0 ; Uz jsme vypsali 64 KB? jne DalsiZnak ; Ne, pokracujeme naplnenim ESnev := 110000h ; Obnov oblast od adresy 80h:0. mov AX,80h mov ES,AX xor DI,DI ; ES:DI := 80h:0 mov SI,OFFSET Uloz102 ; DS:SI := Uloz102 mov CX,51 rep movsw ; Prenes 102 slabik. mov AH,4ch ; Konec programu (sluzbou MS-DOSu) a int 21h ; navrat do MS-DOSu. PROCES ENDP ;************************************************ CODE ENDS ; Konec programu. END PROCES