În mediul DOS din era 8086, afișarea textului se bazează de obicei pe generatorul de caractere încorporat al BIOS-ului și al adaptorului grafic, mai degrabă decât pe orice sistem sofisticat de renderizare a fonturilor.Fonturile erau strâns legate de modurile specifice de text implementate de adaptoare, cum ar fi CGA, EGA sau VGA.Unul dintre cele mai frecvente moduri a fost modul text 03h, care a prezentat o grilă de text de 80 × 25. Într-una dintre scufundările noastre anterioare, am explorat infamul și cum să integrați timerii hardware pentru a produce beeps simple cu De această dată, vom schimba aspectul unui caracter ASCII (în acest caz "A") prin redefinirea datelor pixelului său. VGA-Mode 13h PC Speaker ASCII și setul de caractere DOS ASCII (American Standard Code for Information Interchange) este inițial un cod de 7 biți care definește caractere (lettere, cifre, punctuație) în intervalul 0-127 .În DOS, setul ASCII extins standard (adesea numit Code Page 437) a adăugat un supliment de 128 de caractere (128-255), inclusiv caractere de desen în cutie, simboluri și alte glife utilizate frecvent în lumea DOS. Modul text 03h (80×25) Unul dintre modurile tipice de afișare utilizate în 8086 DOS pentru ieșirea textului este Modul 03h. În Modul 03h, ecranul este împărțit în 80 de coloane și 25 de rânduri de caractere text. care deține un caracter plus atribute (cum ar fi culorile de fundal și de fundal, clipirea etc.). cell Cu cel mai vechi CGA (Adaptor grafic color), fiecare celulă de text era de obicei o matrice de 8×8 pixeli (deși unii adaptori ar putea folosi în mod eficient 8×14 sau 9×14 pentru EGA, și 9×16 pentru VGA). Pentru VGA standard în modul text 80×25, fiecare celulă de caractere este adesea de 9 pixeli lățime și 16 pixeli înălțime (deși gliful real ar putea ocupa doar 8 pixeli lățime, cu coloana a 9-a utilizată pentru spațiu sau alte caracteristici). Dacă luați în considerare modul tipic de text VGA de celule de caractere 9×16 în 80×25, rezoluția totală a ecranului în termeni de pixeli bruți este 720×400 (80 coloane × 9 pixeli lățime, 25 rânduri × 16 pixeli înălțime). în Modul 03h, fiecare caracter este stocat în RAM video (la ES:DI B800h:0000h) cu un Byte pentru caracterul Index (00h - FFh) și un alt byte pentru definirea culorii de fundal și de fundal (0-F pentru fundal și 0-F pentru foreground). Cum să ? Există momente când poate doriți să mergeți dincolo de aspectul de text-mod implicit. Poate doriți să afișați propriile simboluri sau să deveniți creativi cu grafica ASCII. În mediile DOS și alte medii de nivel scăzut, aveți o capacitate uimitoare de a rupe direct memoria BIOS sau VGA pentru a defini modul în care arată pixelii fiecărui personaj. Vom folosi întreruperea BIOS 10h cu AL = 11h pentru a încărca fontul nostru particularizat. Pas cu pas Mai întâi, să clonăm din nou mediul nostru de pornire, astfel încât să puteți urmări: git clone git@github.com:MilesTails01/i8086_boilercode.git După descărcare, trebuie să deconectați DOSBOX.zip și TOOLS.zip cd \bin tar -xf TOOLS.zip tar -xf DOSBOX.zip build.bat // Compile, Link and Start the source debug.bat // Starts AFDEBUG and loads the compiled exe start.bat // Start the program without rebuilding it Eliminați orice nu este necesar. Păstrați codul simplu și începeți cu minimul ; ################################# ; # ASCII.ASM # ; ################################# ; ################################# ; # STACK # ; ################################# STACK SEGMENT PARA STACK db 256 dup(0) STACK ENDS ; ################################# ; # DATA # ; ################################# DATA SEGMENT PARA 'DATA' DATA ENDS ; ################################# ; # CODE # ; ################################# CODE SEGMENT PARA 'CODE' ASSUME cs:CODE, ds:DATA, ss:STACK mov ax, DATA mov ds, ax mov ax, STACK mov ss, ax mov sp, 256 CODE ENDS Pasul 1 Să definim mai întâi datele noastre de caracter pixel. va deveni culoarea de fundal și va deveni culoarea de fundal. Păstrați în minte în mod normal 80x25 dimensiunea pentru un caracter sunt 9x16. Vom defini 14 rânduri fiecare rând care conține 8bit cauza (păstrați în minte pentru a face al 9-lea bit 0 cauza db este limitat la 1 byte). Acest caracter va fi bloc de bandă dacă vă întrebați ce va arăta mai târziu. 0 1 CHAR_DATA db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b Pasul 2 Să definim o funcție de imprimare pentru a umple întregul ecran cu caracterul A PRINT PROC NEAR mov ax, 0B800h ; VGA text mode memory segment mov es, ax mov di, 0 ; Start at the top-left of the screen mov cx, 2000 ; 80x25 screen = 2000 characters mov al, 'A' ; ASCII code for 'A' mov ah, 19h ; Attribute byte (blue on white) rep stosw ; Fill screen with 'A' ret PRINT ENDP Pasul 3 Acum partea importantă: vom folosi interrupt 10h (Bios Interrupt) cu AH setat la 11h. Am scris definiția parametrului pentru AX, BX, CX, DX și BP în comentarii. REPLACE_ASCII PROC NEAR ; mov ax, 03h ; Set video mode to text mode (80x25, color) ; int 10h ; 9x16 font size ; ; mov ax, 1112h ; Force 8x8 font size for character cells ; xor bl, bl ; RAM block ; int 10h ; Change text mode character (int 10h) ; AH = 11h ; BH = Number of bytes per character ; CX = Number of characters to change ; DX = Starting character to change ; ES:BP = Offset of character data push ds pop es ; make sure es = ds lea bp, CHAR_DATA ; Pointer to custom font data mov ax, 1100h ; Load user-defined font mov bh, 0Eh ; Number of bytes per character xor bl,bl ; RAM block mov cx, 01h ; Number of characters to replace = 1 for now mov dx, 41h ; Starting character to change (41h = 'A' in ASCII) int 10h ; Call BIOS to load the font ret REPLACE_ASCII ENDP Pasul 4 Opțional: Dacă doriți, puteți imprima tabelul ASCII curent în mijlocul ecranului ;) ASCIIPRINT PROC NEAR mov ax, 0B800h ; VGA text mode memory segment mov es, ax xor di, di ; Reset offset mov cx, 5 ; Total number of characters (0-255) mov ah, 4Fh ; Attribute byte (red on white) mov dl, 10 ; Padding on the left (adjust as needed) mov dh, 60 ; Total width of the centered line (adjust as needed) mov di, 1620 ; Row (10 x 80 + padding) * 2, starting with left padding PrintLoop: stosw ; Store the character (AL) and attribute (AH) inc al ; Move to the next ASCII character dec dh ; Decrement width counter jnz PrintLoop ; Continue until row width is filled add di, 40 ; Move to the next row with padding ((80 - 60) * 2) mov dh, 60 ; Reset row width loop PrintLoop ; Repeat for all 256 characters ret ASCIIPRINT ENDP Rezultatul Fiecare personaj din A a fost înlocuit cu noul bloc cu dungi. Acest Glyph va fi foarte util într-un articol ulterior. Codul complet ; ################################# ; # ASCII.ASM # ; ################################# ; ################################# ; # STACK # ; ################################# STACK SEGMENT PARA STACK db 256 dup(0) STACK ENDS ; ################################# ; # DATA # ; ################################# DATA SEGMENT PARA 'DATA' CHAR_DATA db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b db 010101010b DATA ENDS ; ################################# ; # CODE # ; ################################# CODE SEGMENT PARA 'CODE' ASSUME cs:CODE, ds:DATA, ss:STACK mov ax, DATA mov ds, ax mov ax, STACK mov ss, ax mov sp, 256 ; ################################# ; # MAIN # ; ################################# call REPLACE_ASCII call PRINT call ASCIIPRINT ret ; ============================= ; | FUNCTIONS | ; ============================= PUBLIC REPLACE_ASCII REPLACE_ASCII PROC NEAR ; mov ax, 03h ; Set video mode to text mode (80x25, color) ; int 10h ; 9x16 font size ; ; mov ax, 1112h ; Force 8x8 font size for character cells ; xor bl, bl ; RAM block ; int 10h ; Change text mode character (int 10h) ; AH = 11h ; BH = Number of bytes per character ; CX = Number of characters to change ; DX = Starting character to change ; ES:BP = Offset of character data push ds pop es ; make sure es = ds lea bp, CHAR_DATA ; Pointer to custom font data mov ax, 1100h ; Load user-defined font mov bh, 0Eh ; Number of bytes per character xor bl,bl ; RAM block mov cx, 01h ; Number of characters to replace = 1 for now mov dx, 41h ; Starting character to change (41h = 'A' in ASCII) int 10h ; Call BIOS to load the font ret REPLACE_ASCII ENDP PRINT PROC NEAR mov ax, 0B800h ; VGA text mode memory segment mov es, ax mov di, 0 ; Start at the top-left of the screen mov cx, 2000 ; 80x25 screen = 2000 characters mov al, 'A' ; ASCII code for 'A' mov ah, 19h ; Attribute byte (blue on white) rep stosw ; Fill screen with 'A' ret PRINT ENDP ASCIIPRINT PROC NEAR mov ax, 0B800h ; VGA text mode memory segment mov es, ax xor di, di ; Reset offset mov cx, 5 ; Total number of characters (0-255) mov ah, 4Fh ; Attribute byte (red on white) mov dl, 10 ; Padding on the left (adjust as needed) mov dh, 60 ; Total width of the centered line (adjust as needed) mov di, 1620 ; Row (10 x 80 + padding) * 2, starting with left padding PrintLoop: stosw ; Store the character (AL) and attribute (AH) inc al ; Move to the next ASCII character dec dh ; Decrement width counter jnz PrintLoop ; Continue until row width is filled add di, 40 ; Move to the next row with padding ((80 - 60) * 2) mov dh, 60 ; Reset row width loop PrintLoop ; Repeat for all 256 characters ret ASCIIPRINT ENDP CODE ENDS END